define_accessors accepts a list of classes if needed
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Wed, 1 Dec 2010 14:44:49 +0000 (15:44 +0100)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Wed, 1 Dec 2010 14:44:49 +0000 (15:44 +0100)
service plc start accessors ensures consistency b/w the accessors
  definition and the tag_types in the db
revised std accessors accordingly

PLC/Accessor.py
PLC/Accessors/Accessors_site.py
PLC/Accessors/Accessors_standard.py
PLC/Accessors/Factory.py

index fb12f3d..e02d29e 100644 (file)
@@ -9,6 +9,8 @@
 # by the Factory, you need to restart your python instance / web server
 # as the cached information then becomes wrong
 
+from PLC.Debug import log 
+
 from PLC.TagTypes import TagTypes, TagType
 from PLC.Roles import Roles, Role
 
@@ -27,12 +29,13 @@ This is implemented as a singleton, so we can cache results over time"""
         self.api=api
         # 'tagname'=>'tag_id'
         self.cache={}
+        self.hash_name_to_role=dict ( [ (role['name'],role) for role in Roles(api)] )
 
     def has_cache (self,tagname): return self.cache.has_key(tagname)
     def get_cache (self,tagname): return self.cache[tagname]
     def set_cache (self,tagname,tag_type): self.cache[tagname]=tag_type
 
-    def locate_or_create_tag (self, tagname, category, description, roles):
+    def locate_or_create_tag (self, tagname, category, description, roles, enforce=False):
         "search tag type from tagname & create if needed"
 
         # cached ?
@@ -42,6 +45,22 @@ This is implemented as a singleton, so we can cache results over time"""
         tag_types = TagTypes (self.api, {'tagname':tagname})
         if tag_types:
             tag_type = tag_types[0]
