f4dbca8955df0b3c00d833149a3884cedc157b92
[plcapi.git] / PLC / Accessors / Factory.py
1 # Thierry Parmentelat - INRIA
2 # $Id$
3
4 from types import NoneType
5
6 from PLC.Method import Method
7 from PLC.Auth import Auth
8 from PLC.Parameter import Parameter, Mixed
9
10 from PLC.Faults import *
11
12 from PLC.Nodes import Node
13 from PLC.Interfaces import Interface
14 from PLC.Slices import Slice
15 from PLC.Ilinks import Ilink
16
17 from PLC.TagTypes import TagTypes, TagType
18
19 # known classes : { class -> secondary_key }
20 taggable_classes = { Node : 'hostname', 
21                      Interface : None, 
22                      Slice: 'login_base', 
23                      Ilink : None}
24
25 # xxx probably defined someplace else
26 all_roles = [ 'admin', 'pi', 'tech', 'user', 'node' ]
27
28 # generates 2 method classes:
29 # Get<classname><methodsuffix> (auth, id_or_name) -> tagvalue or None
30 # Set<classname><methodsuffix> (auth, id_or_name, tagvalue) -> None
31 # tagvalue is always a string, no cast nor typecheck for now
32 #
33 # note: tag_min_role_id gets attached to the tagtype instance, 
34 # while get_roles and set_roles get attached to the created methods
35
36 # returns a tuple (get_method, set_method)
37 # See Accessors* for examples
38
39 def get_set_factory (objclass, methodsuffix, 
40                      tagname, category, description, tag_min_role_id=10,
41                      get_roles=['admin'], set_roles=['admin']):
42     
43     if objclass not in taggable_classes:
44         try:
45             raise PLCInvalidArgument,"PLC.Accessors.Factory: unknown class %s"%objclass.__name__
46         except:
47             raise PLCInvalidArgument,"PLC.Accessors.Factory: unknown class ??"
48     classname=objclass.__name__
49     get_name = "Get" + classname + methodsuffix
50     set_name = "Set" + classname + methodsuffix
51
52     # create method objects under PLC.Method.Method
53     get_class = type (get_name, (Method,),
54                       {"__doc__":"Accessor 'get' method designed for %s objects using tag %s"%\
55                            (classname,tagname)})
56     set_class = type (set_name, (Method,),
57                       {"__doc__":"Accessor 'set' method designed for %s objects using tag %s"%\
58                            (classname,tagname)})
59     # accepts 
60     get_accepts = [ Auth () ]
61     primary_key=objclass.primary_key
62     secondary_key = taggable_classes[objclass]
63     if not secondary_key:
64         get_accepts += [ objclass.fields[primary_key] ]
65     else:
66         get_accepts += [ Mixed (objclass.fields[primary_key], objclass.fields[secondary_key]) ]
67     # for set, idem + one additional arg
68     set_accepts = get_accepts + [ Parameter (str,"New tag value") ]
69
70     # returns
71     get_returns = Mixed (Parameter (str), Parameter(NoneType))
72     set_returns = Parameter(NoneType)
73
74     # store in classes
75     setattr(get_class,'roles',get_roles)
76     setattr(get_class,'accepts',get_accepts)
77     setattr(get_class,'returns', get_returns)
78     setattr(get_class,'skip_typecheck',True)
79
80     setattr(set_class,'roles',set_roles)
81     setattr(set_class,'accepts',set_accepts)
82     setattr(set_class,'returns', set_returns)
83     setattr(set_class,'skip_typecheck',True)
84
85     # body of the get method
86     def get_call (self, auth, id_or_name):
87         print 'Automagical Accessor get method',classname,get_name,tagname,primary_key,secondary_key
88         print 'Warning: PLC/Accessors/Factory is an ongoing work'
89         tag_type_id = locate_or_create_tag_type_id (self.api, tagname, 
90                                                     category, description, tag_min_role_id)
91         return 'foobar'
92     setattr (get_class,"call",get_call)
93
94     # body of the set method
95     def set_call (self, auth, id_or_name, tagvalue):
96         print 'Automagical Accessor set method',classname,get_name,tagname,primary_key,secondary_key
97         print 'Warning: PLC/Accessors/Factory is an ongoing work'
98         return None
99     setattr (set_class,"call",set_call)
100
101     return ( get_class, set_class )
102
103 ### might need to use a cache
104 def locate_or_create_tag_type_id (api, tagname, category, description, min_role_id):
105     # search tag
106     tag_types = TagTypes (api, {'tagname':tagname})
107     # not found: create it
108     if tag_types:
109         print 'FOUND preexisting'
110         tag_type_id = tag_types[0]['tag_type_id']
111     else:
112         print 'not FOUND : creating'
113         tag_type_fields = {'tagname':tagname, 
114                            'category' :  category,
115                            'description' : description,
116                            'min_role_id': min_role_id}
117         tag_type = TagType (api, tag_type_fields)
118         tag_type.sync()
119         tag_type_id = tag_type['tag_type_id']
120
121     return tag_type_id