Merge "Improve ovs_lib bridge management"
This commit is contained in:
commit
89d58c5f27
@ -44,10 +44,52 @@ class VifPort:
|
|||||||
self.switch.br_name)
|
self.switch.br_name)
|
||||||
|
|
||||||
|
|
||||||
class OVSBridge:
|
class BaseOVS(object):
|
||||||
def __init__(self, br_name, root_helper):
|
|
||||||
self.br_name = br_name
|
def __init__(self, root_helper):
|
||||||
self.root_helper = root_helper
|
self.root_helper = root_helper
|
||||||
|
|
||||||
|
def run_vsctl(self, args, check_error=False):
|
||||||
|
full_args = ["ovs-vsctl", "--timeout=2"] + args
|
||||||
|
try:
|
||||||
|
return utils.execute(full_args, root_helper=self.root_helper)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error(_("Unable to execute %(cmd)s. Exception: %(exception)s"),
|
||||||
|
{'cmd': full_args, 'exception': e})
|
||||||
|
if check_error:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def add_bridge(self, bridge_name):
|
||||||
|
self.run_vsctl(["--", "--may-exist", "add-br", bridge_name])
|
||||||
|
return OVSBridge(bridge_name, self.root_helper)
|
||||||
|
|
||||||
|
def delete_bridge(self, bridge_name):
|
||||||
|
self.run_vsctl(["--", "--if-exists", "del-br", bridge_name])
|
||||||
|
|
||||||
|
def bridge_exists(self, bridge_name):
|
||||||
|
try:
|
||||||
|
self.run_vsctl(['br-exists', bridge_name], check_error=True)
|
||||||
|
except RuntimeError as e:
|
||||||
|
if 'Exit code: 2\n' in str(e):
|
||||||
|
return False
|
||||||
|
raise
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_bridge_name_for_port_name(self, port_name):
|
||||||
|
try:
|
||||||
|
return self.run_vsctl(['port-to-br', port_name], check_error=True)
|
||||||
|
except RuntimeError as e:
|
||||||
|
if 'Exit code: 1\n' not in str(e):
|
||||||
|
raise
|
||||||
|
|
||||||
|
def port_exists(self, port_name):
|
||||||
|
return bool(self.get_bridge_name_for_port_name(port_name))
|
||||||
|
|
||||||
|
|
||||||
|
class OVSBridge(BaseOVS):
|
||||||
|
def __init__(self, br_name, root_helper):
|
||||||
|
super(OVSBridge, self).__init__(root_helper)
|
||||||
|
self.br_name = br_name
|
||||||
self.re_id = self.re_compile_id()
|
self.re_id = self.re_compile_id()
|
||||||
self.defer_apply_flows = False
|
self.defer_apply_flows = False
|
||||||
self.deferred_flows = {'add': '', 'mod': '', 'del': ''}
|
self.deferred_flows = {'add': '', 'mod': '', 'del': ''}
|
||||||
@ -65,17 +107,15 @@ class OVSBridge:
|
|||||||
'port': port})
|
'port': port})
|
||||||
return re.compile(_re, re.M | re.X)
|
return re.compile(_re, re.M | re.X)
|
||||||
|
|
||||||
def run_vsctl(self, args):
|
def create(self):
|
||||||
full_args = ["ovs-vsctl", "--timeout=2"] + args
|
self.add_bridge(self.br_name)
|
||||||
try:
|
|
||||||
return utils.execute(full_args, root_helper=self.root_helper)
|
def destroy(self):
|
||||||
except Exception as e:
|
self.delete_bridge(self.br_name)
|
||||||
LOG.error(_("Unable to execute %(cmd)s. Exception: %(exception)s"),
|
|
||||||
{'cmd': full_args, 'exception': e})
|
|
||||||
|
|
||||||
def reset_bridge(self):
|
def reset_bridge(self):
|
||||||
self.run_vsctl(["--", "--if-exists", "del-br", self.br_name])
|
self.destroy()
|
||||||
self.run_vsctl(["add-br", self.br_name])
|
self.create()
|
||||||
|
|
||||||
def add_port(self, port_name):
|
def add_port(self, port_name):
|
||||||
self.run_vsctl(["--", "--may-exist", "add-port", self.br_name,
|
self.run_vsctl(["--", "--may-exist", "add-port", self.br_name,
|
||||||
|
@ -26,6 +26,79 @@ from neutron.openstack.common import uuidutils
|
|||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestBaseOVS(base.BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestBaseOVS, self).setUp()
|
||||||
|
self.root_helper = 'sudo'
|
||||||
|
self.ovs = ovs_lib.BaseOVS(self.root_helper)
|
||||||
|
self.br_name = 'bridge1'
|
||||||
|
|
||||||
|
def test_add_bridge(self):
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl') as mock_vsctl:
|
||||||
|
bridge = self.ovs.add_bridge(self.br_name)
|
||||||
|
|
||||||
|
mock_vsctl.assert_called_with(["--", "--may-exist",
|
||||||
|
"add-br", self.br_name])
|
||||||
|
self.assertEqual(bridge.br_name, self.br_name)
|
||||||
|
self.assertEqual(bridge.root_helper, self.ovs.root_helper)
|
||||||
|
|
||||||
|
def test_delete_bridge(self):
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl') as mock_vsctl:
|
||||||
|
self.ovs.delete_bridge(self.br_name)
|
||||||
|
mock_vsctl.assert_called_with(["--", "--if-exists", "del-br",
|
||||||
|
self.br_name])
|
||||||
|
|
||||||
|
def test_bridge_exists_returns_true(self):
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl') as mock_vsctl:
|
||||||
|
self.assertTrue(self.ovs.bridge_exists(self.br_name))
|
||||||
|
mock_vsctl.assert_called_with(['br-exists', self.br_name],
|
||||||
|
check_error=True)
|
||||||
|
|
||||||
|
def test_bridge_exists_returns_false_for_exit_code_2(self):
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl',
|
||||||
|
side_effect=RuntimeError('Exit code: 2\n')):
|
||||||
|
self.assertFalse(self.ovs.bridge_exists('bridge1'))
|
||||||
|
|
||||||
|
def test_bridge_exists_raises_unknown_exception(self):
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl',
|
||||||
|
side_effect=RuntimeError()):
|
||||||
|
with testtools.ExpectedException(RuntimeError):
|
||||||
|
self.ovs.bridge_exists('bridge1')
|
||||||
|
|
||||||
|
def test_get_bridge_name_for_port_name_returns_bridge_for_valid_port(self):
|
||||||
|
port_name = 'bar'
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl',
|
||||||
|
return_value=self.br_name) as mock_vsctl:
|
||||||
|
bridge = self.ovs.get_bridge_name_for_port_name(port_name)
|
||||||
|
self.assertEqual(bridge, self.br_name)
|
||||||
|
mock_vsctl.assert_called_with(['port-to-br', port_name],
|
||||||
|
check_error=True)
|
||||||
|
|
||||||
|
def test_get_bridge_name_for_port_name_returns_none_for_exit_code_1(self):
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl',
|
||||||
|
side_effect=RuntimeError('Exit code: 1\n')):
|
||||||
|
self.assertFalse(self.ovs.get_bridge_name_for_port_name('bridge1'))
|
||||||
|
|
||||||
|
def test_get_bridge_name_for_port_name_raises_unknown_exception(self):
|
||||||
|
with mock.patch.object(self.ovs, 'run_vsctl',
|
||||||
|
side_effect=RuntimeError()):
|
||||||
|
with testtools.ExpectedException(RuntimeError):
|
||||||
|
self.ovs.get_bridge_name_for_port_name('bridge1')
|
||||||
|
|
||||||
|
def _test_port_exists(self, br_name, result):
|
||||||
|
with mock.patch.object(self.ovs,
|
||||||
|
'get_bridge_name_for_port_name',
|
||||||
|
return_value=br_name):
|
||||||
|
self.assertEqual(self.ovs.port_exists('bar'), result)
|
||||||
|
|
||||||
|
def test_port_exists_returns_true_for_bridge_name(self):
|
||||||
|
self._test_port_exists(self.br_name, True)
|
||||||
|
|
||||||
|
def test_port_exists_returns_false_for_none(self):
|
||||||
|
self._test_port_exists(None, False)
|
||||||
|
|
||||||
|
|
||||||
class OVS_Lib_Test(base.BaseTestCase):
|
class OVS_Lib_Test(base.BaseTestCase):
|
||||||
"""A test suite to excercise the OVS libraries shared by Neutron agents.
|
"""A test suite to excercise the OVS libraries shared by Neutron agents.
|
||||||
|
|
||||||
@ -66,12 +139,23 @@ class OVS_Lib_Test(base.BaseTestCase):
|
|||||||
|
|
||||||
self.mox.VerifyAll()
|
self.mox.VerifyAll()
|
||||||
|
|
||||||
|
def test_create(self):
|
||||||
|
self.br.add_bridge(self.BR_NAME)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
self.br.create()
|
||||||
|
self.mox.VerifyAll()
|
||||||
|
|
||||||
|
def test_destroy(self):
|
||||||
|
self.br.delete_bridge(self.BR_NAME)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
self.br.destroy()
|
||||||
|
self.mox.VerifyAll()
|
||||||
|
|
||||||
def test_reset_bridge(self):
|
def test_reset_bridge(self):
|
||||||
utils.execute(["ovs-vsctl", self.TO, "--",
|
self.br.destroy()
|
||||||
"--if-exists", "del-br", self.BR_NAME],
|
self.br.create()
|
||||||
root_helper=self.root_helper)
|
|
||||||
utils.execute(["ovs-vsctl", self.TO, "add-br", self.BR_NAME],
|
|
||||||
root_helper=self.root_helper)
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
self.br.reset_bridge()
|
self.br.reset_bridge()
|
||||||
|
Loading…
Reference in New Issue
Block a user