changeset 494:9c9bf7a69bf0

Apply patch by Emmanuel Blot to allow a single slave to connect to multiple masters. Closes #271.
author cmlenz
date Tue, 08 Jul 2008 15:17:16 +0000
parents f10da0985227
children 7e9a60417cb3
files bitten/master.py bitten/slave.py
diffstat 2 files changed, 26 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/bitten/master.py
+++ b/bitten/master.py
@@ -198,8 +198,10 @@
         stepname = elem.attr['step']
 	
         # make sure it's the right slave.
-        if build.status != Build.IN_PROGRESS or build.slave_info.get(Build.IP_ADDRESS) != req.remote_addr:
-            raise HTTPForbidden('Build %s has been invalidated for host %s.' % (build.id, req.remote_addr))
+        if build.status != Build.IN_PROGRESS or \
+                build.slave_info.get(Build.IP_ADDRESS) != req.remote_addr:
+            raise HTTPForbidden('Build %s has been invalidated for host %s.'
+                                % (build.id, req.remote_addr))
 
         step = BuildStep.fetch(self.env, build=build.id, name=stepname)
         if step:
@@ -216,8 +218,9 @@
             raise HTTPForbidden('No such build step')
         last_step = index == num
 
-        self.log.debug('Slave %s (build %d) completed step %d (%s) with status %s',
-                       build.slave, build.id, index, stepname, elem.attr['status'])
+        self.log.debug('Slave %s (build %d) completed step %d (%s) with '
+                       'status %s', build.slave, build.id, index, stepname,
+                       elem.attr['status'])
 
         db = self.env.get_db_cnx()
 
--- a/bitten/slave.py
+++ b/bitten/slave.py
@@ -68,15 +68,16 @@
 class BuildSlave(object):
     """BEEP initiator implementation for the build slave."""
 
-    def __init__(self, url, name=None, config=None, dry_run=False,
+    def __init__(self, urls, name=None, config=None, dry_run=False,
                  work_dir=None, build_dir="build_${build}",
                  keep_files=False, single_build=False,
                  poll_interval=300, username=None, password=None,
                  dump_reports=False):
         """Create the build slave instance.
         
-        :param url: the URL of the build master, or the path to a build recipe
-                    file
+        :param urls: a list of URLs of the build masters to connect to, or a
+                     single-element list containing the path to a build recipe
+                     file
         :param name: the name with which this slave should identify itself
         :param config: the path to the slave configuration file
         :param dry_run: wether the build outcome should not be reported back
@@ -97,8 +98,9 @@
                              standard output, in addition to being transmitted
                              to the build master
         """
-        self.url = url
-        self.local = not url.startswith('http') and not url.startswith('https')
+        self.urls = urls
+        self.local = len(urls) == 1 and not urls[0].startswith('http://') \
+                                    and not urls[0].startswith('https://')
         if name is None:
             name = platform.node().split('.', 1)[0].lower()
         self.name = name
@@ -120,7 +122,7 @@
             password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
             if username and password:
                 log.debug('Enabling authentication with username %r', username)
-                password_mgr.add_password(None, url, username, password)
+                password_mgr.add_password(None, urls, username, password)
             self.opener.add_handler(urllib2.HTTPBasicAuthHandler(password_mgr))
             self.opener.add_handler(urllib2.HTTPDigestAuthHandler(password_mgr))
 
@@ -137,17 +139,21 @@
 
     def run(self):
         if self.local:
-            fileobj = open(self.url)
+            fileobj = open(self.urls[0])
             try:
                 self._execute_build(None, fileobj)
             finally:
                 fileobj.close()
             return os.EX_OK
 
+        urls = []
         while True:
+            if not urls:
+                urls[:] = self.urls
+            url = urls.pop(0)
             try:
                 try:
-                    job_done = self._create_build()
+                    job_done = self._create_build(url)
                     if job_done:
                         continue
                 except urllib2.HTTPError, e:
@@ -171,7 +177,7 @@
         log.info('Shutting down')
         raise ExitSlave(os.EX_OK)
 
-    def _create_build(self):
+    def _create_build(self, url):
         xml = xmlio.Element('slave', name=self.name)[
             xmlio.Element('platform', processor=self.config['processor'])[
                 self.config['machine']
@@ -188,7 +194,7 @@
 
         body = str(xml)
         log.debug('Sending slave configuration: %s', body)
-        resp = self.request('POST', self.url, body, {
+        resp = self.request('POST', url, body, {
             'Content-Length': len(body),
             'Content-Type': 'application/x-bitten+xml'
         })
@@ -313,7 +319,7 @@
     from bitten import __version__ as VERSION
     from optparse import OptionParser
 
-    parser = OptionParser(usage='usage: %prog [options] url',
+    parser = OptionParser(usage='usage: %prog [options] url1 [url2] ...',
                           version='%%prog %s' % VERSION)
     parser.add_option('--name', action='store', dest='name',
                       help='name of this slave (defaults to host name)')
@@ -358,7 +364,7 @@
 
     if len(args) < 1:
         parser.error('incorrect number of arguments')
-    url = args[0]
+    urls = args
 
     logger = logging.getLogger('bitten')
     logger.setLevel(options.loglevel)
@@ -375,7 +381,7 @@
         handler.setFormatter(formatter)
         logger.addHandler(handler)
 
-    slave = BuildSlave(url, name=options.name, config=options.config,
+    slave = BuildSlave(urls, name=options.name, config=options.config,
                        dry_run=options.dry_run, work_dir=options.work_dir,
                        build_dir=options.build_dir,
                        keep_files=options.keep_files,
Copyright (C) 2012-2017 Edgewall Software