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 or registry
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
25 def __init__(self, flavour, config):
26 self.flavour = flavour
30 # example flavour='pl' -> sfa.generic.pl.pl()
32 def the_flavour(flavour=None, config=None):
36 flavour = config.SFA_GENERIC_FLAVOUR
37 flavour = flavour.lower()
38 # mixed = flavour.capitalize()
39 module_path = "sfa.generic.%s" % flavour
40 classname = "%s" % flavour
41 logger.debug("Generic.the_flavour with flavour=%s" % flavour)
43 module = __import__(module_path, globals(), locals(), [classname])
44 return getattr(module, classname)(flavour, config)
47 "Cannot locate generic instance with flavour=%s" % flavour)
49 # provide default for importer_class
50 def importer_class(self):
53 # in the simplest case these can be redefined to the class/module objects to be used
54 # see pl.py for an example
55 # some descendant of SfaApi
56 def api_class(self): pass
57 # the python classes to use to build up the context
59 def registry_class(self): pass
61 def aggregate_class(self): pass
63 def component_class(self): pass
66 # insert a manager instance
67 def make_api(self, *args, **kwargs):
68 # interface is a required arg
69 if not 'interface' in kwargs:
70 logger.critical("Generic.make_api: no interface found")
71 api = self.api_class()(*args, **kwargs)
72 # xxx can probably drop support for managers implemented as modules
73 # which makes it a bit awkward
74 manager_class_or_module = self.make_manager(api.interface)
75 driver = self.make_driver(api)
76 # arrange stuff together
77 # add a manager wrapper
78 manager_wrap = ManagerWrapper(
79 manager_class_or_module, api.interface, api.config)
80 api.manager = manager_wrap
81 # add it in api as well; driver.api is set too as part of make_driver
85 def make_manager(self, interface):
87 interface expected in ['registry', 'aggregate', 'component']
88 flavour is e.g. 'pl' or 'max' or whatever
90 flavour = self.flavour
91 message = "Generic.make_manager for interface=%s and flavour=%s" % (
94 classname = "%s_manager_class" % interface
96 module_or_class = getattr(self, classname)()
97 logger.debug("%s : %s" % (message, module_or_class))
98 # this gets passed to ManagerWrapper that will
99 # call the class constructor if it's a class,
100 # or use the module as is if it's a module
101 # so bottom line is, don't try the constructor here
102 return module_or_class
104 logger.log_exc(message)
107 # need interface to select the right driver
108 def make_driver(self, api):
110 interface = api.interface
111 flavour = self.flavour
112 message = "Generic.make_driver for flavour=%s and interface=%s" % (
115 if interface == "component":
116 classname = "component_driver_class"
118 classname = "driver_class"
120 class_obj = getattr(self, classname)()
121 logger.debug("%s : %s" % (message, class_obj))
122 return class_obj(api)
124 logger.log_exc(message)