changeset 199:9cabfdbdb8e0

* Improve error handling in the snapshot archive packing/unpacking code. Specificially, when a build slave fails to unpack a snapshot it received from the master, it'll report the error back to the master (and thereby reject the build request), instead of just bailing and leaving the master waiting for a reply. * Host names of slaves are now lower-cased (some windows machines would report the host all upper-case). * Minor fixes to some of the recipe commands.
author cmlenz
date Wed, 14 Sep 2005 18:52:12 +0000
parents 6bb8e7a18072
children 692924ffed80
files bitten/build/ctools.py bitten/build/shtools.py bitten/slave.py bitten/util/archive.py
diffstat 4 files changed, 59 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/bitten/build/ctools.py
+++ b/bitten/build/ctools.py
@@ -14,13 +14,11 @@
 
 log = logging.getLogger('bitten.build.ctools')
 
-def make(ctxt, target=None, file_=None, jobs=None, keep_going=False):
+def make(ctxt, target=None, file_=None, keep_going=False):
     """Execute a Makefile target."""
     args = ['--directory', ctxt.basedir]
     if file_:
         args += ['--file', ctxt.resolve(file_)]
-    if jobs:
-        args += ['--jobs', int(jobs)]
     if keep_going:
         args.append('--keep-going')
     if target:
--- a/bitten/build/shtools.py
+++ b/bitten/build/shtools.py
@@ -61,7 +61,8 @@
 def pipe(ctxt, executable=None, file_=None, input_=None, output=None,
          args=None):
     """Pipe the contents of a file through a script."""
-    assert file_, 'Missing required attribute "file"'
+    assert executable or file_, \
+        'Either "executable" or "file" attribute required'
     assert input_, 'Missing required attribute "file"'
 
     if args:
--- a/bitten/slave.py
+++ b/bitten/slave.py
@@ -66,7 +66,7 @@
         if self.session.name is not None:
             node = self.session.name
         else:
-            node = node.split('.', 1)[0]
+            node = node.split('.', 1)[0].lower()
 
         packages = []
         if self.session.config is not None:
@@ -137,9 +137,18 @@
             log.debug('Received snapshot archive: %s', archive_path)
 
             # Unpack the archive
-            prefix = archive.unpack(archive_path, workdir)
-            path = os.path.join(workdir, prefix)
-            log.debug('Unpacked snapshot to %s' % path)
+            try:
+                prefix = archive.unpack(archive_path, workdir)
+                path = os.path.join(workdir, prefix)
+                log.debug('Unpacked snapshot to %s' % path)
+            except archive.Error, e:
+                xml = xmlio.Element('error', code=550)[
+                    'Could not unpack archive (%s)' % e
+                ]
+                self.channel.send_err(msgno, beep.Payload(xml))
+                log.error('Could not unpack archive %s: %s', archive_path, e,
+                          exc_info=True)
+                return
 
             # Fix permissions
             for root, dirs, files in os.walk(workdir, topdown=False):
@@ -151,7 +160,6 @@
             self.execute_build(msgno, Recipe(self.recipe_xml, path))
 
     def execute_build(self, msgno, recipe):
-        global log
         log.info('Building in directory %s', recipe.ctxt.basedir)
         try:
             if not self.session.dry_run:
--- a/bitten/util/archive.py
+++ b/bitten/util/archive.py
@@ -15,6 +15,9 @@
 _formats = {'gzip': ('.tar.gz', 'gz'), 'bzip2': ('.tar.bz2', 'bz2'),
             'zip': ('.zip', None)}
 
+class Error(Exception):
+    """Error raised when packing or unpacking a snapshot archive fails."""
+
 def index(env, prefix):
     """Generator that yields `(rev, format, path)` tuples for every archive in
     the environment snapshots directory that match the specified prefix.
@@ -45,13 +48,14 @@
         repos = env.get_repository()
     root = repos.get_node(path or '/', rev)
     if not root.isdir:
-        raise Exception, '"%s" is not a directory' % path
+        raise Error, '"%s" is not a directory' % path
 
-    assert format in _formats, 'Unknown archive format: %s' % format
+    if format not in _formats:
+        raise Error, 'Unknown archive format: %s' % format
 
     filedir = os.path.join(env.path, 'snapshots')
     if not os.access(filedir, os.R_OK + os.W_OK):
-        raise IOError, 'Insufficient permissions to create tarball'
+        raise Error, 'Insufficient permissions to create tarball'
     if not prefix:
         prefix = root.path.replace('/', '-')
     prefix += '_r%s' % root.rev
@@ -73,17 +77,23 @@
             for entry in node.get_entries():
                 _add_entry(entry)
         elif format in ('bzip2', 'gzip'):
-            info = tarfile.TarInfo(os.path.join(prefix, name))
-            info.type = tarfile.REGTYPE
-            info.mtime = node.last_modified
-            info.size = node.content_length
-            archive.addfile(info, node.get_content())
+            try:
+                info = tarfile.TarInfo(os.path.join(prefix, name))
+                info.type = tarfile.REGTYPE
+                info.mtime = node.last_modified
+                info.size = node.content_length
+                archive.addfile(info, node.get_content())
+            except tarfile.TarError, e:
+                raise Error, e
         else: # ZIP format
-            info = zipfile.ZipInfo(os.path.join(prefix, name))
-            info.compress_type = zipfile.ZIP_DEFLATED
-            info.date_time = time.gmtime(node.last_modified)[:6]
-            info.file_size = node.content_length
-            archive.writestr(info, node.get_content().read())
+            try:
+                info = zipfile.ZipInfo(os.path.join(prefix, name))
+                info.compress_type = zipfile.ZIP_DEFLATED
+                info.date_time = time.gmtime(node.last_modified)[:6]
+                info.file_size = node.content_length
+                archive.writestr(info, node.get_content().read())
+            except zipfile.error, e:
+                raise Error, e
     _add_entry(root)
 
     archive.close()
@@ -98,22 +108,28 @@
                 format = name
                 break
         if not format:
-            raise Exception, 'Unkown archive extension: %s' \
-                             % os.path.splitext(filename)[1]
+            raise Error, 'Unkown archive extension: %s' \
+                         % os.path.splitext(filename)[1]
 
     names = []
     if format in ('bzip2', 'gzip'):
-        tar_file = tarfile.open(filename)
-        for tarinfo in tar_file:
-            names.append(tarinfo.name)
-            tar_file.extract(tarinfo, dest_path)
+        try:
+            tar_file = tarfile.open(filename)
+            for tarinfo in tar_file:
+                names.append(tarinfo.name)
+                tar_file.extract(tarinfo, dest_path)
+        except tarfile.TarError, e:
+            raise Error, e
     elif format == 'zip':
-        zip_file = zipfile.ZipFile(filename, 'r')
-        for name in zip_file.namelist():
-            names.append(name)
-            path = os.path.join(dest_path, name)
-            if name.endswith('/'):
-                os.makedirs(path)
-            else:
-                file(path, 'wb').write(zip_file.read(name))
+        try:
+            zip_file = zipfile.ZipFile(filename, 'r')
+            for name in zip_file.namelist():
+                names.append(name)
+                path = os.path.join(dest_path, name)
+                if name.endswith('/'):
+                    os.makedirs(path)
+                else:
+                    file(path, 'wb').write(zip_file.read(name))
+        except zipfile.error:
+            raise Error, e
     return os.path.commonprefix(names)
Copyright (C) 2012-2017 Edgewall Software