Package buildslave :: Module pbutil
[frames] | no frames]

Source Code for Module buildslave.pbutil

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16   
 17  """Base classes handy for use with PB clients. 
 18  """ 
 19   
 20  from twisted.spread import pb 
 21   
 22  from twisted.spread.pb import PBClientFactory 
 23  from twisted.internet import protocol, reactor 
 24  from twisted.python import log 
 25  from twisted.cred import error 
 26   
27 -class ReconnectingPBClientFactory(PBClientFactory, 28 protocol.ReconnectingClientFactory):
29 """Reconnecting client factory for PB brokers. 30 31 Like PBClientFactory, but if the connection fails or is lost, the factory 32 will attempt to reconnect. 33 34 Instead of using f.getRootObject (which gives a Deferred that can only 35 be fired once), override the gotRootObject method. 36 37 Instead of using the newcred f.login (which is also one-shot), call 38 f.startLogin() with the credentials and client, and override the 39 gotPerspective method. 40 41 gotRootObject and gotPerspective will be called each time the object is 42 received (once per successful connection attempt). You will probably want 43 to use obj.notifyOnDisconnect to find out when the connection is lost. 44 45 If an authorization error occurs, failedToGetPerspective() will be 46 invoked. 47 48 To use me, subclass, then hand an instance to a connector (like 49 TCPClient). 50 """ 51 52 # hung connections wait for a relatively long time, since a busy master may 53 # take a while to get back to us. 54 hungConnectionTimer = None 55 HUNG_CONNECTION_TIMEOUT = 120 56
57 - def clientConnectionFailed(self, connector, reason):
58 PBClientFactory.clientConnectionFailed(self, connector, reason) 59 if self.continueTrying: 60 self.connector = connector 61 self.retry()
62
63 - def clientConnectionLost(self, connector, reason):
64 PBClientFactory.clientConnectionLost(self, connector, reason, 65 reconnecting=True) 66 RCF = protocol.ReconnectingClientFactory 67 RCF.clientConnectionLost(self, connector, reason)
68
69 - def startedConnecting(self, connector):
71
72 - def clientConnectionMade(self, broker):
73 self.resetDelay() 74 PBClientFactory.clientConnectionMade(self, broker) 75 self.doLogin(self._root, broker) 76 self.gotRootObject(self._root)
77 78 # newcred methods 79
80 - def login(self, *args):
81 raise RuntimeError, "login is one-shot: use startLogin instead"
82
83 - def startLogin(self, credentials, client=None):
84 self._credentials = credentials 85 self._client = client
86
87 - def doLogin(self, root, broker):
88 # newcred login() 89 d = self._cbSendUsername(root, self._credentials.username, 90 self._credentials.password, self._client) 91 d.addCallbacks(self.gotPerspective, self.failedToGetPerspective, 92 errbackArgs=(broker,))
93 94 # timer for hung connections 95
96 - def startHungConnectionTimer(self, connector):
97 self.stopHungConnectionTimer() 98 def hungConnection(): 99 log.msg("connection attempt timed out (is the port number correct?)") 100 self.hungConnectionTimer = None 101 connector.disconnect()
102 # (this will trigger the retry) 103 self.hungConnectionTimer = reactor.callLater(self.HUNG_CONNECTION_TIMEOUT, hungConnection)
104
105 - def stopHungConnectionTimer(self):
106 if self.hungConnectionTimer: 107 self.hungConnectionTimer.cancel() 108 self.hungConnectionTimer = None
109 110 # methods to override 111
112 - def gotPerspective(self, perspective):
113 """The remote avatar or perspective (obtained each time this factory 114 connects) is now available.""" 115 self.stopHungConnectionTimer()
116
117 - def gotRootObject(self, root):
118 """The remote root object (obtained each time this factory connects) 119 is now available. This method will be called each time the connection 120 is established and the object reference is retrieved.""" 121 self.stopHungConnectionTimer()
122
123 - def failedToGetPerspective(self, why, broker):
124 """The login process failed, most likely because of an authorization 125 failure (bad password), but it is also possible that we lost the new 126 connection before we managed to send our credentials. 127 """ 128 log.msg("ReconnectingPBClientFactory.failedToGetPerspective") 129 self.stopHungConnectionTimer() 130 # put something useful in the logs 131 if why.check(pb.PBConnectionLost): 132 log.msg("we lost the brand-new connection") 133 # fall through 134 elif why.check(error.UnauthorizedLogin): 135 log.msg("unauthorized login; check slave name and password") 136 # fall through 137 else: 138 log.err(why, 'While trying to connect:') 139 self.stopTrying() 140 reactor.stop() 141 return 142 143 # lose the current connection, which will trigger a retry 144 broker.transport.loseConnection()
145