From 196d474841ff8cbfed8ddff43f01ffb7933a15d8 Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Tue, 19 Aug 2008 18:03:55 +0000 Subject: [PATCH] get/set accessors should now work, e.g.: SetNodeArch(hostname,'x86_64') GetNodeArch(node_id) == The set of accessors is split into 2 python files: (*) Accessors/Accessors_standard.py where the tags used by the core software should be defined (*) Accessors/Accessors_site.py where local admins can add custom accessors (see .in for an example) this is not overwritten by upgrades of myplc-native (for chroot ?) == I have only defined G/SetNodeArch for now The template for site accessors shows how to define G/SetInterfaceVlan --- ...rtcuts_site.py.in => Accessors_site.py.in} | 2 +- ...cuts_standard.py => Accessors_standard.py} | 0 PLC/Accessors/Factory.py | 132 ++++++++++++------ PLC/TagTypes.py | 2 +- 4 files changed, 93 insertions(+), 43 deletions(-) rename PLC/Accessors/{Shortcuts_site.py.in => Accessors_site.py.in} (91%) rename PLC/Accessors/{Shortcuts_standard.py => Accessors_standard.py} (100%) diff --git a/PLC/Accessors/Shortcuts_site.py.in b/PLC/Accessors/Accessors_site.py.in similarity index 91% rename from PLC/Accessors/Shortcuts_site.py.in rename to PLC/Accessors/Accessors_site.py.in index e89a2ad..24bc977 100644 --- a/PLC/Accessors/Shortcuts_site.py.in +++ b/PLC/Accessors/Accessors_site.py.in @@ -14,7 +14,7 @@ from PLC.Interfaces import Interface from PLC.Slices import Slice from PLC.Ilinks import Ilink -from PLC.Shortcuts.Factory import all_roles, get_set_factory +from PLC.Accessors.Factory import all_roles, get_set_factory #### example : attach vlan ids on interfaces ###(GetInterfaceVlan, SetInterfaceVlan) = \ diff --git a/PLC/Accessors/Shortcuts_standard.py b/PLC/Accessors/Accessors_standard.py similarity index 100% rename from PLC/Accessors/Shortcuts_standard.py rename to PLC/Accessors/Accessors_standard.py diff --git a/PLC/Accessors/Factory.py b/PLC/Accessors/Factory.py index f4dbca8..99c782e 100644 --- a/PLC/Accessors/Factory.py +++ b/PLC/Accessors/Factory.py @@ -9,18 +9,30 @@ from PLC.Parameter import Parameter, Mixed from PLC.Faults import * -from PLC.Nodes import Node -from PLC.Interfaces import Interface -from PLC.Slices import Slice -from PLC.Ilinks import Ilink +from PLC.Nodes import Nodes, Node +from PLC.NodeTags import NodeTags, NodeTag +from PLC.Interfaces import Interfaces, Interface +from PLC.InterfaceSettings import InterfaceSettings, InterfaceSetting +from PLC.Slices import Slices, Slice +from PLC.SliceAttributes import SliceAttributes, SliceAttribute + +# this is another story.. +#from PLC.Ilinks import Ilink from PLC.TagTypes import TagTypes, TagType # known classes : { class -> secondary_key } -taggable_classes = { Node : 'hostname', - Interface : None, - Slice: 'login_base', - Ilink : None} +taggable_classes = { Node : {'table_class' : Nodes, + 'joins_class' : NodeTags, 'join_class' : NodeTag, + 'value_key': 'tagvalue', 'secondary_key': 'hostname'}, + Interface : {'table_class' : Interfaces, + 'joins_class': InterfaceSettings, 'join_class': InterfaceSetting, + 'value_key' : 'value' }, + Slice: {'table_class' : Slices, + 'joins_class': SliceAttributes, 'join_class': SliceAttribute, + 'value_key' : 'value', 'secondary_key':'login_base'}, +# Ilink : xxx + } # xxx probably defined someplace else all_roles = [ 'admin', 'pi', 'tech', 'user', 'node' ] @@ -59,12 +71,13 @@ def get_set_factory (objclass, methodsuffix, # accepts get_accepts = [ Auth () ] primary_key=objclass.primary_key - secondary_key = taggable_classes[objclass] - if not secondary_key: - get_accepts += [ objclass.fields[primary_key] ] - else: + try: + secondary_key = taggable_classes[objclass]['secondary_key'] get_accepts += [ Mixed (objclass.fields[primary_key], objclass.fields[secondary_key]) ] - # for set, idem + one additional arg + except: + secondary_key = None + get_accepts += [ objclass.fields[primary_key] ] + # for set, idem set of arguments + one additional arg, the new value set_accepts = get_accepts + [ Parameter (str,"New tag value") ] # returns @@ -81,41 +94,78 @@ def get_set_factory (objclass, methodsuffix, setattr(set_class,'accepts',set_accepts) setattr(set_class,'returns', set_returns) setattr(set_class,'skip_typecheck',True) + + table_class = taggable_classes[objclass]['table_class'] + joins_class = taggable_classes[objclass]['joins_class'] + join_class = taggable_classes[objclass]['join_class'] + value_key = taggable_classes[objclass]['value_key'] # body of the get method def get_call (self, auth, id_or_name): - print 'Automagical Accessor get method',classname,get_name,tagname,primary_key,secondary_key - print 'Warning: PLC/Accessors/Factory is an ongoing work' - tag_type_id = locate_or_create_tag_type_id (self.api, tagname, - category, description, tag_min_role_id) - return 'foobar' + # 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'] + filter = {'tag_type_id':tag_type_id} + if isinstance (id_or_name,int): + filter[primary_key]=id_or_name + else: + filter[secondary_key]=id_or_name + joins = joins_class (self.api,filter,[value_key]) + if not joins: + # xxx - we return None even if id_or_name is not valid + return None + else: + return joins[0][value_key] + + # attach it setattr (get_class,"call",get_call) - # body of the set method + # body of the set method def set_call (self, auth, id_or_name, tagvalue): - print 'Automagical Accessor set method',classname,get_name,tagname,primary_key,secondary_key - print 'Warning: PLC/Accessors/Factory is an ongoing work' - return None + # locate the object + if isinstance (id_or_name, int): + filter={primary_key:id_or_name} + else: + filter={secondary_key:id_or_name} + objs = table_class(self.api, filter,[primary_key]) + if not objs: + 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() + # proceed + tag_type_id = tag_type['tag_type_id'] + filter = {'tag_type_id':tag_type_id} + if isinstance (id_or_name,int): + filter[primary_key]=id_or_name + else: + filter[secondary_key]=id_or_name + joins = joins_class (self.api,filter) + if not joins: + join = join_class (self.api) + join['tag_type_id']=tag_type_id + join[primary_key]=primary_id + join[value_key]=tagvalue + join.sync() + else: + joins[0][value_key]=tagvalue + joins[0].sync() + + # attach it setattr (set_class,"call",set_call) return ( get_class, set_class ) -### might need to use a cache -def locate_or_create_tag_type_id (api, tagname, category, description, min_role_id): - # search tag - tag_types = TagTypes (api, {'tagname':tagname}) - # not found: create it - if tag_types: - print 'FOUND preexisting' - tag_type_id = tag_types[0]['tag_type_id'] - else: - print 'not FOUND : creating' - tag_type_fields = {'tagname':tagname, - 'category' : category, - 'description' : description, - 'min_role_id': min_role_id} - tag_type = TagType (api, tag_type_fields) - tag_type.sync() - tag_type_id = tag_type['tag_type_id'] - - return tag_type_id diff --git a/PLC/TagTypes.py b/PLC/TagTypes.py index f15cbfe..c94be0b 100644 --- a/PLC/TagTypes.py +++ b/PLC/TagTypes.py @@ -21,7 +21,7 @@ class TagType (Row): table_name = 'tag_types' primary_key = 'tag_type_id' - join_tables = ['node_tag'] + join_tables = ['node_tag', 'interface_setting', 'slice_attribute' ] fields = { 'tag_type_id': Parameter(int, "Node tag type identifier"), 'tagname': Parameter(str, "Node tag type name", max = 100), -- 2.43.0