Add types to backend status messages
[plstackapi.git] / planetstack / openstack_observer / syncstep.py
index fc0cb0b..fd34f55 100644 (file)
@@ -4,13 +4,14 @@ from datetime import datetime
 from planetstack.config import Config
 from util.logger import Logger, logging
 from observer.steps import *
+from django.db.models import F, Q
 
 logger = Logger(level=logging.INFO)
 
 class FailedDependency(Exception):
     pass
 
-class SyncStep:
+class SyncStep(object):
     """ A PlanetStack Sync step. 
 
     Attributes:
@@ -44,15 +45,31 @@ class SyncStep:
         return
 
     def fetch_pending(self, deletion=False):
-        return []
+        # This is the most common implementation of fetch_pending
+        # Steps should override it if they have their own logic
+        # for figuring out what objects are outstanding.
+        main_obj = self.provides[0]
+        if (not deletion):
+            objs = main_obj.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+        else:
+            objs = main_obj.deleted_objects.all()
+
+        return objs
         #return Sliver.objects.filter(ip=None)
     
     def check_dependencies(self, obj, failed):
         for dep in self.dependencies:
             peer_name = dep[0].lower() + dep[1:]    # django names are camelCased with the first letter lower
-            peer_object = getattr(obj, peer_name)
-            if (peer_object.pk==failed.pk):
-                raise FailedDependency
+            try:
+                peer_object = getattr(obj, peer_name)
+            except:
+                peer_object = None
+
+            if (peer_object and peer_object.pk==failed.pk and type(peer_object)==type(failed)):
+                if (obj.backend_status!=peer_object.backend_status):
+                    obj.backend_status = peer_object.backend_status
+                    obj.save(update_fields=['backend_status'])
+                raise FailedDependency("Failed dependency for %s:%s peer %s:%s failed  %s:%s" % (obj.__class__.__name__, str(obj.pk), peer_object.__class__.__name__, str(peer_object.pk), failed.__class__.__name__, str(failed.pk)))
 
     def call(self, failed=[], deletion=False):
         pending = self.fetch_pending(deletion)
@@ -66,17 +83,25 @@ class SyncStep:
                 else:
                     self.sync_record(o)
                     o.enacted = datetime.now() # Is this the same timezone? XXX
-                    o.backend_status = "OK"
+                    o.backend_status = "1 - OK"
                     o.save(update_fields=['enacted'])
             except Exception,e:
+                logger.log_exc("sync step failed!")
+                str_e = '%r'%e
                 try:
-                    o.backend_status = self.error_map.map(str(e))
+                    o.backend_status = '2 - %s'%self.error_map.map(str_e)
                 except:
-                    o.backend_status = str(e)
+                    o.backend_status = '2 - %s'%str_e
 
-                o.save(update_fields=['backend_status'])
+                # TOFIX:
+                # DatabaseError: value too long for type character varying(140)
+                if (o.pk):
+                    try:
+                        o.save(update_fields=['backend_status'])
+                    except:
+                        print "Could not update backend status field!"
+                        pass
 
-                logger.log_exc("sync step failed!")
                 failed.append(o)
 
         return failed