# $Id$
#
-# Metafiles
-init := PLC/__init__.py PLC/Methods/__init__.py PLC/Legacy/__init__.py
+# Metafiles - manage Legacy/ and Shortcuts by hand
+init := PLC/__init__.py PLC/Methods/__init__.py
# python-pycurl and python-psycopg2 avail. from fedora 5
# we used to ship our own version of psycopg2 and pycurl, for fedora4
PLC/Methods/__init__.py: force
endif
PLC/Methods/__init__.py:
- (echo 'methods = """' ; cd PLC/Methods; ls -1 *.py system/*.py | grep -v __init__ | sed -e 's,.py$$,,' -e 's,system/,system.,' ; echo '""".split()') > $@
-
-########## Legacy/
-# the current content of __init__.py
-LEGACY_now := $(sort $(shell fgrep -v '"' PLC/Legacy/__init__.py 2>/dev/null))
-# what should be declared
-LEGACY_paths := $(filter-out %/__init__.py, $(wildcard PLC/Legacy/*.py))
-LEGACY_files := $(sort $(notdir $(LEGACY_paths:.py=)))
-
-ifneq ($(LEGACY_now),$(LEGACY_files))
-PLC/Legacy/__init__.py: force
-endif
-PLC/Legacy/__init__.py:
- (echo '# each module to define in "methods" the set of methods that it defines' ;\
- echo '__all__ = """' ; \
- cd PLC/Legacy; ls -1 *.py | grep -v __init__ | sed -e 's,.py$$,,' ; \
- echo '""".split()') > $@
+ (echo 'native_methods = """' ; cd PLC/Methods; ls -1 *.py system/*.py | grep -v __init__ | sed -e 's,.py$$,,' -e 's,system/,system.,' ; echo '""".split()') > $@
##########
force:
from PLC.Config import Config
from PLC.Faults import *
import PLC.Methods
+import PLC.Shortcuts
import PLC.Legacy
def import_deep(name):
class PLCAPI:
# flat list of method names
- methods = PLC.Methods.methods
-
- # dict {methodname:module}
- legacy_map={}
- for module in PLC.Legacy.__all__ :
- for method in getattr(import_deep("PLC.Legacy."+module),"methods"):
- legacy_map[method]=module
-
- all_methods = methods+legacy_map.keys()
+ native_methods = PLC.Methods.native_methods
+
+ # other_methods_map : dict {methodname: fullpath}
+ # e.g. 'Shortcuts' -> 'PLC.Shortcuts.Shortcuts'
+ other_methods_map={}
+ for subdir in [ 'Shortcuts', 'Legacy']:
+ path="PLC."+subdir
+ # scan e.g. PLC.Shortcuts.__all__
+ pkg = __import__(path).__dict__[subdir]
+ for modulename in getattr(pkg,"__all__"):
+ fullpath=path+"."+modulename
+ for method in getattr(import_deep(fullpath),"methods"):
+ other_methods_map[method] = fullpath
+
+ all_methods = native_methods + other_methods_map.keys()
def __init__(self, config = "/etc/planetlab/plc_config", encoding = "utf-8"):
self.encoding = encoding
# Get new instance of method
try:
classname = method.split(".")[-1]
- if method in self.methods:
+ if method in self.native_methods:
module = __import__("PLC.Methods." + method, globals(), locals(), [classname])
return getattr(module, classname)(self)
else:
- modulename=self.legacy_map[method]
- module = __import__("PLC.Legacy." + modulename, globals(), locals(), [classname])
+ fullpath=self.other_methods_map[method]
+ module = __import__(fullpath, globals(), locals(), [classname])
return getattr(module, classname)(self)
except ImportError, AttributeError:
raise PLCInvalidAPIMethod, method
+# $Id$
+
import time
from PLC.Faults import *
-methods = """
+native_methods = """
AddAddressType
AddAddressTypeToAddress
AddBootState
if role is not None:
self.auth['Role'] = role
- for method in PLC.Methods.methods + PLC.API.PLCAPI.legacy_map.keys():
+ for method in PLC.API.PLCAPI.all_methods:
api_function = self.api.callable(method)
if self.server is None:
--- /dev/null
+# Thierry Parmentelat - INRIA
+# $Id$
+
+from types import NoneType
+
+from PLC.Method import Method
+from PLC.Auth import Auth
+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
+
+# known classes : { class -> secondary_key }
+taggable_classes = { Node : 'hostname', Interface : None, Slice: 'login_base', Ilink : None}
+
+# generates 2 method classes:
+# Get<classname><methodsuffix> (auth, id_or_name) -> tagvalue or None
+# Set<classname><methodsuffix> (auth, id_or_name, tagvalue) -> None
+# tagvalue is always a string, no cast nor typecheck for now
+#
+# note: tag_min_role_id gets attached to the tagtype instance,
+# while get_roles and set_roles get attached to the created methods
+#
+# returns a tuple (get_method, set_method)
+# See Shortcuts.py for examples
+
+def get_set_factory (objclass, methodsuffix,
+ tagname, category, description, tag_min_role_id=10,
+ get_roles=['admin'], set_roles=['admin']):
+
+ if objclass not in taggable_classes:
+ try:
+ raise PLCInvalidArgument,"PLC.Shortcuts.Factory: unknown class %s"%objclass.__name__
+ except:
+ raise PLCInvalidArgument,"PLC.Shortcuts.Factory: unknown class ??"
+ classname=objclass.__name__
+ get_name = "Get" + classname + methodsuffix
+ set_name = "Set" + classname + methodsuffix
+
+ # create method objects under PLC.Method.Method
+ get_class = type (get_name, (Method,),
+ {"__doc__":"Shortcut 'get' method designed for %s objects using tag %s"%\
+ (classname,tagname)})
+ set_class = type (set_name, (Method,),
+ {"__doc__":"Shortcut 'set' method designed for %s objects using tag %s"%\
+ (classname,tagname)})
+ # 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:
+ get_accepts += [ Mixed (objclass.fields[primary_key], objclass.fields[secondary_key]) ]
+ # for set, idem + one additional arg
+ set_accepts = get_accepts + [ Parameter (str,"New tag value") ]
+
+ # returns
+ get_returns = Mixed (Parameter (str), Parameter(NoneType))
+ set_returns = Parameter(NoneType)
+
+ # store in classes
+ setattr(get_class,'roles',get_roles)
+ setattr(get_class,'accepts',get_accepts)
+ setattr(get_class,'returns', get_returns)
+ setattr(get_class,'skip_typecheck',True)
+
+ setattr(set_class,'roles',set_roles)
+ setattr(set_class,'accepts',set_accepts)
+ setattr(set_class,'returns', set_returns)
+ setattr(set_class,'skip_typecheck',True)
+
+ # body of the get method
+ def get_call (self, auth, id_or_name):
+ print 'Automagical Shortcut get method',classname,get_name,tagname,primary_key,secondary_key
+ print 'Warning: PLC/Shortcuts/Factory is an ongoing work'
+ return 'foobar'
+ setattr (get_class,"call",get_call)
+
+ # body of the set method
+ def set_call (self, auth, id_or_name, tagvalue):
+ print 'Automagical Shortcut set method',classname,get_name,tagname,primary_key,secondary_key
+ print 'Warning: PLC/Shortcuts/Factory is an ongoing work'
+ return None
+ setattr (set_class,"call",set_call)
+
+ return ( get_class, set_class )
+
--- /dev/null
+# Thierry Parmentelat - INRIA
+# $Id$
+
+from PLC.Nodes import Node
+from PLC.Interfaces import Interface
+from PLC.Slices import Slice
+from PLC.Ilinks import Ilink
+
+from PLC.Shortcuts.Factory import get_set_factory
+
+# xxx probably defined someplace else
+all_roles = [ 'admin', 'pi', 'tech', 'user', 'node' ]
+
+methods=[]
+
+# example : node architecture
+(GetNodeArch, SetNodeArch) = \
+ get_set_factory ( Node, "Arch", 'arch', 'node/config', 'architecture name',
+ tag_min_role_id=40,
+ get_roles=all_roles,
+ set_roles=['admin', 'pi', 'tech'] )
+methods += [ 'GetNodeArch', 'SetNodeArch' ]
+
+# example : vlan ids on interfaces
+(GetInterfaceVlan, SetInterfaceVlan) = \
+ get_set_factory ( Interface, "Vlan", "vlan","interface/general", "tag for setting VLAN id",
+ get_roles=all_roles,
+ set_roles=['admin', 'pi', 'tech'] )
+methods += [ 'GetInterfaceVlan', 'SetInterfaceVlan' ]
--- /dev/null
+# each module to define in "methods" the set of methods that it defines
+__all__ = """
+Shortcuts
+""".split()