revised accessor factory; tagtype gets created on Get... methods, and maintain a...
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Tue, 26 Jan 2010 16:43:37 +0000 (16:43 +0000)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Tue, 26 Jan 2010 16:43:37 +0000 (16:43 +0000)
PLC/Accessor.py [new file with mode: 0644]
PLC/Accessors/Accessors_site.py
PLC/Accessors/Accessors_standard.py
PLC/Accessors/Factory.py

diff --git a/PLC/Accessor.py b/PLC/Accessor.py
new file mode 100644 (file)
index 0000000..8a8d16d
--- /dev/null
@@ -0,0 +1,58 @@
+# $Id$
+# $URL$
+#
+# Thierry Parmentelat - INRIA
+#
+#
+# just a placeholder for storing accessor-related tag checkers
+# this is filled by the accessors factory
+
+from PLC.TagTypes import TagTypes, TagType
+
+# implementation
+class Accessor (object) :
+    """This is placeholder for storing accessor-related tag checkers
+methods in this class are defined by the accessors factory
+
+This is implemented as a singleton, so we can cache results over time"""
+
+    _instance = None
+
+    def __init__ (self, api):
+        self.api=api
+        # 'tagname'=>'tag_id'
+        self.cache={}
+
+    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_id): self.cache[tagname]=tag_id
+
+    def locate_or_create_tag (self,tagname,category, description, min_role_id):
+        "search tag type from tagname & create if needed"
+        
+        # cached ?
+        if self.has_cache (tagname):
+            return self.get_cache(tagname)
+        # search
+        tag_types = TagTypes (self.api, {'tagname':tagname})
+        if tag_types:
+            tag_type = tag_types[0]
+        else:
+            # not found: create it
+            tag_type_fields = {'tagname':tagname, 
+                               'category' :  category,
+                               'description' : description,
+                               'min_role_id': min_role_id}
+            tag_type = TagType (self.api, tag_type_fields)
+            tag_type.sync()
+        tag_type_id = tag_type['tag_type_id']
+        self.set_cache(tagname,tag_type_id)
+        return tag_type_id
+
+
+####################
+# make it a singleton so we can cache stuff in there over time
+def AccessorSingleton (api):
+    if not Accessor._instance:
+        Accessor._instance = Accessor(api)
+    return Accessor._instance
index 0eadebc..f27cd8d 100644 (file)
@@ -2,8 +2,11 @@
 # $Id$
 # $URL$
 #
-# Shortcuts_site.py is the place where you can define your own tag accessors
-# this will not be overwritten through rpm upgrades in a myplc-devel packaging
+# Accessors_site.py is the place where you can define your own local tag accessors
+# this will not be overwritten through rpm upgrades
+#
+# 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
@@ -13,6 +16,8 @@ methods=[]
 from PLC.Nodes import Node
 from PLC.Interfaces import Interface
 from PLC.Slices import Slice
+from PLC.Sites import Site
+from PLC.Persons import Person
 #from PLC.Ilinks import Ilink
 
 from PLC.Accessors.Factory import define_accessors, all_roles, tech_roles
index 1e28b87..9d3c1e1 100644 (file)
@@ -5,6 +5,9 @@
 from PLC.Nodes import Node
 from PLC.Interfaces import Interface
 from PLC.Slices import Slice
+from PLC.Slices import Slice
+from PLC.Sites import Site
+from PLC.Persons import Person
 #from PLC.Ilinks import Ilink
 
 from PLC.Accessors.Factory import define_accessors, all_roles, tech_roles
@@ -44,14 +47,16 @@ define_accessors(current_module, Slice, "Fcdistro", "fcdistro",
                  "node/slice/config", "Fedora or CentOS distribution to use for node or slivers", 
                  get_roles=all_roles, set_roles=["admin"], expose_in_api=True)
 
-# node architecture 
+# Ditto for the GetNodeFlavour method
 define_accessors(current_module, Node, "Arch", "arch",  
                  "node/slice/config", "node arch or slivers arch",
                  get_roles=all_roles, set_roles=tech_roles, expose_in_api=True)
-# distribution to be deployed
 define_accessors(current_module, Node, "Pldistro", "pldistro",
                  "node/slice/config", "PlanetLab distribution to use for node or slivers", 
                  get_roles=all_roles, set_roles=["admin"], expose_in_api=True)
