Package Products :: Package ZenUtils :: Module PBUtil
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenUtils.PBUtil

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 or (at your 
  8  # option) any later version as published by the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  # taken from r1.10 of buildbot.sf.net/buildbot/pbutil.py 
 15   
 16  # flumotion has nearly the same code 
 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   
31 -class ReconnectingPBClientFactory(PBClientFactory, 32 protocol.ReconnectingClientFactory):
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 # maxDelay(secs) set to 5 minute maximum delay before attempting to 62 # reconnect 63 maxDelay = 300 64
65 - def __init__(self):
66 PBClientFactory.__init__(self) 67 self._doingLogin = False 68 self._doingGetPerspective = False
69
70 - def clientConnectionFailed(self, connector, reason):
71 PBClientFactory.clientConnectionFailed(self, connector, reason) 72 # Twisted-1.3 erroneously abandons the connection on non-UserErrors. 73 # To avoid this bug, don't upcall, and implement the correct version 74 # of the method here. 75 if self.continueTrying: 76 self.connector = connector 77 self.retry()
78
79 - def clientConnectionLost(self, connector, reason, reconnecting=1):
80 PBClientFactory.clientConnectionLost(self, connector, reason, 81 reconnecting=reconnecting) 82 RCF = protocol.ReconnectingClientFactory 83 RCF.clientConnectionLost(self, connector, reason)
84
85 - def clientConnectionMade(self, broker):
86 self.resetDelay() 87 PBClientFactory.clientConnectionMade(self, broker) 88 if self._doingLogin: 89 self.doLogin(self._root) 90 if self._doingGetPerspective: 91 self.doGetPerspective(self._root) 92 self.gotRootObject(self._root)
93
94 - def __getstate__(self):
95 # this should get folded into ReconnectingClientFactory 96 d = self.__dict__.copy() 97 d['connector'] = None 98 d['_callID'] = None 99 return d
100 101 # oldcred methods 102
103 - def getPerspective(self, *args):
104 raise RuntimeError( "getPerspective is one-shot: use startGettingPerspective instead" )
105
106 - def startGettingPerspective(self, username, password, serviceName, 107 perspectiveName=None, client=None):
108 self._doingGetPerspective = True 109 if perspectiveName == None: 110 perspectiveName = username 111 self._oldcredArgs = (username, password, serviceName, 112 perspectiveName, client)
113
114 - def doGetPerspective(self, root):
115 # oldcred getPerspective() 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 # newcred methods 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
131 - def startLogin(self, credentials, client=None):
132 self._credentials = credentials 133 self._client = client 134 self._doingLogin = True
135
136 - def doLogin(self, root):
137 # newcred login() 138 d = self._cbSendUsername(root, self._credentials.username, 139 self._credentials.password, self._client) 140 d.addCallbacks(self.gotPerspective, self.failedToGetPerspective) 141 return d
142 143 144 # methods to override 145
146 - def gotPerspective(self, perspective):
147 """The remote avatar or perspective (obtained each time this factory 148 connects) is now available.""" 149 pass
150
151 - def gotRootObject(self, root):
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
157 - def failedToGetPerspective(self, why):
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 # retrying might help here, let clientConnectionLost decide 166 return 167 168 self.stopTrying() # logging in harder won't help 169 if why.type == 'twisted.cred.error.UnauthorizedLogin': 170 zenlog.critical("zenhub username/password combination is incorrect!") 171 # Don't exit as Enterprise caches info and can survive 172 else: 173 zenlog.critical("Unknown connection problem to zenhub %s", why.type) 174 log.err(why)
175