3 from datetime import datetime
4 from planetstack.config import Config
5 from util.logger import Logger, logging
6 from observer.steps import *
8 logger = Logger(level=logging.INFO)
10 class FailedDependency(Exception):
14 """ A PlanetStack Sync step.
17 psmodel Model name the step synchronizes
18 dependencies list of names of models that must be synchronized first if the current model depends on them
23 sync_config_dir = Config().sync_config_dir
25 sync_config_dir = '/etc/planetstack/sync'
26 prop_config_path = '/'.join(sync_config_dir,self.name,prop)
27 return open(prop_config_path).read().rstrip()
29 def __init__(self, **args):
30 """Initialize a sync step
32 name -- Name of the step
33 provides -- PlanetStack models sync'd by this step
36 self.driver = args.get('driver')
37 self.error_map = args.get('error_map')
40 self.soft_deadline = int(self.get_prop('soft_deadline_seconds'))
42 self.soft_deadline = 5 # 5 seconds
46 def fetch_pending(self, deletion=False):
47 # This is the most common implementation of fetch_pending
48 # Steps should override it if they have their own logic
49 # for figuring out what objects are outstanding.
50 main_obj = self.provides[0]
52 objs = main_obj.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
54 objs = main_obj.deleted_objects.all()
57 #return Sliver.objects.filter(ip=None)
59 def check_dependencies(self, obj, failed):
60 for dep in self.dependencies:
61 peer_name = dep[0].lower() + dep[1:] # django names are camelCased with the first letter lower
62 peer_object = getattr(obj, peer_name)
64 # peer_object can be None, and if so there
65 # is no object-level dependency
66 if (peer_object and peer_object.pk==failed.pk):
67 raise FailedDependency
69 def call(self, failed=[], deletion=False):
70 pending = self.fetch_pending(deletion)
74 self.check_dependencies(o,f) # Raises exception if failed
80 o.enacted = datetime.now() # Is this the same timezone? XXX
81 o.backend_status = "OK"
82 o.save(update_fields=['enacted'])
85 o.backend_status = self.error_map.map(str(e))
87 o.backend_status = str(e)
90 o.save(update_fields=['backend_status'])
92 logger.log_exc("sync step failed!")
97 def __call__(self, **args):
98 return self.call(**args)