--- /dev/null
+"""An object to manage remote calls to a BuildBot PB service."""
+
+from twisted.internet import reactor
+from twisted.spread import pb
+from twisted.cred import credentials
+from twisted.python import log
+
+class BBModel(pb.Referenceable):
+
+ def connect(self, host, port, username, password):
+
+ cf = pb.PBClientFactory()
+ creds = credentials.UsernamePassword(username, password)
+
+ d = cf.login(creds)
+ reactor.connectTCP(host, port, cf)
+
+ d.addCallback(self.connected)
+ d.addErrback(lambda arg: log.err(arg))
+
+ log.msg('connecting to %s:%d as %s' % (host, port, username))
+
+ return d
+
+ def connected(self, ref):
+
+ log.msg('connected')
+
+ self.remote = ref
+ self.remote.notifyOnDisconnect(self.disconnected)
+
+ def disconnected(self, ref):
+
+ log.msg('disconnected')
--- /dev/null
+#!/usr/bin/python
+
+import sys, string
+
+from twisted.internet import reactor
+from twisted.python import log
+
+import bbmodel
+
+# Command line parsing
+
+from optparse import OptionParser
+
+optparser = OptionParser(
+ usage = '%prog HOSTNAME:PORT -u USER -p PASS')
+
+optparser.add_option('-u', '--user', dest = 'user',
+ action = 'store', type = 'string',
+ help = 'user to connect as')
+
+optparser.add_option('-p', '--password', dest = 'password',
+ action = 'store', type = 'string',
+ help = 'password to connect user as')
+
+(opts, argv) = optparser.parse_args()
+
+if len(argv) != 1:
+ optparser.print_usage()
+ sys.exit(1)
+
+if opts.user is None:
+ print 'Username required'
+ optparser.print_usage()
+ sys.exit(1)
+
+if opts.password is None:
+ print 'Password required'
+ optparser.print_usage()
+ sys.exit(1)
+
+host, port = string.split(argv[0], ':')
+
+# Main program
+
+log.startLogging(sys.stdout)
+
+bb = bbmodel.BBModel()
+bb.connect(host, int(port), opts.user, opts.password)
+
+reactor.run()