--- /dev/null
+# $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
# $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
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.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
"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"',
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)
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
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
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
}
# 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,
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
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
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}