1 from sfa.util.sfalogging import logger
2 from sfa.util.config import Config
4 from sfa.managers.managerwrapper import ManagerWrapper
6 # a bundle is the combination of
7 # (*) an api that reacts on the incoming requests to trigger the API methods
8 # (*) a manager that implements the function of the service,
9 # either aggregate, registry, or slicemgr
10 # (*) a driver that controls the underlying testbed
13 # The Generic class is a utility that uses the configuration to figure out
14 # which combination of these pieces need to be put together
16 # this extra indirection is needed to adapt to the current naming scheme
17 # where we have 'pl' and 'plc' and components and the like, that does not
18 # yet follow a sensible scheme
20 # needs refinements to cache more efficiently, esp. wrt the config
24 def __init__ (self, flavour, config):
29 # example flavour='pl' -> sfa.generic.pl.pl()
31 def the_flavour (flavour=None, config=None):
32 if config is None: config=Config()
33 if flavour is None: flavour=config.SFA_GENERIC_FLAVOUR
34 flavour = flavour.lower()
35 #mixed = flavour.capitalize()
36 module_path="sfa.generic.%s"%flavour
37 classname="%s"%flavour
38 logger.debug("Generic.the_flavour with flavour=%s"%flavour)
40 module = __import__ (module_path, globals(), locals(), [classname])
41 return getattr(module, classname)(flavour,config)
43 logger.log_exc("Cannot locate generic instance with flavour=%s"%flavour)
45 # provide default for importer_class
46 def importer_class (self):
49 # in the simplest case these can be redefined to the class/module objects to be used
50 # see pl.py for an example
51 # some descendant of SfaApi
52 def api_class (self) : pass
53 # the python classes to use to build up the context
54 def registry_class (self) : pass
55 def slicemgr_class (self) : pass
56 def aggregate_class (self) : pass
57 def component_class (self) : pass
61 # insert a manager instance
62 def make_api (self, *args, **kwargs):
63 # interface is a required arg
64 if not 'interface' in kwargs:
65 logger.critical("Generic.make_api: no interface found")
66 api = self.api_class()(*args, **kwargs)
67 # xxx can probably drop support for managers implemented as modules
68 # which makes it a bit awkward
69 manager_class_or_module = self.make_manager(api.interface)
70 driver = self.make_driver (api.config, api.interface)
71 ### arrange stuff together
72 # add a manager wrapper
73 manager_wrap = ManagerWrapper(manager_class_or_module,api.interface,api.config)
74 api.manager=manager_wrap
75 # insert driver in manager
76 logger.debug("Setting manager.driver, manager=%s"%manager_class_or_module)
77 # xxx this should go into the object and not the class !?!
78 manager_class_or_module.driver=driver
79 # add it in api as well for convenience
83 def make_manager (self, interface):
85 interface expected in ['registry', 'aggregate', 'slicemgr', 'component']
86 flavour is e.g. 'pl' or 'max' or whatever
88 flavour = self.flavour
89 message="Generic.make_manager for interface=%s and flavour=%s"%(interface,flavour)
91 classname = "%s_manager_class"%interface
93 module_or_class = getattr(self,classname)()
94 logger.debug("%s : %s"%(message,module_or_class))
95 # this gets passed to ManagerWrapper that will call the class constructor
96 # if it's a class, or use the module as is if it's a module
97 # so bottom line is, don't try the constructor here
98 return module_or_class
100 logger.log_exc_critical(message)
102 # need interface to select the right driver
103 def make_driver (self, config, interface):
104 flavour = self.flavour
105 message="Generic.make_driver for flavour=%s and interface=%s"%(flavour,interface)
107 if interface == "component":
108 classname = "component_driver_class"
110 classname = "driver_class"
112 class_obj = getattr(self,classname)()
113 logger.debug("%s : %s"%(message,class_obj))
114 return class_obj(config)
116 logger.log_exc_critical(message)