From 253ce73b7f934f3a7e07f539d91e2201e2994d41 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 31 Oct 2017 14:28:38 +0900 Subject: lib/ovs/vsctl: Function for validate OVSDB address Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/ovs/bridge.py | 5 +++++ ryu/lib/ovs/vsctl.py | 37 ++++++++++++++++++++++++++++++++++++ ryu/tests/unit/lib/ovs/test_vsctl.py | 24 +++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/ryu/lib/ovs/bridge.py b/ryu/lib/ovs/bridge.py index 337867e2..e48052fb 100644 --- a/ryu/lib/ovs/bridge.py +++ b/ryu/lib/ovs/bridge.py @@ -25,6 +25,8 @@ from ryu import cfg import ryu.exception as ryu_exc import ryu.lib.dpid as dpid_lib import ryu.lib.ovs.vsctl as ovs_vsctl +from ryu.lib.ovs.vsctl import valid_ovsdb_addr + LOG = logging.getLogger(__name__) @@ -95,6 +97,7 @@ class OVSBridge(object): exception=None): super(OVSBridge, self).__init__() self.datapath_id = datapath_id + self.ovsdb_addr = ovsdb_addr self.vsctl = ovs_vsctl.VSCtl(ovsdb_addr) self.timeout = timeout or CONF.ovsdb_timeout self.exception = exception @@ -105,6 +108,8 @@ class OVSBridge(object): self.vsctl.run_command(commands, self.timeout, self.exception) def init(self): + if not valid_ovsdb_addr(self.ovsdb_addr): + raise ValueError('Invalid OVSDB address: %s' % self.ovsdb_addr) if self.br_name is None: self.br_name = self._get_bridge_name() diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py index 82ff52bd..2391c903 100644 --- a/ryu/lib/ovs/vsctl.py +++ b/ryu/lib/ovs/vsctl.py @@ -20,6 +20,7 @@ from __future__ import print_function import logging import operator import os +import re import sys import weakref @@ -37,6 +38,7 @@ from ovs import stream from ovs.db import idl from ryu.lib import hub +from ryu.lib import ip from ryu.lib.ovs import vswitch_idl from ryu.lib.stringify import StringifyMixin @@ -44,6 +46,41 @@ from ryu.lib.stringify import StringifyMixin LOG = logging.getLogger(__name__) # use ovs.vlog? +def valid_ovsdb_addr(addr): + """ + Returns True if the given addr is valid OVSDB server address, otherwise + False. + + The valid formats are: + + - unix:file + - tcp:ip:port + - ssl:ip:port + + If ip is IPv6 address, wrap ip with brackets (e.g., ssl:[::1]:6640). + + :param addr: str value of OVSDB server address. + :return: True if valid, otherwise False. + """ + # Assumes Unix socket format: "unix:file" + m = re.match('unix:(\S+)', addr) + if m: + file = m.group(1) + return os.path.isfile(file) + # Assumes TCP/SSL socket format: "tcp:ip:port" or "ssl:ip:port" + m = re.match('(tcp|ssl):(\S+):(\d+)', addr) + if m: + address = m.group(2) + port = m.group(3) + if '[' in address: + address = address.strip('[').strip(']') + return ip.valid_ipv6(address) and port.isdigit() + else: + return ip.valid_ipv4(address) and port.isdigit() + # Assumes invalid format or unsupported type + return False + + # for debug def ovsrec_row_changes_to_string(ovsrec_row): if not ovsrec_row._changes: diff --git a/ryu/tests/unit/lib/ovs/test_vsctl.py b/ryu/tests/unit/lib/ovs/test_vsctl.py index 28edf6e9..84698eec 100644 --- a/ryu/tests/unit/lib/ovs/test_vsctl.py +++ b/ryu/tests/unit/lib/ovs/test_vsctl.py @@ -24,6 +24,11 @@ from nose.tools import ok_ from ryu.lib.hub import sleep from ryu.lib.ovs import vsctl +try: + import mock # Python 2 +except ImportError: + from unittest import mock # Python 3 + LOG = logging.getLogger(__name__) @@ -39,6 +44,25 @@ def setUpModule(): 'Docker is not available. Test in %s will be skipped.' % __name__) +class TestUtils(unittest.TestCase): + """ + Test cases for utilities defined in module. + """ + + @mock.patch('os.path.isfile', mock.MagicMock(return_value=True)) + def test_valid_ovsdb_addr_with_unix(self): + ok_(vsctl.valid_ovsdb_addr('unix:/var/run/openvswitch/db.sock')) + + def test_valid_ovsdb_addr_with_ipv4(self): + ok_(vsctl.valid_ovsdb_addr('tcp:127.0.0.1:6640')) + + def test_valid_ovsdb_addr_with_ipv6(self): + ok_(vsctl.valid_ovsdb_addr('ssl:[::1]:6640')) + + def test_valid_ovsdb_addr_with_invalid_type(self): + eq_(vsctl.valid_ovsdb_addr('invalid:127.0.0.1:6640'), False) + + def _run(command): popen = subprocess.Popen(command.split(), stdout=subprocess.PIPE) popen.wait() -- cgit v1.2.3