On Fri, 8 Nov 2013 10:20:57 +0900
FUJITA Tomonori <[email protected]> wrote:

> Currently, ryu always starts ofp application because ryu doesn't know
> applications that an user specifies needs ofp application or not. So
> you can't run two ryu instances even if one of them doesn't use ofp
> application because two instances tries to listen the same port.
> 
> The root problem is that there is no way to represent dependency
> between applications. The patch to invent our own json format to
> represent such was proposed ago but I'm still not sure we really need
> such complicity.
> 
> This tries to solve the problem simply. A module defining events for
> an application calls register_service() to declare which application
> generates the events, e.g., ofp_event.py call register_service() with
> 'ofp_handler' argument. If an application starts including @set_ev_cls
> for ofp_event, ryu-manager starts ofp application (ofp_handler).
> 
> Signed-off-by: FUJITA Tomonori <[email protected]>
> ---
>  ryu/base/app_manager.py      | 18 +++++++++---------
>  ryu/cmd/manager.py           | 11 ++++++-----
>  ryu/controller/controller.py |  6 ++++++
>  ryu/controller/handler.py    | 24 ++++++++++++++++++++++--
>  ryu/controller/ofp_event.py  |  4 ++++
>  5 files changed, 47 insertions(+), 16 deletions(-)

Applied with a fix to solve the dependency of applications invoked via
_CONTEXTS.

---
 ryu/base/app_manager.py      | 25 ++++++++++++++++---------
 ryu/cmd/manager.py           | 11 ++++++-----
 ryu/controller/controller.py |  6 ++++++
 ryu/controller/handler.py    | 24 ++++++++++++++++++++++--
 ryu/controller/ofp_event.py  |  4 ++++
 5 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/ryu/base/app_manager.py b/ryu/base/app_manager.py
index b39d6cc..a5f1c4c 100644
--- a/ryu/base/app_manager.py
+++ b/ryu/base/app_manager.py
@@ -17,9 +17,10 @@
 import inspect
 import itertools
 import logging
+import sys
 
 from ryu import utils
-from ryu.controller.handler import register_instance
+from ryu.controller.handler import register_instance, get_dependent_services
 from ryu.controller.controller import Datapath
 from ryu.controller.event import EventRequestBase, EventReplyBase
 from ryu.lib import hub
@@ -158,15 +159,13 @@ class AppManager(object):
         return None
 
     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)
+        app_lists = [app for app
+                     in itertools.chain.from_iterable(app.split(',')
+                                                      for app in app_lists)]
+        while len(app_lists) > 0:
+            app_cls_name = app_lists.pop(0)
 
-            # 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
+            LOG.info('loading app %s', app_cls_name)
 
             cls = self.load_app(app_cls_name)
             if cls is None:
@@ -174,10 +173,18 @@ class AppManager(object):
 
             self.applications_cls[app_cls_name] = cls
 
+            services = []
             for key, context_cls in cls.context_iteritems():
                 cls = self.contexts_cls.setdefault(key, context_cls)
                 assert cls == context_cls
 
+                if issubclass(context_cls, RyuApp):
+                    services.extend(get_dependent_services(context_cls))
+
+            services.extend(get_dependent_services(cls))
+            if services:
+                app_lists.extend(services)
+
     def create_contexts(self):
         for key, cls in self.contexts_cls.items():
             context = cls()
diff --git a/ryu/cmd/manager.py b/ryu/cmd/manager.py
index cc1ea74..8386705 100755
--- a/ryu/cmd/manager.py
+++ b/ryu/cmd/manager.py
@@ -61,8 +61,7 @@ def main():
 
     log.init_log()
 
-    # always enable ofp for now.
-    app_lists = CONF.app_lists + CONF.app + ['ryu.controller.ofp_handler']
+    app_lists = CONF.app_lists + CONF.app
 
     app_mgr = AppManager()
     app_mgr.load_apps(app_lists)
@@ -71,9 +70,11 @@ def main():
 
     services = []
 
-    ctlr = controller.OpenFlowController()
-    thr = hub.spawn(ctlr)
-    services.append(thr)
+    # TODO: do the following in app_manager's instantiate_apps()
+    ofpapp = controller.start_service(app_mgr)
+    if ofpapp:
+        thr = hub.spawn(ofpapp)
+        services.append(thr)
 
     webapp = wsgi.start_service(app_mgr)
     if webapp:
diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py
index d6bc3de..fc6e116 100644
--- a/ryu/controller/controller.py
+++ b/ryu/controller/controller.py
@@ -321,3 +321,9 @@ def datapath_connection_factory(socket, address):
                 dpid_str = dpid_to_str(datapath.id)
             LOG.error("Error in the datapath %s from %s", dpid_str, address)
             raise
+
+
+def start_service(app_mgr):
+    for app in app_mgr.applications:
+        if app.endswith('ofp_handler'):
+            return OpenFlowController()
diff --git a/ryu/controller/handler.py b/ryu/controller/handler.py
index ba45b0d..d5f57cd 100644
--- a/ryu/controller/handler.py
+++ b/ryu/controller/handler.py
@@ -16,8 +16,7 @@
 
 import inspect
 import logging
-
-from ryu.controller import ofp_event
+import sys
 
 LOG = logging.getLogger('ryu.controller.handler')
 
@@ -63,3 +62,24 @@ def register_instance(i):
         # LOG.debug('instance %s k %s m %s', i, _k, m)
         if _is_ev_cls(m):
             i.register_handler(m.ev_cls, m)
+
+
+def get_dependent_services(cls):
+    services = []
+    for _k, m in inspect.getmembers(cls, inspect.ismethod):
+        if _is_ev_cls(m):
+            service = getattr(sys.modules[m.ev_cls.__module__],
+                              '_SERVICE_NAME', None)
+            if service:
+                # avoid cls that registers the own events (like ofp_handler)
+                if cls.__module__ != service:
+                    services.append(service)
+
+    services = list(set(services))
+    return services
+
+
+def register_service(service):
+    frm = inspect.stack()[1]
+    m = inspect.getmodule(frm[0])
+    m._SERVICE_NAME = service
diff --git a/ryu/controller/ofp_event.py b/ryu/controller/ofp_event.py
index 566b834..124a93e 100644
--- a/ryu/controller/ofp_event.py
+++ b/ryu/controller/ofp_event.py
@@ -16,6 +16,7 @@
 
 import inspect
 
+from ryu.controller import handler
 from ryu import ofproto
 from ryu import utils
 from . import event
@@ -75,3 +76,6 @@ class EventOFPStateChange(event.EventBase):
     def __init__(self, dp):
         super(EventOFPStateChange, self).__init__()
         self.datapath = dp
+
+
+handler.register_service('ryu.controller.ofp_handler')
-- 
1.8.3.4 (Apple Git-47)


------------------------------------------------------------------------------
DreamFactory - Open Source REST & JSON Services for HTML5 & Native Apps
OAuth, Users, Roles, SQL, NoSQL, BLOB Storage and External API Access
Free app hosting. Or install the open source package on any LAMP server.
Sign up and see examples for AngularJS, jQuery, Sencha Touch and Native!
http://pubads.g.doubleclick.net/gampad/clk?id=63469471&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to