+            # enforce should only be set by the 'service plc start accessors' sequence
+            if enforce:
+                try:
+                    tag_type.update({'category':category,'description':description})
+                    tag_type.sync()
+                    roles_to_add = set(roles).difference(set(tag_type['roles']))
+                    for rolename in roles_to_add:
+                        tag_type.add_role(self.hash_name_to_role[rolename])
+                    roles_to_delete = set(tag_type['roles']).difference(set(roles))
+                    for rolename in roles_to_delete:
+                        tag_type.remove_role(self.hash_name_to_role[rolename])
+                except:
+                    # this goes in boot.log ...
+                    print >> log, "WARNING, Could not enforce tag type, tagname=%s\n"%tagname
+                    traceback.print_exc(file=log)
+                    
         else:
             # not found: create it
             tag_type_fields = {'tagname':tagname,
@@ -70,12 +89,12 @@ This is implemented as a singleton, so we can cache results over time"""
     
     # this is designed to be part of the 'service plc start' sequence
     # it ensures the creation of all the tagtypes defined 
-    # in the various accessors
+    # in the various accessors, and enforces consistency to the DB
     # it's not easy to have define_accessors do this because at
     # load-time as we do not have an instance of API yet
     def run_all_tag_locators (self):
         for (name, tag_locator) in Accessor.tag_locators.items():
-            tag_locator(self)
+            tag_locator(self,enforce=True)
 
 ####################
 # make it a singleton so we can cache stuff in there over time
index 7955395..cce0c51 100644 (file)
@@ -4,21 +4,16 @@
 # Accessors_site.py is the place where you can define your own local tag accessors
 # this will not be overwritten through rpm upgrades
 #
+# Historical note: now that Sites are taggable too, the name may be confusing, 
+# think of this as Accessors_local.py
+#
 # to ensure creation of new tag_types, just run 
 #   service plc start accessors
-# also for the running service to take the new accessors into account, you need to
+# also for the running API to take the new accessors into account, you need to
 #   apachectl restart
 # or to stay on the safe side, simply do
 #   service plc restart
 #
-# please note however that if a tag_type already exists in the DB, then 
-# changing the corresponding accessors creation code WILL NOT alter the 
-# tag_type in the DB; that applies to roles and other desc. or categ. 
-# you will thus need to apply them manually 
-#
-# Now that Sites are taggable too, the name may be confusing, think of is as
-# Accessors_local.py
-#
 # methods denotes the set of methods (names) that get inserted into the API
 # it is updated by define_accessors
 
index 680dfd5..e07c8be 100644 (file)
@@ -33,26 +33,17 @@ define_accessors(current_module, Slice, "Initscript","initscript",
 
 # xxx the accessor factory should enforce the category, descriptions and roles provided here.
 # BootManager might need to set any of these 3, so 'node' needs to be in set_roles
-define_accessors(current_module, Slice, "Arch", "arch",
+# to tweaks the installed version on nodes and slivers
+define_accessors(current_module, [Slice,Node], "Arch", "arch",
                  "node/slice/config", "node arch or slivers arch",
                  set_roles=["pi","user","tech","node"], expose_in_api=True)
-define_accessors(current_module, Slice, "Pldistro", "pldistro",
+define_accessors(current_module, [Slice,Node], "Pldistro", "pldistro",
                  "node/slice/config", "PlanetLab distribution to use for node or slivers",
                  set_roles=["pi","user","tech","node"], expose_in_api=True)
-define_accessors(current_module, Slice, "Fcdistro", "fcdistro",
+define_accessors(current_module, [Slice,Node], "Fcdistro", "fcdistro",
                  "node/slice/config", "Fedora or CentOS distribution to use for node or slivers",
                  set_roles=["pi","user","tech","node"], expose_in_api=True)
 
-# Ditto for the GetNodeFlavour method
-define_accessors(current_module, Node, "Arch", "arch",
-                 "node/slice/config", "node arch or slivers arch",
-                 set_roles=["pi","user","tech"], expose_in_api=True)
-define_accessors(current_module, Node, "Pldistro", "pldistro",
-                 "node/slice/config", "PlanetLab distribution to use for node or slivers",
-                 set_roles=["pi","user","tech"], expose_in_api=True)
-define_accessors(current_module, Node, "Fcdistro", "fcdistro",
-                 "node/slice/config", "Fedora or CentOS distribution to use for node or slivers",
-                 set_roles=["pi","user","tech"], expose_in_api=True)
 # node deployment (alpha, beta, ...)
 define_accessors(current_module, Node, "Deployment", "deployment",
                  "node/operation", 'typically "alpha", "beta", or "production"',
index 3ad0bc1..e4ef578 100644 (file)
@@ -72,10 +72,19 @@ tech_roles = [ 'admin', 'pi', 'tech' ]
 # the convention here is that methodsuffix should be mixed case, e.g. MyStuff
 # while tagname is expected to be lowercase
 # you then end up with e.g. GetPersonMyStuff
-def define_accessors (module, objclass, methodsuffix, tagname,
-                      category, description,
-                      get_roles=all_roles, set_roles=admin_roles, 
-                      expose_in_api = False):
+
+# the entry point accepts a single class or a list of classes
+def define_accessors (module, objclasses, *args, **kwds):
+    if not isinstance(objclasses,list):
+        objclasses=[objclasses]
+    for objclass in objclasses:
+        define_accessors_ (module, objclass, *args, **kwds)
+
+# this is for one class
+def define_accessors_ (module, objclass, methodsuffix, tagname,
+                       category, description,
+                       get_roles=all_roles, set_roles=admin_roles, 
+                       expose_in_api = False):
 
     if objclass not in taggable_classes:
         try:
@@ -131,11 +140,12 @@ def define_accessors (module, objclass, methodsuffix, tagname,
 
     # locate the tag and create it if needed
     # this method is attached to the Accessor class
-    def tag_locator (self):
+    def tag_locator (self, enforce=False):
         return self.locate_or_create_tag (tagname=tagname,
                                           category=category,
                                           description=description,
-                                          roles=set_roles)
+                                          roles=set_roles,
+                                          enforce=enforce)
 
     # attach it to the Accessor class
     Accessor.register_tag_locator(locator_name,tag_locator)