generic to handle the manager instance in the api too
[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.info("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     # in the simplest case these can be redefined to the class/module objects to be used
46     # see pl.py for an example
47     # some descendant of SfaApi
48     def api_class (self) : pass
49     # in practical terms these are modules for now
50     def registry_class (self) : pass
51     def slicemgr_class (self) : pass
52     def aggregate_class (self) : pass
53     def component_class (self) : pass
54
55
56     # build an API object
57     # insert a manager instance 
58     def make_api (self, *args, **kwargs):
59         # interface is a required arg
60         if not 'interface' in kwargs:
61             logger.fatal("Generic.make_api: no interface found")
62         api = self.api_class()(*args, **kwargs)
63         interface=kwargs['interface']
64         # or simpler, interface=api.interface
65         manager = self.make_manager(interface)
66         api.manager = ManagerWrapper(manager,interface)
67         return api
68
69     def make_manager (self, interface):
70         """
71         interface expected in ['registry', 'aggregate', 'slice', 'component']
72         flavour is e.g. 'pl' or 'max' or whatever
73         """
74         flavour = self.flavour
75         message="Generic.make_manager for interface=%s and flavour=%s"%(interface,flavour)
76         
77         classname = "%s_class"%interface
78         try:
79             module = getattr(self,classname)()
80             logger.info("%s : %s"%(message,module))
81             return module
82         except:
83             logger.log_exc(message)
84             logger.fatal("Aborting")
85         
86 # former logic was
87 #        basepath = 'sfa.managers'
88 #        qualified = "%s.%s_manager_%s"%(basepath,interface,flavour)
89 #        generic = "%s.%s_manager"%(basepath,interface)
90 #
91 #        try: 
92 #            manager = __import__(qualified, fromlist=[basepath])
93 #            logger.info ("%s: loaded %s"%(message,qualified))
94 #        except:
95 #            try:
96 #                manager = __import__ (generic, fromlist=[basepath])
97 #                if flavour != 'pl' : 
98 #                    logger.warn ("%s: using generic with flavour!='pl'"%(message))
99 #                logger.info("%s: loaded %s"%(message,generic))
100 #            except:
101 #                logger.log_exc("%s: unable to import either %s or %s"%(message,qualified,generic))
102 #                logger.fatal("Aborted")
103 #        return manager
104