changeset 119:430c518ebb14

* More logging in master and slave about the build status. * The model classes do cascading deletion now.
author cmlenz
date Mon, 08 Aug 2005 14:24:56 +0000
parents 77dd69f7c405
children b63ed684c29c
files bitten/master.py bitten/model.py bitten/slave.py bitten/store.py bitten/tests/store.py
diffstat 5 files changed, 43 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/bitten/master.py
+++ b/bitten/master.py
@@ -123,11 +123,6 @@
             build.status = Build.PENDING
             build.update(db=db)
         for build in Build.select(self.env, status=Build.PENDING, db=db):
-            for step in BuildStep.select(self.env, build=build.id, db=db):
-                for log in BuildLog.select(self.env, build=build.id,
-                                           step=step.name, db=db):
-                    log.delete(db=db)
-                step.delete(db=db)
             build.delete(db=db)
         db.commit()
 
@@ -337,7 +332,8 @@
                  self.name, build.id, build.config, build.rev)
 
     def _build_step_completed(self, db, build, elem):
-        log.debug('Slave completed step "%s"', elem.attr['id'])
+        log.debug('Slave completed step "%s" with status %s', elem.attr['id'],
+                  elem.attr['result'])
         step = BuildStep(self.env, build=build.id, name=elem.attr['id'],
                          description=elem.attr.get('description'))
         step.started = int(_parse_iso_datetime(elem.attr['time']))
@@ -365,8 +361,9 @@
             store.store_report(build, step, report)
 
     def _build_completed(self, db, build, elem):
-        log.info('Slave %s completed build %d ("%s" as of [%s])', self.name,
-                 build.id, build.config, build.rev)
+        log.info('Slave %s completed build %d ("%s" as of [%s]) with status %s',
+                 self.name, build.id, build.config, build.rev,
+                 elem.attr['result'])
         build.stopped = int(_parse_iso_datetime(elem.attr['time']))
         if elem.attr['result'] == 'failure':
             build.status = Build.FAILURE
--- a/bitten/model.py
+++ b/bitten/model.py
@@ -307,8 +307,13 @@
 
         assert self.status == self.PENDING, 'Only pending builds can be deleted'
 
+        for step in BuildStep.select(self.env, build=self.id):
+            step.delete(db=db)
+
         cursor = db.cursor()
+        cursor.execute("DELETE FROM bitten_slave WHERE build=%s", (self.id,))
         cursor.execute("DELETE FROM bitten_build WHERE id=%s", (self.id,))
+
         if handle_ta:
             db.commit()
 
@@ -455,6 +460,9 @@
         else:
             handle_ta = False
 
+        for log in BuildLog.select(self.env, build=self.build, step=self.name):
+            log.delete(db=db)
+
         cursor = db.cursor()
         cursor.execute("DELETE FROM bitten_step WHERE build=%s AND name=%s",
                        (self.build, self.name))
@@ -558,9 +566,9 @@
             handle_ta = False
 
         cursor = db.cursor()
-        cursor.execute("DELETE FROM bitten_log WHERE id=%s", (self.id,))
         cursor.execute("DELETE FROM bitten_log_message WHERE log=%s",
                        (self.id,))
+        cursor.execute("DELETE FROM bitten_log WHERE id=%s", (self.id,))
 
         if handle_ta:
             db.commit()
--- a/bitten/slave.py
+++ b/bitten/slave.py
@@ -156,8 +156,10 @@
                     for type, function, output in step.execute(recipe.ctxt):
                         xmlio.SubElement(xml, type, type=function)[output]
                     xml.attr['duration'] = (datetime.utcnow() - started).seconds
+                    log.info('Build step %s completed successfully', step.id)
                     self.channel.send_ans(msgno, beep.Payload(xml))
                 except (BuildError, InvalidRecipeError), e:
+                    log.warning('Build step %s failed: %s', step.id, e)
                     duration = datetime.utcnow() - started
                     failed = True
                     xml = xmlio.Element('step', id=step.id, result='failure',
@@ -166,7 +168,10 @@
                                         duration=duration.seconds)[e]
                     self.channel.send_ans(msgno, beep.Payload(xml))
 
