The ryu-manager creates structures which applications share.
Currently it is hard-coded in ryu-managers. Concretely network.Network and
dpset.DPSet. It is difficult to maintain the code appropriately by hand.
When the application is changed or new application comes in, ryu-manager
also must be updated.
So introduce the notion of application context so that application manager
can determine what structures applications want to share and create them.

Signed-off-by: Isaku Yamahata <[email protected]>
---
 bin/ryu-manager         |   15 +++++-
 ryu/base/app_manager.py |  120 +++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 118 insertions(+), 17 deletions(-)

diff --git a/bin/ryu-manager b/bin/ryu-manager
index cb57e62..a6944e2 100755
--- a/bin/ryu-manager
+++ b/bin/ryu-manager
@@ -49,11 +49,18 @@ def main():
     _args = FLAGS(sys.argv)
     log.init_log()
 
-    nw = network.Network()
-    dpset_ = dpset.DPSet()
+    # to make non-converted apps work. Once all of them converted,
+    # this will be removed.
+    kwargs = {
+        'network': network.Network(),
+        'dpset': dpset.DPSet(),
+        }
 
     app_mgr = AppManager()
-    app_mgr.load_apps(FLAGS.app_lists, network=nw, dpset=dpset_)
+    app_mgr.load_apps(FLAGS.app_lists)
+    contexts = app_mgr.create_contexts()
+    contexts.update(kwargs)
+    app_mgr.instantiate_apps(**contexts)
 
     services = []
 
@@ -67,6 +74,8 @@ def main():
     services.append(thr)
 
     gevent.joinall(services)
+    app_mgr.close()
+
 
 if __name__ == "__main__":
     main()
diff --git a/ryu/base/app_manager.py b/ryu/base/app_manager.py
index 4aae290..0d91f70 100644
--- a/ryu/base/app_manager.py
+++ b/ryu/base/app_manager.py
@@ -23,24 +23,116 @@ from ryu.controller.handler import register_instance
 LOG = logging.getLogger('ryu.base.app_manager')
 
 
+_NOARG_APP_CONTEXTS = {}
+
+
+def noarg_app_context_factory(cls):
+    """
+    wrapper function to context
+    Ryu application contexts requires cls.__init__(self, *args, **kwargs)
+    This functions wraps the class whose init signature is __init__(self)
+    """
+    if cls in _NOARG_APP_CONTEXTS:
+        return _NOARG_APP_CONTEXTS[cls]
+
+    def _noarg_app_context_factory(*_args, **_kwargs):
+        return cls()
+    _NOARG_APP_CONTEXTS[cls] = _noarg_app_context_factory
+    return _noarg_app_context_factory
+
+
+class RyuAppContext(object):
+    """
+    Base class for Ryu application context
+    """
+    def __init__(self, *_args, **_kwargs):
+        super(RyuAppContext, self).__init__()
+
+    def close(self):
+        pass
+
+
+class RyuApp(object):
+    """
+    Base class for Ryu network application
+    """
+    _CONTEXTS = {}
+
+    @classmethod
+    def context_dict(cls):
+        """
+        Return list of application context
+        """
+        return cls._CONTEXTS
+
+    @classmethod
+    def context_create(cls, name, *args, **kwargs):
+        """
+        Return application context
+        """
+        return cls._CONTEXTS[name](*args, **kwargs)
+
+    def __init__(self, *_args, **_kwargs):
+        super(RyuApp, self).__init__()
+
+    def close(self):
+        """
+        teardown method.
+        The method name, close, is chosen for python context manager
+        """
+        pass
+
+
 class AppManager(object):
     def __init__(self):
+        self.applications_cls = {}
         self.applications = {}
+        self.contexts_cls = {}
+        self.contexts = {}
+
+    def load_apps(self, app_lists):
+        for app_cls_name in itertools.chain.from_iterable([app_list.split(',')
+                                                           for app_list
+                                                           in app_lists]):
+            LOG.info('loading app %s', app_cls_name)
+
+            # for now, only single instance of a given module
+            # Do we need to support multiple instances?
+            # Yes, maybe for slicing.
+            assert app_cls_name not in self.applications_cls
+
+            cls = utils.import_object(app_cls_name)
+            self.applications_cls[app_cls_name] = cls
+
+            for key, context_cls in cls.context_dict().items():
+                cls = self.contexts_cls.setdefault(key, context_cls)
+                assert cls == context_cls
+
+    def create_contexts(self, *args, **kwargs):
+        for key, cls in self.contexts_cls.items():
+            self.contexts[key] = cls(*args, **kwargs)
+        return self.contexts
 
-    def load(self, app_mod_name, *args, **kwargs):
-        # for now, only single instance of a given module
-        # Do we need to support multiple instances?
-        # Yes, maybe for slicing.
-        assert app_mod_name not in self.applications
+    def instantiate_apps(self, *args, **kwargs):
+        kwargs.update(self.contexts)
 
-        cls = utils.import_object(app_mod_name)
-        app = cls(*args, **kwargs)
-        register_instance(app)
+        for app_name, cls in self.applications_cls.items():
+            # for now, only single instance of a given module
+            # Do we need to support multiple instances?
+            # Yes, maybe for slicing.
+            LOG.info('instantiating app %s', app_name)
+            assert app_name not in self.applications
+            app = cls(*args, **kwargs)
+            register_instance(app)
+            self.applications[app_name] = app
 
-        self.applications[app_mod_name] = app
+    def close(self):
+        def close_all(close_dict):
+            for app in close_dict:
+                close_method = getattr(app, 'close', None)
+                if callable(close_method):
+                    close_method()
+            close_dict.clear()
 
-    def load_apps(self, app_lists, *args, **kwargs):
-        for app in itertools.chain.from_iterable([app_list.split(',')
-                                                  for app_list in app_lists]):
-            self.load(app, *args, **kwargs)
-            LOG.info('loading app %s', app)
+        close_all(self.applications)
+        close_all(self.contexts)
-- 
1.7.1.1


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to