Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp> --- Changes v1 -> v2: - dynamic configuration change - trivial update for depending patch change --- ryu/services/vrrp/manager.py | 162 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 ryu/services/vrrp/manager.py
diff --git a/ryu/services/vrrp/manager.py b/ryu/services/vrrp/manager.py new file mode 100644 index 0000000..be1151c --- /dev/null +++ b/ryu/services/vrrp/manager.py @@ -0,0 +1,162 @@ +# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation. +# Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +VRRP manager that manages VRRP router instances +""" + +import gevent +from gevent.queue import Queue + +from ryu.base import app_manager +from ryu.controller import handler +from ryu.services.vrrp import event as vrrp_event +from ryu.services.vrrp import monitor as vrrp_monitor +from ryu.services.vrrp import router as vrrp_router + + +class VRRPInstance(object): + def __init__(self, name, monitor_name, config, interface, + vrrp_router_, interface_monitor): + super(VRRPInstance, self).__init__() + self.name = name # vrrp_router.name + self.monitor_name = monitor_name # interface_monitor.name + self.config = config + self.interface = interface + self.vrrp_router = vrrp_router_ + self.interface_monitor = interface_monitor + + +class VRRPManager(app_manager.RyuApp): + @staticmethod + def _instance_name(interface, vrid, is_ipv6): + ip_version = 'ipv6' if is_ipv6 else 'ipv4' + return 'VRRP-Router-%s-%d-%s' % (str(interface), vrid, ip_version) + + def __init__(self, *args, **kwargs): + super(VRRPManager, self).__init__(*args, **kwargs) + self._args = args + self._kwargs = kwargs + self.name = vrrp_event.VRRP_MANAGER_NAME + self._instances = {} # name -> VRRPInstance + self.shutdown = Queue() + + def start(self): + self.threads.append(gevent.spawn(self._shutdown_loop)) + super(VRRPManager, self).start() + + @handler.set_ev_cls(vrrp_event.EventVRRPConfigRequest) + def config_request_handler(self, ev): + config = ev.config + interface = ev.interface + name = self._instance_name(interface, config.vrid, config.is_ipv6) + if name in self._instances: + rep = vrrp_event.EventVRRPConfigReply(None, interface, config) + self.reply_to_request(ev, rep) + return + + monitor = vrrp_monitor.VRRPInterfaceMonitor.factory( + interface, config, name, *self._args, **self._kwargs) + router = vrrp_router.VRRPRouter.factory( + name, monitor.name, interface, config, *self._args, **self._kwargs) + + # Event piping + # vrrp_router -> vrrp_manager + # EventVRRPStateChanged to vrrp_manager is handled by framework + # vrrp_manager -> vrrp_rouer + self.register_observer(vrrp_event.EventVRRPShutdownRequest, + router.name) + # vrrp_router -> vrrp_monitor + router.register_observer(vrrp_event.EventVRRPStateChanged, + monitor.name) + router.register_observer(vrrp_event.EventVRRPTransmitRequest, + monitor.name) + # vrrp_interface_monitor -> vrrp_router + monitor.register_observer(vrrp_event.EventVRRPReceived, router.name) + + instance = VRRPInstance(name, monitor.name, + config, interface, router, monitor) + self._instances[name] = instance + #self.logger.debug('report_bricks') + #app_manager.AppManager.get_instance().report_bricks() # debug + monitor.start() + router.start() + + rep = vrrp_event.EventVRRPConfigReply(router.name, interface, config) + self.reply_to_request(ev, rep) + + def _proxy_event(self, ev): + name = ev.instance_name + instance = self._instances.get(name, None) + if not instance: + self.logger.info('unknown vrrp router %s', name) + return + self.send_event(instance.vrrp_router.name, ev) + + @handler.set_ev_cls(vrrp_event.EventVRRPShutdownRequest) + def shutdown_request_handler(self, ev): + self._proxy_event(ev) + + @handler.set_ev_cls(vrrp_event.EventVRRPConfigChangeRequest) + def config_change_request_handler(self, ev): + self._proxy_event(ev) + + @handler.set_ev_cls(vrrp_event.EventVRRPStateChanged) + def state_change_handler(self, ev): + if ev.old_state and ev.new_state == vrrp_event.VRRP_STATE_INITIALIZE: + instance = self._instances.get(ev.instance_name, None) + assert instance is not None + self.shutdown.put(instance) + + def _shutdown_loop(self): + app_mgr = app_manager.AppManager.get_instance() + while self.is_active or not self.shutdown.empty(): + instance = self.shutdown.get() + app_mgr.uninstantiate(instance.vrrp_router) + app_mgr.uninstantiate(instance.interface_monitor) + del self._instances[instance.name] + + @handler.set_ev_cls(vrrp_event.EventVRRPListRequest) + def list_request_handler(self, ev): + instance_name = ev.instance_name + if instance_name is None: + instance_list = [vrrp_event.VRRPInstance( + instance.name, instance.monitor_name, + instance.config, instance.interface) + for instance in self._instances.values()] + else: + instance = self._instances.get(instance_name, None) + if instance is None: + instance_list = [] + else: + instance_list = [vrrp_event.VRRPInstance(instance_name, + instance.config, + instance.interface)] + + vrrp_list = vrrp_event.EventVRRPListReply(instance_list) + self.reply_to_request(ev, vrrp_list) + + @handler.set_ev_cls(vrrp_event.EventVRRPRegisterRequest) + def register_request_handler(self, ev): + instance = self._instances.get(ev.instance_name, None) + if instance is None: + return + if ev.register: + instance.vrrp_router.regisger_observer( + vrrp_event.EventVRRPStateChanged, ev.observer_name) + else: + instance.vrrp_router.unregister_observer( + vrrp_event.EventVRRPStateChanged, ev.observer_name) -- 1.7.10.4 ------------------------------------------------------------------------------ Precog is a next-generation analytics platform capable of advanced analytics on semi-structured data. The platform includes APIs for building apps and a phenomenal toolset for data science. Developers can use our toolset for easy data analysis & visualization. Get a free account! http://www2.precog.com/precogplatform/slashdotnewsletter _______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel