1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 __doc__ = """PBUtil
19 Base classes handy for use with PB clients.
20 """
21
22 import logging
23 zenlog = logging.getLogger("zen.pbclientfactory")
24
25 from twisted.spread import pb
26
27 from twisted.spread.pb import PBClientFactory
28 from twisted.internet import protocol
29 from twisted.python import log
30
33 """Reconnecting client factory for PB brokers.
34
35 Like PBClientFactory, but if the connection fails or is lost, the factory
36 will attempt to reconnect.
37
38 Instead of using f.getRootObject (which gives a Deferred that can only
39 be fired once), override the gotRootObject method.
40
41 Instead of using the newcred f.login (which is also one-shot), call
42 f.startLogin() with the credentials and client, and override the
43 gotPerspective method.
44
45 Instead of using the oldcred f.getPerspective (also one-shot), call
46 f.startGettingPerspective() with the same arguments, and override
47 gotPerspective.
48
49 gotRootObject and gotPerspective will be called each time the object is
50 received (once per successful connection attempt). You will probably want
51 to use obj.notifyOnDisconnect to find out when the connection is lost.
52
53 If an authorization error occurs, failedToGetPerspective() will be
54 invoked.
55
56 To use me, subclass, then hand an instance to a connector (like
57 TCPClient).
58 """
59 __pychecker__='no-override'
60
61
62
63 maxDelay = 300
64
66 PBClientFactory.__init__(self)
67 self._doingLogin = False
68 self._doingGetPerspective = False
69
71 PBClientFactory.clientConnectionFailed(self, connector, reason)
72
73
74
75 if self.continueTrying:
76 self.connector = connector
77 self.retry()
78
84
93
95
96 d = self.__dict__.copy()
97 d['connector'] = None
98 d['_callID'] = None
99 return d
100
101
102
104 raise RuntimeError( "getPerspective is one-shot: use startGettingPerspective instead" )
105
108 self._doingGetPerspective = True
109 if perspectiveName == None:
110 perspectiveName = username
111 self._oldcredArgs = (username, password, serviceName,
112 perspectiveName, client)
113
115
116 (username, password,
117 serviceName, perspectiveName, client) = self._oldcredArgs
118 d = self._cbAuthIdentity(root, username, password)
119 d.addCallback(self._cbGetPerspective,
120 serviceName, perspectiveName, client)
121 d.addCallbacks(self.gotPerspective, self.failedToGetPerspective)
122
123
124
125
126 - def login(self, credentials, client=None):
127 from Products.ZenUtils.Utils import unused
128 unused(credentials, client)
129 raise RuntimeError( "Login is one-shot: use startLogin instead" )
130
132 self._credentials = credentials
133 self._client = client
134 self._doingLogin = True
135
142
143
144
145
147 """The remote avatar or perspective (obtained each time this factory
148 connects) is now available."""
149 pass
150
152 """The remote root object (obtained each time this factory connects)
153 is now available. This method will be called each time the connection
154 is established and the object reference is retrieved."""
155 pass
156
158 """The login process failed, most likely because of an authorization
159 failure (bad password), but it is also possible that we lost the new
160 connection before we managed to send our credentials.
161 """
162 log.msg("ReconnectingPBClientFactory.failedToGetPerspective")
163 if why.check(pb.PBConnectionLost):
164 log.msg("we lost the brand-new connection")
165
166 return
167
168 self.stopTrying()
169 if why.type == 'twisted.cred.error.UnauthorizedLogin':
170 zenlog.critical("zenhub username/password combination is incorrect!")
171
172 else:
173 zenlog.critical("Unknown connection problem to zenhub %s", why.type)
174 log.err(why)
175