solve application dependency via @set_ev_cls
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 <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
47f1d19538
commit
73ae9dd109
ryu
@ -17,9 +17,10 @@
|
|||||||
import inspect
|
import inspect
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
from ryu import utils
|
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.controller import Datapath
|
||||||
from ryu.controller.event import EventRequestBase, EventReplyBase
|
from ryu.controller.event import EventRequestBase, EventReplyBase
|
||||||
from ryu.lib import hub
|
from ryu.lib import hub
|
||||||
@ -158,15 +159,13 @@ class AppManager(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def load_apps(self, app_lists):
|
def load_apps(self, app_lists):
|
||||||
for app_cls_name in itertools.chain.from_iterable([app_list.split(',')
|
app_lists = [app for app
|
||||||
for app_list
|
in itertools.chain.from_iterable(app.split(',')
|
||||||
in app_lists]):
|
for app in app_lists)]
|
||||||
LOG.info('loading app %s', app_cls_name)
|
while len(app_lists) > 0:
|
||||||
|
app_cls_name = app_lists.pop(0)
|
||||||
|
|
||||||
# for now, only single instance of a given module
|
LOG.info('loading app %s', app_cls_name)
|
||||||
# Do we need to support multiple instances?
|
|
||||||
# Yes, maybe for slicing.
|
|
||||||
assert app_cls_name not in self.applications_cls
|
|
||||||
|
|
||||||
cls = self.load_app(app_cls_name)
|
cls = self.load_app(app_cls_name)
|
||||||
if cls is None:
|
if cls is None:
|
||||||
@ -174,10 +173,18 @@ class AppManager(object):
|
|||||||
|
|
||||||
self.applications_cls[app_cls_name] = cls
|
self.applications_cls[app_cls_name] = cls
|
||||||
|
|
||||||
|
services = []
|
||||||
for key, context_cls in cls.context_iteritems():
|
for key, context_cls in cls.context_iteritems():
|
||||||
cls = self.contexts_cls.setdefault(key, context_cls)
|
cls = self.contexts_cls.setdefault(key, context_cls)
|
||||||
assert cls == 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):
|
def create_contexts(self):
|
||||||
for key, cls in self.contexts_cls.items():
|
for key, cls in self.contexts_cls.items():
|
||||||
context = cls()
|
context = cls()
|
||||||
|
@ -61,8 +61,7 @@ def main():
|
|||||||
|
|
||||||
log.init_log()
|
log.init_log()
|
||||||
|
|
||||||
# always enable ofp for now.
|
app_lists = CONF.app_lists + CONF.app
|
||||||
app_lists = CONF.app_lists + CONF.app + ['ryu.controller.ofp_handler']
|
|
||||||
|
|
||||||
app_mgr = AppManager()
|
app_mgr = AppManager()
|
||||||
app_mgr.load_apps(app_lists)
|
app_mgr.load_apps(app_lists)
|
||||||
@ -71,8 +70,10 @@ def main():
|
|||||||
|
|
||||||
services = []
|
services = []
|
||||||
|
|
||||||
ctlr = controller.OpenFlowController()
|
# TODO: do the following in app_manager's instantiate_apps()
|
||||||
thr = hub.spawn(ctlr)
|
ofpapp = controller.start_service(app_mgr)
|
||||||
|
if ofpapp:
|
||||||
|
thr = hub.spawn(ofpapp)
|
||||||
services.append(thr)
|
services.append(thr)
|
||||||
|
|
||||||
webapp = wsgi.start_service(app_mgr)
|
webapp = wsgi.start_service(app_mgr)
|
||||||
|
@ -321,3 +321,9 @@ def datapath_connection_factory(socket, address):
|
|||||||
dpid_str = dpid_to_str(datapath.id)
|
dpid_str = dpid_to_str(datapath.id)
|
||||||
LOG.error("Error in the datapath %s from %s", dpid_str, address)
|
LOG.error("Error in the datapath %s from %s", dpid_str, address)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def start_service(app_mgr):
|
||||||
|
for app in app_mgr.applications:
|
||||||
|
if app.endswith('ofp_handler'):
|
||||||
|
return OpenFlowController()
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
from ryu.controller import ofp_event
|
|
||||||
|
|
||||||
LOG = logging.getLogger('ryu.controller.handler')
|
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)
|
# LOG.debug('instance %s k %s m %s', i, _k, m)
|
||||||
if _is_ev_cls(m):
|
if _is_ev_cls(m):
|
||||||
i.register_handler(m.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
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
|
from ryu.controller import handler
|
||||||
from ryu import ofproto
|
from ryu import ofproto
|
||||||
from ryu import utils
|
from ryu import utils
|
||||||
from . import event
|
from . import event
|
||||||
@ -75,3 +76,6 @@ class EventOFPStateChange(event.EventBase):
|
|||||||
def __init__(self, dp):
|
def __init__(self, dp):
|
||||||
super(EventOFPStateChange, self).__init__()
|
super(EventOFPStateChange, self).__init__()
|
||||||
self.datapath = dp
|
self.datapath = dp
|
||||||
|
|
||||||
|
|
||||||
|
handler.register_service('ryu.controller.ofp_handler')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user