+define_accessors(current_module, Node, "Fcdistro", "fcdistro",
+                 "node/slice/config", "Fedora or CentOS distribution to use for node or slivers", 
+                 get_roles=all_roles, set_roles=["admin"], expose_in_api=True)
 # node deployment (alpha, beta, ...)
 define_accessors(current_module, Node, "Deployment", "deployment",
                  "node/operation", 'typically "alpha", "beta", or "production"',
@@ -88,3 +93,8 @@ define_accessors(current_module, Interface, "Driver", "driver",
 define_accessors(current_module, Interface, "Alias", "alias", 
                  "interface/config", "interface alias",
                  get_roles=all_roles, set_roles=tech_roles)
+
+# site
+define_accessors(current_module, Site, "Foo", "foo",
+                 "site/test", "some name",
+                 get_roles=all_roles, set_roles=all_roles, expose_in_api=True)
index 02de440..2dd2a73 100644 (file)
@@ -4,11 +4,12 @@
 
 from types import NoneType
 
-from PLC.Method import Method
+from PLC.Faults import *
+
 from PLC.Auth import Auth
 from PLC.Parameter import Parameter, Mixed
-
-from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Accessor import Accessor, AccessorSingleton
 
 from PLC.Nodes import Nodes, Node
 from PLC.NodeTags import NodeTags, NodeTag
@@ -16,6 +17,10 @@ from PLC.Interfaces import Interfaces, Interface
 from PLC.InterfaceTags import InterfaceTags, InterfaceTag
 from PLC.Slices import Slices, Slice
 from PLC.SliceTags import SliceTags, SliceTag
+from PLC.Sites import Sites, Site
+from PLC.SiteTags import SiteTags, SiteTag
+from PLC.Persons import Persons, Person
+from PLC.PersonTags import PersonTags, PersonTag
 
 # this is another story..
 #from PLC.Ilinks import Ilink
@@ -32,6 +37,12 @@ taggable_classes = { Node : {'table_class' : Nodes,
                      Slice: {'table_class' : Slices, 
                              'joins_class': SliceTags, 'join_class': SliceTag,
                              'secondary_key':'name'},
+                     Site: {'table_class' : Sites, 
+                             'joins_class': SiteTags, 'join_class': SiteTag,
+                             'secondary_key':'login_base'},
+                     Person: {'table_class' : Persons, 
+                             'joins_class': PersonTags, 'join_class': PersonTag,
+                             'secondary_key':'email'},
 #                     Ilink : xxx
                      }
 
@@ -52,6 +63,8 @@ tech_roles = [ 'admin', 'pi', 'tech' ]
 # while get_roles and set_roles get attached to the created methods
 # this might need a cleanup
 # 
+# in addition a convenience method like e.g. LocateNodeArch is defined 
+# in the Accessor class; its purpose is to retrieve the tag, or to create it if needed
 
 def define_accessors (module, objclass, methodsuffix, tagname, 
                       category, description, 
@@ -71,14 +84,16 @@ def define_accessors (module, objclass, methodsuffix, tagname,
     classname=objclass.__name__
     get_name = "Get" + classname + methodsuffix
     set_name = "Set" + classname + methodsuffix
+    locator_name = "Locate" + classname + methodsuffix
 
-    # create method objects under PLC.Method.Method
+    # accessor method objects under PLC.Method.Method
     get_class = type (get_name, (Method,),
                       {"__doc__":"Accessor 'get' method designed for %s objects using tag %s"%\
                            (classname,tagname)})
     set_class = type (set_name, (Method,),
                       {"__doc__":"Accessor 'set' method designed for %s objects using tag %s"%\
                            (classname,tagname)})
+
     # accepts 
     get_accepts = [ Auth () ]
     primary_key=objclass.primary_key
@@ -106,13 +121,23 @@ def define_accessors (module, objclass, methodsuffix, tagname,
     joins_class = taggable_classes[objclass]['joins_class']
     join_class = taggable_classes[objclass]['join_class']
 
+    # locate the tag and create it if needed
+    # this method is attached to the Accessor class
+    def locate_or_create_tag (self):
+        return self.locate_or_create_tag (tagname=tagname,
+                                          category=category,
+                                          description=description,
+                                          min_role_id=tag_min_role_id)
+
+    # attach it to the Accessor class
+    setattr(Accessor,locator_name,locate_or_create_tag)
+
     # body of the get method
     def get_call (self, auth, id_or_name):
-        # search the tagtype - xxx - might need a cache
-        tag_types = TagTypes (self.api, {'tagname': tagname})
-        if not tag_types:
-            return None
-        tag_type_id = tag_types[0]['tag_type_id']
+        # locate the tag, see above
+        locator = getattr(Accessor,locator_name)
+        tag_type_id = locator(AccessorSingleton(self.api))
+
         filter = {'tag_type_id':tag_type_id}
         if isinstance (id_or_name,int):
             filter[primary_key]=id_or_name
@@ -140,19 +165,9 @@ def define_accessors (module, objclass, methodsuffix, tagname,
             raise PLCInvalidArgument, "Cannot set tag on %s %r"%(objclass.__name__,id_or_name)
         primary_id = objs[0][primary_key]
                            
-        # search tag type & create if needed
-        tag_types = TagTypes (self.api, {'tagname':tagname})
-        if tag_types:
-            tag_type = tag_types[0]
-        else:
-            # not found: create it
-            tag_type_fields = {'tagname':tagname, 
-                               'category' :  category,
-                               'description' : description,
-                               'min_role_id': tag_min_role_id}
-            tag_type = TagType (self.api, tag_type_fields)
-            tag_type.sync()
-        tag_type_id = tag_type['tag_type_id']
+        # locate the tag, see above
+        locator = getattr(Accessor,locator_name)
+        tag_type_id = locator(AccessorSingleton(self.api))
 
         # locate the join object (e.g. NodeTag, SliceTag or InterfaceTag)
         filter = {'tag_type_id':tag_type_id}