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: 7162 $"
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
61 - def __init__(self, host, filename, info):
68
71
72
81
82
84 """
85 Returns if we have at least one recent connection
86 @returns: if we have a recent connection
87 @rtype: bool
88 """
89 gen = _getRecentFilenames()
90 try:
91 gen.next()
92 except StopIteration:
93 return False
94
95 return True
96
97
99 """
100 Fetches a list of recently used connections
101 @returns: recently used connections
102 @rtype: list of L{RecentConnection}
103 """
104
105 def _parseConnection(filename):
106 tree = minidom.parse(filename)
107 state = {}
108 for childNode in tree.documentElement.childNodes:
109 if (childNode.nodeType != Node.TEXT_NODE and
110 childNode.nodeType != Node.COMMENT_NODE):
111 state[childNode.nodeName] = childNode.childNodes[0].wholeText
112 state['port'] = int(state['port'])
113 state['use_insecure'] = (state['use_insecure'] != '0')
114 authenticator = Authenticator(username=state['user'],
115 password=state['passwd'])
116 return PBConnectionInfo(state['host'], state['port'],
117 not state['use_insecure'],
118 authenticator)
119
120 recentFilenames = _getRecentFilenames()
121 recentConnections = []
122 for filename in sorted(recentFilenames, reverse=True):
123 try:
124 state = _parseConnection(filename)
125 recentConnections.append(
126 RecentConnection(str(state),
127 filename=filename,
128 info=state))
129 except Exception, e:
130 log.warning('connections', 'Error parsing %s: %r', filename, e)
131 return recentConnections
132
133
136 """The same as L{flumotion.common.connection.parsePBConnectionInfo},
137 but fills in missing information from the recent connections cache
138 if possible.
139 @param managerString: manager string we should connect to
140 @type managerString: string
141 @param use_ssl: True if we should use ssl
142 @type use_ssl: bool
143 @param defaultPort: default port to use
144 @type defaultPort: int
145 @returns: connection info
146 @rtype: a L{PBConnectionInfo}
147 """
148 recent = getRecentConnections()
149 if not managerString:
150 if recent:
151 return recent[0].info
152 else:
153 raise OptionError('No string given and no recent '
154 'connections to use')
155
156 info = parsePBConnectionInfo(managerString, username=None,
157 password=None,
158 port=defaultPort,
159 use_ssl=use_ssl)
160
161 def compatible(i1, i2):
162 if i1.port and i1.port != i2.port:
163 return False
164 if i1.use_ssl != i2.use_ssl:
165 return False
166 a1, a2 = i1.authenticator, i2.authenticator
167 if a1.username and a1.username != a2.username:
168 return False
169 if a1.password and a1.password != a2.password:
170 return False
171 return True
172
173 if not info.authenticator.username:
174 for c in recent:
175 recent = c.info
176 if compatible(info, recent):
177 info.authenticator.username = recent.authenticator.username
178 info.authenticator.password = recent.authenticator.password
179 break
180 elif not info.authenticator.password:
181 for c in recent:
182 recent = c.info
183 if compatible(info, recent):
184 info.authenticator.password = recent.authenticator.password
185 break
186 if not (info.authenticator.username and info.authenticator.password):
187 raise OptionError('You are connecting to %s for the '
188 'first time; please specify a user and '
189 'password (e.g. user:test@%s).'
190 % (managerString, managerString))
191 else:
192 return info
193