Merge branch 'master' of git.planet-lab.org:/git/plstackapi
[plstackapi.git] / planetstack / observer / syncstep.py
1 import os
2 import base64
3 from planetstack.config import Config
4
5 class FailedDependency(Exception):
6         pass
7
8 class SyncStep:
9         """ A PlanetStack Sync step. 
10
11         Attributes:
12                 psmodel         Model name the step synchronizes 
13                 dependencies    list of names of models that must be synchronized first if the current model depends on them
14         """ 
15         slow=False
16         def get_prop(prop):
17                 try:
18                         sync_config_dir = Config().sync_config_dir
19                 except:
20                         sync_config_dir = '/etc/planetstack/sync'
21                 prop_config_path = '/'.join(sync_config_dir,self.name,prop)
22                 return open(prop_config_path).read().rstrip()
23
24         def __init__(self, **args):
25                 """Initialize a sync step
26                    Keyword arguments:
27                                 name -- Name of the step
28                                 provides -- PlanetStack models sync'd by this step
29                 """
30                 dependencies = []
31                 try:
32                         self.soft_deadline = int(self.get_prop('soft_deadline_seconds'))
33                 except:
34                         self.soft_deadline = 5 # 5 seconds
35
36                 return
37
38         def fetch_pending(self):
39                 return Sliver.objects.filter(ip=None)
40         
41         def check_dependencies(self, obj):
42                 for dep in self.dependencies:
43                         peer_object = getattr(obj, dep.name.lowercase())
44                         if (peer_object.pk==dep.pk):
45                                 raise DependencyFailed
46
47         def call(self, failed=[]):
48                 pending = self.fetch_pending()
49                 for o in pending:
50                         if (not self.depends_on(o, failed)):
51                                 try:
52                                         check_dependencies(o) # Raises exception if failed                                      
53                                         self.sync_record(o)
54                                         o.enacted = datetime.now() # Is this the same timezone? XXX
55                                         o.save(update_fields=['enacted'])
56                                 except:
57                                         failed.append(o)
58                 return failed
59
60         def __call__(self):
61                 return self.call()