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$
 #
 # $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
 #
 # 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.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
 #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.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
 #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/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)
 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, "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"',
 # 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)
 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 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.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
 
 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.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
 
 # 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'},
                      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
                      }
 
 #                     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
 # 
 # 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, 
 
 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
     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)})
     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
     # 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']
 
     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):
     # 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
         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]
                            
             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}
 
         # locate the join object (e.g. NodeTag, SliceTag or InterfaceTag)
         filter = {'tag_type_id':tag_type_id}