from PLC.Config import Config
from PLC.Faults import *
import PLC.Methods
+import PLC.Legacy
+
+def import_deep(name):
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
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()
+
def __init__(self, config = "/etc/planetlab/plc_config", encoding = "utf-8"):
self.encoding = encoding
"""
# Look up method
- if method not in self.methods:
+ if method not in self.all_methods:
raise PLCInvalidAPIMethod, method
-
+
# Get new instance of method
try:
classname = method.split(".")[-1]
- module = __import__("PLC.Methods." + method, globals(), locals(), [classname])
- return getattr(module, classname)(self)
+ if method in self.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])
+ return getattr(module, classname)(self)
except ImportError, AttributeError:
raise PLCInvalidAPIMethod, method
--- /dev/null
+# Thierry Parmentelat - INRIA
+# $Id$
+
+from PLC.Method import Method
+
+def import_deep(name):
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+methods = [
+ "AddNodeNetwork",
+ "AddNodeNetworkSetting",
+ "DeleteNodeNetwork",
+ "DeleteNodeNetworkSetting",
+ "GetNodeNetworkSettings",
+ "GetNodeNetworks",
+ "UpdateNodeNetwork",
+ "UpdateNodeNetworkSetting",
+]
+
+# does any required renaming
+def rename (x):
+ if x=='nodenetwork_id':
+ return 'interface_id'
+ if x=='nodenetwork_ids':
+ return 'interface_ids'
+ else:
+ return x
+
+# apply rename on list (columns) or dict (filter) args
+def patch_legacy_arg (arg):
+ if isinstance(arg,list):
+ return [rename(x) for x in arg]
+ if isinstance(arg,dict):
+ return dict ( [ (rename(k),v) for (k,v) in arg.iteritems() ] )
+ return arg
+
+def factory (legacyname):
+ # new method name
+ newname=legacyname.replace("NodeNetwork","Interface")
+ # locate new class
+ newclass=getattr(import_deep("PLC.Methods."+newname),newname)
+ # create class for legacy name
+ legacyclass = type(legacyname,(newclass,),
+ {"__doc__":"Legacy method - please use %s instead"%newname})
+ # xxx should rewrite 'call' to handle any argument using nodenetwork_id(s)
+ for internal in ["roles","accepts","returns"]:
+ setattr(legacyclass,internal,getattr(newclass,internal))
+ # turn off type checking, as introspection code fails on wrapped_call
+ setattr(legacyclass,"skip_typecheck",True)
+ # rewrite call
+ def wrapped_call (self,auth,*args, **kwds):
+ newargs=[patch_legacy_arg(x) for x in args]
+ newkwds=dict ( [ (k,patch_legacy_arg(v)) for (k,v) in kwds.iteritems() ] )
+ return getattr(newclass,"call")(self,auth,*newargs,**newkwds)
+ setattr(legacyclass,"call",wrapped_call)
+
+ return legacyclass
+
+# this does not work, as __module__ is not yet supported
+#for legacyname in methods:
+# setattr(__module__,legacyname,factory(legacyname))
+# this does not work either, as we are importing the module so we cannot locate it yet
+#for legacyname in methods:
+# this_module = import_deep(__name__)
+# setattr(__module__,legacyname,factory(legacyname))
+
+AddNodeNetwork=factory("AddNodeNetwork")
+AddNodeNetworkSetting=factory("AddNodeNetworkSetting")
+DeleteNodeNetwork=factory("DeleteNodeNetwork")
+DeleteNodeNetworkSetting=factory("DeleteNodeNetworkSetting")
+GetNodeNetworkSettings=factory("GetNodeNetworkSettings")
+GetNodeNetworks=factory("GetNodeNetworks")
+UpdateNodeNetwork=factory("UpdateNodeNetwork")
+UpdateNodeNetworkSetting=factory("UpdateNodeNetworkSetting")
--- /dev/null
+# Thierry Parmentelat - INRIA
+# $Id$
+
+from PLC.Method import Method
+
+def import_deep(name):
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+map = {
+ "AddSliceAttributeType" : "AddTagType",
+ "DeleteSliceAttributeType" : "DeleteTagType",
+ "GetSliceAttributeTypes" : "GetTagTypes",
+ "UpdateSliceAttributeType" : "UpdateTagType",
+ "AddNodeNetworkSettingType" : "AddTagType",
+ "DeleteNodeNetworkSettingType" : "DeleteTagType",
+ "GetNodeNetworkSettingTypes" : "GetTagTypes",
+ "UpdateNodeNetworkSettingType" : "UpdateTagType",
+}
+
+methods = map.keys()
+
+# does any required renaming
+def rename (x):
+ if x=='name':
+ return 'tagname'
+ else:
+ return x
+
+# apply rename on list (columns) or dict (filter) args
+def patch_legacy_arg (arg):
+ if isinstance(arg,list):
+ return [rename(x) for x in arg]
+ if isinstance(arg,dict):
+ return dict ( [ (rename(k),v) for (k,v) in arg.iteritems() ] )
+ return arg
+
+def factory (legacyname, newname):
+ # locate new class
+ newclass=getattr(import_deep("PLC.Methods."+newname),newname)
+ # create class for legacy name
+ legacyclass = type(legacyname,(newclass,),
+ {"__doc__":"Legacy method - please use %s instead"%newname})
+ for internal in ["roles","accepts","returns"]:
+ setattr(legacyclass,internal,getattr(newclass,internal))
+ # turn off type checking, as introspection code fails on wrapped_call
+ setattr(legacyclass,"skip_typecheck",True)
+ # rewrite call
+ def wrapped_call (self,auth,*args, **kwds):
+ newargs=[patch_legacy_arg(x) for x in args]
+ newkwds=dict ( [ (k,patch_legacy_arg(v)) for (k,v) in kwds.iteritems() ] )
+ return getattr(newclass,"call")(self,auth,*newargs,**newkwds)
+ setattr(legacyclass,"call",wrapped_call)
+
+ return legacyclass
+
+# see NodeNetworks for attempts to avoid this
+
+AddSliceAttributeType=factory("AddSliceAttributeType","AddTagType")
+DeleteSliceAttributeType=factory("DeleteSliceAttributeType","DeleteTagType")
+GetSliceAttributeTypes=factory("GetSliceAttributeTypes","GetTagTypes")
+UpdateSliceAttributeType=factory("UpdateSliceAttributeType","UpdateTagType")
+AddNodeNetworkSettingType=factory("AddNodeNetworkSettingType","AddTagType")
+DeleteNodeNetworkSettingType=factory("DeleteNodeNetworkSettingType","DeleteTagType")
+GetNodeNetworkSettingTypes=factory("GetNodeNetworkSettingTypes","GetTagTypes")
+UpdateNodeNetworkSettingType=factory("UpdateNodeNetworkSettingType","UpdateTagType")
--- /dev/null
+# supposed to be managed manually
+# syntax is modulename.methodname
+
+# xxx could we use __all__ and have each module define its
+# own set of methods ?
+
+__all__ = """
+NodeNetworks
+Types
+""".split()
+
from PLC.Nodes import Node, Nodes
from PLC.Persons import Person, Persons
-class Method:
+# we inherit object because we use new-style classes for legacy methods
+class Method (object):
"""
Base class for all PLCAPI functions. At a minimum, all PLCAPI
functions must define:
try:
start = time.time()
- (min_args, max_args, defaults) = self.args()
+
+ # legacy code cannot be type-checked, due to the way Method.args() works
+ if not hasattr(self,"skip_typecheck"):
+ (min_args, max_args, defaults) = self.args()
- # Check that the right number of arguments were passed in
- if len(args) < len(min_args) or len(args) > len(max_args):
- raise PLCInvalidArgumentCount(len(args), len(min_args), len(max_args))
+ # Check that the right number of arguments were passed in
+ if len(args) < len(min_args) or len(args) > len(max_args):
+ raise PLCInvalidArgumentCount(len(args), len(min_args), len(max_args))
- for name, value, expected in zip(max_args, args, self.accepts):
- self.type_check(name, value, expected, args)
+ for name, value, expected in zip(max_args, args, self.accepts):
+ self.type_check(name, value, expected, args)
result = self.call(*args, **kwds)
runtime = time.time() - start
That represents the minimum and maximum sets of arguments that
this function accepts and the defaults for the optional arguments.
"""
-
+
# Inspect call. Remove self from the argument list.
max_args = self.call.func_code.co_varnames[1:self.call.func_code.co_argcount]
defaults = self.call.func_defaults
if role is not None:
self.auth['Role'] = role
- for method in PLC.Methods.methods:
+ for method in PLC.Methods.methods + PLC.API.PLCAPI.legacy_map.keys():
api_function = self.api.callable(method)
if self.server is None: