Signed-off-by: FUJITA Tomonori <[email protected]>
---
 ryu/services/protocols/vrrp/event.py       |   4 +-
 ryu/services/protocols/vrrp/rpc_manager.py | 197 +++++++++++++++++++++++++++++
 2 files changed, 199 insertions(+), 2 deletions(-)
 create mode 100644 ryu/services/protocols/vrrp/rpc_manager.py

diff --git a/ryu/services/protocols/vrrp/event.py 
b/ryu/services/protocols/vrrp/event.py
index b1872c6..e339a96 100644
--- a/ryu/services/protocols/vrrp/event.py
+++ b/ryu/services/protocols/vrrp/event.py
@@ -116,11 +116,11 @@ class VRRPConfig(object):
     advertmisement_interval is in seconds as float. (Not in centiseconds)
     """
     def __init__(self, version=vrrp.VRRP_VERSION_V3, vrid=None,
-                 admin_state=None,
+                 admin_state=True,
                  priority=vrrp.VRRP_PRIORITY_BACKUP_DEFAULT, ip_addresses=None,
                  advertisement_interval=vrrp.VRRP_MAX_ADVER_INT_DEFAULT_IN_SEC,
                  preempt_mode=True, preempt_delay=0, accept_mode=False,
-                 statistics_interval=None, resource_id=None):
+                 statistics_interval=0, resource_id=None):
         # To allow version and priority default
         assert vrid is not None
         assert ip_addresses is not None
diff --git a/ryu/services/protocols/vrrp/rpc_manager.py 
b/ryu/services/protocols/vrrp/rpc_manager.py
new file mode 100644
index 0000000..3aa03b2
--- /dev/null
+++ b/ryu/services/protocols/vrrp/rpc_manager.py
@@ -0,0 +1,197 @@
+# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+#
+# 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.
+
+from oslo.config import cfg
+import socket
+import eventlet
+
+import netaddr
+from ryu.base import app_manager
+from ryu.controller import handler
+from ryu.services.protocols.vrrp import event as vrrp_event
+from ryu.services.protocols.vrrp import api as vrrp_api
+from ryu.lib import rpc
+from ryu.lib import hub
+from ryu.lib import mac
+
+VRRP_RPC_PORT = 50004  # random
+CONF = cfg.CONF
+
+CONF.register_opts([
+    cfg.IntOpt('vrrp-rpc-port', default=VRRP_RPC_PORT,
+               help='port for vrrp rpc interface')])
+
+
+class RPCError(Exception):
+    pass
+
+
+class Peer(object):
+    def __init__(self, queue):
+        super(Peer, self).__init__()
+        self.queue = queue
+
+    def _handle_vrrp_request(self, data):
+        self.queue.put((self, data))
+
+
+class RpcVRRPManager(app_manager.RyuApp):
+    def __init__(self, *args, **kwargs):
+        super(RpcVRRPManager, self).__init__(*args, **kwargs)
+        self._args = args
+        self._kwargs = kwargs
+        self._peers = []
+        self._rpc_events = hub.Queue(128)
+        self.serverThread = hub.spawn(self._peer_accept_thread)
+        self.event_thread = hub.spawn(self._rpc_request_loop_thread)
+
+    def _rpc_request_loop_thread(self):
+        while True:
+            (peer, data) = self._rpc_events.get()
+            msgid, target_method, params = data
+            error = None
+            result = None
+            try:
+                if target_method == "vrrp_config":
+                    result = self._config(msgid, params)
+                elif target_method == "vrrp_list":
+                    result = self._list(msgid, params)
+                elif target_method == "vrrp_config_change":
+                    result = self._config_change(msgid, params)
+                else:
+                    error = 'Unknown method %s' % (target_method)
+            except RPCError as e:
+                error = str(e)
+            peer._endpoint.send_response(msgid, error=error, result=result)
+
+    def _peer_loop_thread(self, peer):
+        peer._endpoint.serve()
+        # the peer connection is closed
+        self._peers.remove(peer)
+
+    def _peer_accept_thread(self):
+        server = eventlet.listen(('', CONF.vrrp_rpc_port))
+        while True:
+            new_sock, address = server.accept()
+            peer = Peer(self._rpc_events)
+            table = {
+                rpc.MessageType.REQUEST: peer._handle_vrrp_request,
+                }
+            peer._endpoint = rpc.EndPoint(new_sock, disp_table=table)
+            self._peers.append(peer)
+            hub.spawn(self._peer_loop_thread, peer)
+
+    def _params_to_dict(self, params, keys):
+        d = {}
+        for k, v in params.items():
+            if k in keys:
+                d[k] = v
+        return d
+
+    def _config(self, msgid, params):
+        self.logger.debug('handle vrrp_config request')
+        try:
+            param_dict = params[0]
+        except:
+            raise RPCError('parameters are missing')
+
+        if_params = self._params_to_dict(param_dict,
+                                         ('primary_ip_address',
+                                          'device_name'))
+        # drop vlan support later
+        if_params['vlan_id'] = None
+        if_params['mac_address'] = mac.DONTCARE_STR
+        try:
+            interface = vrrp_event.VRRPInterfaceNetworkDevice(**if_params)
+        except:
+            raise RPCError('parameters are invalid, %s' % (str(param_dict)))
+
+        config_params = self._params_to_dict(param_dict,
+                                             ('vrid',  # mandatory
+                                              'ip_addresses',  # mandatory
+                                              'version',
+                                              'admin_state',
+                                              'priority',
+                                              'advertisement_interval',
+                                              'preempt_mode',
+                                              'preempt_delay',
+                                              'statistics_interval'))
+        try:
+            config = vrrp_event.VRRPConfig(**config_params)
+        except:
+            raise RPCError('parameters are invalid, %s' % (str(param_dict)))
+
+        config_result = vrrp_api.vrrp_config(self, interface, config)
+
+        api_result = [
+            config_result.config.vrid,
+            config_result.config.priority,
+            str(netaddr.IPAddress(config_result.config.ip_addresses[0]))]
+        return api_result
+
+    def _lookup_instance(self, vrid):
+        for instance in vrrp_api.vrrp_list(self).instance_list:
+            if vrid == instance.config.vrid:
+                return instance.instance_name
+        return None
+
+    def _config_change(self, msgid, params):
+        self.logger.debug('handle vrrp_config_change request')
+        try:
+            config_values = params[0]
+        except:
+            raise RPCError('parameters are missing')
+
+        vrid = config_values.get('vrid')
+        instance_name = self._lookup_instance(vrid)
+        if not instance_name:
+            raise RPCError('vrid %d is not found' % (vrid))
+
+        priority = config_values.get('priority')
+        interval = config_values.get('advertisement_interval')
+        vrrp_api.vrrp_config_change(self, instance_name, priority=priority,
+                                    advertisement_interval=interval)
+        return {}
+
+    def _list(self, msgid, params):
+        self.logger.debug('handle vrrp_list request')
+        result = vrrp_api.vrrp_list(self)
+        instance_list = result.instance_list
+        ret_list = []
+        for instance in instance_list:
+            c = instance.config
+            info_dict = {
+                "instance_name": instance.instance_name,
+                "vrid": c.vrid,
+                "version": c.version,
+                "advertisement_interval": c.advertisement_interval,
+                "priority": c.priority,
+                "virtual_ip_address": str(netaddr.IPAddress(c.ip_addresses[0]))
+                }
+            ret_list.append(info_dict)
+        return ret_list
+
+    @handler.set_ev_cls(vrrp_event.EventVRRPStateChanged)
+    def vrrp_state_changed_handler(self, ev):
+        self.logger.info('handle EventVRRPStateChanged')
+        name = ev.instance_name
+        old_state = ev.old_state
+        new_state = ev.new_state
+        vrid = ev.config.vrid
+        self.logger.info('VRID:%s %s: %s -> %s', vrid, name, old_state,
+                         new_state)
+        params = {'vrid': vrid, 'old_state': old_state, 'new_state': new_state}
+        for peer in self._peers:
+            peer._endpoint.send_notification("notify_status", [params])
-- 
1.8.3.4 (Apple Git-47)


------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today.
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to