-            log.info('Build completed')
+            if failed:
+                log.warning('Build failed')
+            else:
+                log.info('Build completed successfully')
             xml = xmlio.Element('completed', time=datetime.utcnow().isoformat(),
                                 result=['success', 'failure'][failed])
             self.channel.send_ans(msgno, beep.Payload(xml))
--- a/bitten/store.py
+++ b/bitten/store.py
@@ -27,7 +27,7 @@
 log = logging.getLogger('bitten.store')
 
 
-class IReportStore(Interface):
+class IReportStoreBackend(Interface):
 
     def store_report(build, step, xml):
         """Store the given report."""
@@ -38,22 +38,25 @@
 
 class ReportStore(Component):
 
-    backends = ExtensionPoint(IReportStore)
+    backends = ExtensionPoint(IReportStoreBackend)
 
-    def _get_backend(self):
-        configured = self.config.get('bitten', 'report_store', 'BDBXMLStore')
+    def store_report(self, build, step, xml):
+        assert xml.name == 'report' and 'type' in xml.attr
+        backend = self._get_configured_backend()
+        log.debug('Storing report of type "%s" in %s', xml.attr['type'],
+                  backend.__class__.__name__)
+        backend.store_report(build, step, xml)
+
+    def retrieve_reports(self, build, step, type=None):
+        backend = self._get_configured_backend()
+        return backend.retrieve_reports(build, step, type)
+
+    def _get_configured_backend(self):
+        configured = self.config.get('bitten', 'report_store', 'BDBXMLBackend')
         for backend in self.backends:
             if backend.__class__.__name__ == configured:
                 return backend
-        raise TracError, 'No report store backend available'
-    backend = property(fget=lambda self: self._get_backend())
-
-    def store_report(self, build, step, xml):
-        assert xml.name == 'report' and 'type' in xml.attr
-        self.backend.store_report(build, step, xml)
-
-    def retrieve_reports(self, build, step, type=None):
-        return self.backend.retrieve_reports(build, step, type)
+        raise TracError, 'Report store backend not available'
 
 
 try:
@@ -62,8 +65,8 @@
     dbxml = None
 
 
-class BDBXMLStore(Component):
-    implements(IReportStore)
+class BDBXMLBackend(Component):
+    implements(IReportStoreBackend)
 
     indexes = [
         ('build', 'node-metadata-equality-decimal'),
@@ -127,7 +130,7 @@
         query += "]"
         results = mgr.query(query, ctxt)
         for value in results:
-            yield BDBXMLStore.XmlValueWrapper(value)
+            yield BDBXMLBackend.XmlValueWrapper(value)
 
     def _open_container(self, mgr, create=False):
         if create and not os.path.exists(self.path):
--- a/bitten/tests/store.py
+++ b/bitten/tests/store.py
@@ -24,11 +24,11 @@
 import unittest
 
 from trac.test import EnvironmentStub, Mock
-from bitten.store import BDBXMLStore
+from bitten.store import BDBXMLBackend
 from bitten.util import xmlio
 
 
-class BDBXMLStoreTestCase(unittest.TestCase):
+class BDBXMLBackendTestCase(unittest.TestCase):
 
     def setUp(self):
         self.env = EnvironmentStub()
@@ -39,7 +39,7 @@
         shutil.rmtree(self.env.path)
 
     def test_store_report(self):
-        store = BDBXMLStore(self.env)
+        store = BDBXMLBackend(self.env)
         build = Mock(id=42)
         step = Mock(name='foo')
         xml = xmlio.Element('report', type='test')[xmlio.Element('dummy')]
@@ -63,4 +63,4 @@
 
 
 def suite():
-    return unittest.makeSuite(BDBXMLStoreTestCase, 'test')
+    return unittest.makeSuite(BDBXMLBackendTestCase, 'test')
Copyright (C) 2012-2017 Edgewall Software