ece7e2b857317051f3aa769b82812a7e37eb0390
[sfa.git] / sfa / generic / __init__.py
1 from sfa.util.sfalogging import logger
2 from sfa.util.config import Config
3
4 from sfa.managers.managerwrapper import ManagerWrapper
5
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
11
12
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 
15 # from config.
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
19
20 # needs refinements to cache more efficiently, esp. wrt the config
21
22 class Generic:
23
24     def __init__ (self, flavour, config):
25         self.flavour=flavour
26         self.config=config
27
28     # proof of concept
29     # example flavour='pl' -> sfa.generic.pl.pl()
30     @staticmethod
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)
39         try:
40             module = __import__ (module_path, globals(), locals(), [classname])
41             return getattr(module, classname)(flavour,config)
42         except:
43             logger.log_exc("Cannot locate generic instance with flavour=%s"%flavour)
44
45     # provide default for importer_class
46     def importer_class (self): 
47         return None
48
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
58
59
60     # build an API object
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)
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         # add it in api as well; driver.api is set too as part of make_driver
76         api.driver=driver
77         return api
78
79     def make_manager (self, interface):
80         """
81         interface expected in ['registry', 'aggregate', 'slicemgr', 'component']
82         flavour is e.g. 'pl' or 'max' or whatever
83         """
84         flavour = self.flavour
85         message="Generic.make_manager for interface=%s and flavour=%s"%(interface,flavour)
86         
87         classname = "%s_manager_class"%interface
88         try:
89             module_or_class = getattr(self,classname)()
90             logger.debug("%s : %s"%(message,module_or_class))
91             # this gets passed to ManagerWrapper that will call the class constructor 
92             # if it's a class, or use the module as is if it's a module
93             # so bottom line is, don't try the constructor here
94             return module_or_class
95         except:
96             logger.log_exc_critical(message)
97         
98     # need interface to select the right driver
99     def make_driver (self, api):
100         config=api.config
101         interface=api.interface
102         flavour = self.flavour
103         message="Generic.make_driver for flavour=%s and interface=%s"%(flavour,interface)
104         
105         if interface == "component":
106             classname = "component_driver_class"
107         else:
108             classname = "driver_class"
109         try:
110             class_obj = getattr(self,classname)()
111             logger.debug("%s : %s"%(message,class_obj))
112             return class_obj(api)
113         except:
114             logger.log_exc_critical(message)
115