1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """recent connections"""
23
24 import datetime
25 import os
26 from xml.dom import minidom, Node
27
28 from flumotion.common import log, common
29 from flumotion.common.connection import PBConnectionInfo, parsePBConnectionInfo
30 from flumotion.common.errors import OptionError
31
32
33
34 __pychecker__ = 'no-shadowbuiltin'
35 from flumotion.common.python import sorted
36 __pychecker__ = ''
37 from flumotion.configure import configure
38 from flumotion.twisted.pb import Authenticator
39
40 __version__ = "$Rev: 7036 $"
41
42
44 """
45 I am an object representing a recent connection.
46 You can access some of my state and update the timestamp
47 (eg, when I was last connected to) by calling L{updateTimestamp}.
48
49 @ivar name: name of the recent connection usually host:port
50 @type name: string
51 @ivar host: hostname
52 @type host: string
53 @ivar filename: filename of the connection
54 @type filename: string
55 @ivar info: connection info
56 @type info: L{PBConnectionInfo}
57 @ivar timestamp: timestamp
58 @type timestamp: datetime.datetime
59 """
60 - def __init__(self, host, filename, info):
67
70
71
80
82 """
83 Returns if we have at least one recent connection
84 @returns: if we have a recent connection
85 @rtype: bool
86 """
87 gen = _getRecentFilenames()
88 try:
89 gen.next()
90 except StopIteration:
91 return False
92
93 return True
94
96 """
97 Fetches a list of recently used connections
98 @returns: recently used connections
99 @rtype: list of L{RecentConnection}
100 """
101 def _parseConnection(filename):
102 tree = minidom.parse(filename)
103 state = {}
104 for childNode in tree.documentElement.childNodes:
105 if (childNode.nodeType != Node.TEXT_NODE and
106 childNode.nodeType != Node.COMMENT_NODE):
107 state[childNode.nodeName] = childNode.childNodes[0].wholeText
108 state['port'] = int(state['port'])
109 state['use_insecure'] = (state['use_insecure'] != '0')
110 authenticator = Authenticator(username=state['user'],
111 password=state['passwd'])
112 return PBConnectionInfo(state['host'], state['port'],
113 not state['use_insecure'],
114 authenticator)
115
116 recentFilenames = _getRecentFilenames()
117 recentConnections = []
118 for filename in sorted(recentFilenames, reverse=True):
119 try:
120 state = _parseConnection(filename)
121 recentConnections.append(
122 RecentConnection(str(state),
123 filename=filename,
124 info=state))
125 except Exception, e:
126 log.warning('connections', 'Error parsing %s: %r', filename, e)
127 return recentConnections
128
131 """The same as L{flumotion.common.connection.parsePBConnectionInfo},
132 but fills in missing information from the recent connections cache
133 if possible.
134 @param managerString: manager string we should connect to
135 @type managerString: string
136 @param use_ssl: True if we should use ssl
137 @type use_ssl: bool
138 @param defaultPort: default port to use
139 @type defaultPort: int
140 @returns: connection info
141 @rtype: a L{PBConnectionInfo}
142 """
143 recent = getRecentConnections()
144 if not managerString:
145 if recent:
146 return recent[0].info
147 else:
148 raise OptionError('No string given and no recent '
149 'connections to use')
150
151 info = parsePBConnectionInfo(managerString, username=None,
152 password=None,
153 port=defaultPort,
154 use_ssl=use_ssl)
155
156 def compatible(i1, i2):
157 if i1.port and i1.port != i2.port:
158 return False
159 if i1.use_ssl != i2.use_ssl:
160 return False
161 a1, a2 = i1.authenticator, i2.authenticator
162 if a1.username and a1.username != a2.username:
163 return False
164 if a1.password and a1.password != a2.password:
165 return False
166 return True
167
168 if not info.authenticator.username:
169 for c in recent:
170 recent = c.info
171 if compatible(info, recent):
172 info.authenticator.username = recent.authenticator.username
173 info.authenticator.password = recent.authenticator.password
174 break
175 elif not info.authenticator.password:
176 for c in recent:
177 recent = c.info
178 if compatible(info, recent):
179 info.authenticator.password = recent.authenticator.password
180 break
181 if not (info.authenticator.username and info.authenticator.password):
182 raise OptionError('You are connecting to %s for the '
183 'first time; please specify a user and '
184 'password (e.g. user:test@%s).'
185 % (managerString, managerString))
186 else:
187 return info
188