1 # Thierry Parmentelat - INRIA
4 from types import NoneType
6 from PLC.Method import Method
7 from PLC.Auth import Auth
8 from PLC.Parameter import Parameter, Mixed
10 from PLC.Faults import *
12 from PLC.Nodes import Nodes, Node
13 from PLC.NodeTags import NodeTags, NodeTag
14 from PLC.Interfaces import Interfaces, Interface
15 from PLC.InterfaceSettings import InterfaceSettings, InterfaceSetting
16 from PLC.Slices import Slices, Slice
17 from PLC.SliceAttributes import SliceAttributes, SliceAttribute
19 # this is another story..
20 #from PLC.Ilinks import Ilink
22 from PLC.TagTypes import TagTypes, TagType
24 # known classes : { class -> secondary_key }
25 taggable_classes = { Node : {'table_class' : Nodes,
26 'joins_class' : NodeTags, 'join_class' : NodeTag,
27 'value_key': 'tagvalue', 'secondary_key': 'hostname'},
28 Interface : {'table_class' : Interfaces,
29 'joins_class': InterfaceSettings, 'join_class': InterfaceSetting,
30 'value_key' : 'value' },
31 Slice: {'table_class' : Slices,
32 'joins_class': SliceAttributes, 'join_class': SliceAttribute,
33 'value_key' : 'value', 'secondary_key':'login_base'},
37 # xxx probably defined someplace else
38 all_roles = [ 'admin', 'pi', 'tech', 'user', 'node' ]
40 # generates 2 method classes:
41 # Get<classname><methodsuffix> (auth, id_or_name) -> tagvalue or None
42 # Set<classname><methodsuffix> (auth, id_or_name, tagvalue) -> None
43 # tagvalue is always a string, no cast nor typecheck for now
45 # note: tag_min_role_id gets attached to the tagtype instance,
46 # while get_roles and set_roles get attached to the created methods
48 # returns a tuple (get_method, set_method)
49 # See Accessors* for examples
51 def get_set_factory (objclass, methodsuffix,
52 tagname, category, description, tag_min_role_id=10,
53 get_roles=['admin'], set_roles=['admin']):
55 if objclass not in taggable_classes:
57 raise PLCInvalidArgument,"PLC.Accessors.Factory: unknown class %s"%objclass.__name__
59 raise PLCInvalidArgument,"PLC.Accessors.Factory: unknown class ??"
60 classname=objclass.__name__
61 get_name = "Get" + classname + methodsuffix
62 set_name = "Set" + classname + methodsuffix
64 # create method objects under PLC.Method.Method
65 get_class = type (get_name, (Method,),
66 {"__doc__":"Accessor 'get' method designed for %s objects using tag %s"%\
68 set_class = type (set_name, (Method,),
69 {"__doc__":"Accessor 'set' method designed for %s objects using tag %s"%\
72 get_accepts = [ Auth () ]
73 primary_key=objclass.primary_key
75 secondary_key = taggable_classes[objclass]['secondary_key']
76 get_accepts += [ Mixed (objclass.fields[primary_key], objclass.fields[secondary_key]) ]
79 get_accepts += [ objclass.fields[primary_key] ]
80 # for set, idem set of arguments + one additional arg, the new value
81 set_accepts = get_accepts + [ Parameter (str,"New tag value") ]
84 get_returns = Mixed (Parameter (str), Parameter(NoneType))
85 set_returns = Parameter(NoneType)
88 setattr(get_class,'roles',get_roles)
89 setattr(get_class,'accepts',get_accepts)
90 setattr(get_class,'returns', get_returns)
91 setattr(get_class,'skip_typecheck',True)
93 setattr(set_class,'roles',set_roles)
94 setattr(set_class,'accepts',set_accepts)
95 setattr(set_class,'returns', set_returns)
96 setattr(set_class,'skip_typecheck',True)
98 table_class = taggable_classes[objclass]['table_class']
99 joins_class = taggable_classes[objclass]['joins_class']
100 join_class = taggable_classes[objclass]['join_class']
101 value_key = taggable_classes[objclass]['value_key']
103 # body of the get method
104 def get_call (self, auth, id_or_name):
105 # search the tagtype - xxx - might need a cache
106 tag_types = TagTypes (self.api, {'tagname': tagname})
109 tag_type_id = tag_types[0]['tag_type_id']
110 filter = {'tag_type_id':tag_type_id}
111 if isinstance (id_or_name,int):
112 filter[primary_key]=id_or_name
114 filter[secondary_key]=id_or_name
115 joins = joins_class (self.api,filter,[value_key])
117 # xxx - we return None even if id_or_name is not valid
120 return joins[0][value_key]
123 setattr (get_class,"call",get_call)
125 # body of the set method
126 def set_call (self, auth, id_or_name, tagvalue):
128 if isinstance (id_or_name, int):
129 filter={primary_key:id_or_name}
131 filter={secondary_key:id_or_name}
132 objs = table_class(self.api, filter,[primary_key])
134 raise PLCInvalidArgument, "Cannot set tag on %s %r"%(objclass.__name__,id_or_name)
135 primary_id = objs[0][primary_key]
137 # search tag type & create if needed
138 tag_types = TagTypes (self.api, {'tagname':tagname})
140 tag_type = tag_types[0]
142 # not found: create it
143 tag_type_fields = {'tagname':tagname,
144 'category' : category,
145 'description' : description,
146 'min_role_id': tag_min_role_id}
147 tag_type = TagType (self.api, tag_type_fields)
150 tag_type_id = tag_type['tag_type_id']
151 filter = {'tag_type_id':tag_type_id}
152 if isinstance (id_or_name,int):
153 filter[primary_key]=id_or_name
155 filter[secondary_key]=id_or_name
156 joins = joins_class (self.api,filter)
158 join = join_class (self.api)
159 join['tag_type_id']=tag_type_id
160 join[primary_key]=primary_id
161 join[value_key]=tagvalue
164 joins[0][value_key]=tagvalue
168 setattr (set_class,"call",set_call)
170 return ( get_class, set_class )