Merge "Ensure the OVS bridge exists when plugging"
This commit is contained in:
commit
2025adb978
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- The ovs plugin has been modified to ensure that the
|
||||||
|
specified OVS bridge that the vif will be attached to
|
||||||
|
has been created. If the OVS bridge does not exist, it
|
||||||
|
will be created with the proper datapath_type.
|
||||||
|
|
|
@ -11,3 +11,6 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
OVS_VHOSTUSER_INTERFACE_TYPE = 'dpdkvhostuser'
|
OVS_VHOSTUSER_INTERFACE_TYPE = 'dpdkvhostuser'
|
||||||
|
|
||||||
|
OVS_DATAPATH_SYSTEM = 'system'
|
||||||
|
OVS_DATAPATH_NETDEV = 'netdev'
|
||||||
|
|
|
@ -60,6 +60,11 @@ def _create_ovs_vif_cmd(bridge, dev, iface_id, mac,
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
|
def _create_ovs_bridge_cmd(bridge, datapath_type):
|
||||||
|
return ['--', '--may-exist', 'add-br', bridge,
|
||||||
|
'--', 'set', 'Bridge', bridge, 'datapath_type=%s' % datapath_type]
|
||||||
|
|
||||||
|
|
||||||
@privsep.vif_plug.entrypoint
|
@privsep.vif_plug.entrypoint
|
||||||
def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id,
|
def create_ovs_vif_port(bridge, dev, iface_id, mac, instance_id,
|
||||||
mtu=None, interface_type=None, timeout=None):
|
mtu=None, interface_type=None, timeout=None):
|
||||||
|
@ -117,6 +122,11 @@ def create_veth_pair(dev1_name, dev2_name, mtu):
|
||||||
_set_device_mtu(dev, mtu)
|
_set_device_mtu(dev, mtu)
|
||||||
|
|
||||||
|
|
||||||
|
@privsep.vif_plug.entrypoint
|
||||||
|
def ensure_ovs_bridge(bridge, datapath_type):
|
||||||
|
_ovs_vsctl(_create_ovs_bridge_cmd(bridge, datapath_type))
|
||||||
|
|
||||||
|
|
||||||
@privsep.vif_plug.entrypoint
|
@privsep.vif_plug.entrypoint
|
||||||
def ensure_bridge(bridge):
|
def ensure_bridge(bridge):
|
||||||
if not device_exists(bridge):
|
if not device_exists(bridge):
|
||||||
|
|
|
@ -81,6 +81,8 @@ class OvsPlugin(plugin.PluginBase):
|
||||||
])
|
])
|
||||||
|
|
||||||
def _plug_vhostuser(self, vif, instance_info):
|
def _plug_vhostuser(self, vif, instance_info):
|
||||||
|
linux_net.ensure_ovs_bridge(vif.network.bridge,
|
||||||
|
constants.OVS_DATAPATH_NETDEV)
|
||||||
linux_net.create_ovs_vif_port(
|
linux_net.create_ovs_vif_port(
|
||||||
vif.network.bridge,
|
vif.network.bridge,
|
||||||
OvsPlugin.gen_port_name("vhu", vif.id),
|
OvsPlugin.gen_port_name("vhu", vif.id),
|
||||||
|
@ -107,6 +109,8 @@ class OvsPlugin(plugin.PluginBase):
|
||||||
linux_net.create_veth_pair(v1_name, v2_name,
|
linux_net.create_veth_pair(v1_name, v2_name,
|
||||||
self.config.network_device_mtu)
|
self.config.network_device_mtu)
|
||||||
linux_net.add_bridge_port(vif.bridge_name, v1_name)
|
linux_net.add_bridge_port(vif.bridge_name, v1_name)
|
||||||
|
linux_net.ensure_ovs_bridge(vif.network.bridge,
|
||||||
|
constants.OVS_DATAPATH_SYSTEM)
|
||||||
linux_net.create_ovs_vif_port(
|
linux_net.create_ovs_vif_port(
|
||||||
vif.network.bridge,
|
vif.network.bridge,
|
||||||
v2_name,
|
v2_name,
|
||||||
|
@ -124,7 +128,8 @@ class OvsPlugin(plugin.PluginBase):
|
||||||
profile=vif.port_profile.__class__.__name__)
|
profile=vif.port_profile.__class__.__name__)
|
||||||
|
|
||||||
if isinstance(vif, objects.vif.VIFOpenVSwitch):
|
if isinstance(vif, objects.vif.VIFOpenVSwitch):
|
||||||
pass # no special plugging required
|
linux_net.ensure_ovs_bridge(vif.network.bridge,
|
||||||
|
constants.OVS_DATAPATH_SYSTEM)
|
||||||
elif isinstance(vif, objects.vif.VIFBridge):
|
elif isinstance(vif, objects.vif.VIFBridge):
|
||||||
self._plug_bridge(vif, instance_info)
|
self._plug_bridge(vif, instance_info)
|
||||||
elif isinstance(vif, objects.vif.VIFVHostUser):
|
elif isinstance(vif, objects.vif.VIFVHostUser):
|
||||||
|
|
|
@ -141,6 +141,24 @@ class LinuxNetTest(testtools.TestCase):
|
||||||
'fake-type')
|
'fake-type')
|
||||||
self.assertEqual(expected, cmd)
|
self.assertEqual(expected, cmd)
|
||||||
|
|
||||||
|
@mock.patch.object(linux_net, '_create_ovs_bridge_cmd')
|
||||||
|
@mock.patch.object(linux_net, '_ovs_vsctl')
|
||||||
|
def test_ensure_ovs_bridge(self, mock_vsctl, mock_create_ovs_bridge):
|
||||||
|
bridge = 'fake-bridge'
|
||||||
|
dp_type = 'fake-type'
|
||||||
|
linux_net.ensure_ovs_bridge(bridge, dp_type)
|
||||||
|
mock_create_ovs_bridge.assert_called_once_with(bridge, dp_type)
|
||||||
|
self.assertTrue(mock_vsctl.called)
|
||||||
|
|
||||||
|
def test_create_ovs_bridge_cmd(self):
|
||||||
|
bridge = 'fake-bridge'
|
||||||
|
dp_type = 'fake-type'
|
||||||
|
expected = ['--', '--may-exist', 'add-br', bridge,
|
||||||
|
'--', 'set', 'Bridge', bridge,
|
||||||
|
'datapath_type=%s' % dp_type]
|
||||||
|
actual = linux_net._create_ovs_bridge_cmd(bridge, dp_type)
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
@mock.patch.object(linux_net, '_ovs_vsctl')
|
@mock.patch.object(linux_net, '_ovs_vsctl')
|
||||||
@mock.patch.object(linux_net, '_create_ovs_vif_cmd')
|
@mock.patch.object(linux_net, '_create_ovs_vif_cmd')
|
||||||
@mock.patch.object(linux_net, '_set_device_mtu')
|
@mock.patch.object(linux_net, '_set_device_mtu')
|
||||||
|
|
|
@ -17,6 +17,7 @@ import testtools
|
||||||
|
|
||||||
from os_vif import objects
|
from os_vif import objects
|
||||||
|
|
||||||
|
from vif_plug_ovs import constants
|
||||||
from vif_plug_ovs import linux_net
|
from vif_plug_ovs import linux_net
|
||||||
from vif_plug_ovs import ovs
|
from vif_plug_ovs import ovs
|
||||||
|
|
||||||
|
@ -88,11 +89,15 @@ class PluginTest(testtools.TestCase):
|
||||||
uuid='f0000000-0000-0000-0000-000000000001')
|
uuid='f0000000-0000-0000-0000-000000000001')
|
||||||
|
|
||||||
def test_plug_ovs(self):
|
def test_plug_ovs(self):
|
||||||
|
with mock.patch.object(linux_net, 'ensure_ovs_bridge') as (
|
||||||
|
ensure_ovs_bridge):
|
||||||
plug_bridge_mock = mock.Mock()
|
plug_bridge_mock = mock.Mock()
|
||||||
plugin = ovs.OvsPlugin.load("ovs")
|
plugin = ovs.OvsPlugin.load("ovs")
|
||||||
plugin._plug_bridge = plug_bridge_mock
|
plugin._plug_bridge = plug_bridge_mock
|
||||||
plugin.plug(self.vif_ovs, self.instance)
|
plugin.plug(self.vif_ovs, self.instance)
|
||||||
self.assertFalse(plug_bridge_mock.called)
|
self.assertFalse(plug_bridge_mock.called)
|
||||||
|
ensure_ovs_bridge.assert_called_once_with(
|
||||||
|
self.vif_ovs.network.bridge, constants.OVS_DATAPATH_SYSTEM)
|
||||||
|
|
||||||
def test_plug_ovs_bridge(self):
|
def test_plug_ovs_bridge(self):
|
||||||
calls = {
|
calls = {
|
||||||
|
@ -109,7 +114,9 @@ class PluginTest(testtools.TestCase):
|
||||||
'ca:fe:de:ad:be:ef',
|
'ca:fe:de:ad:be:ef',
|
||||||
'f0000000-0000-0000-0000-000000000001',
|
'f0000000-0000-0000-0000-000000000001',
|
||||||
1500,
|
1500,
|
||||||
timeout=120)]
|
timeout=120)],
|
||||||
|
'ensure_ovs_bridge': [mock.call('br0',
|
||||||
|
constants.OVS_DATAPATH_SYSTEM)]
|
||||||
}
|
}
|
||||||
|
|
||||||
with nested(
|
with nested(
|
||||||
|
@ -118,9 +125,10 @@ class PluginTest(testtools.TestCase):
|
||||||
return_value=False),
|
return_value=False),
|
||||||
mock.patch.object(linux_net, 'create_veth_pair'),
|
mock.patch.object(linux_net, 'create_veth_pair'),
|
||||||
mock.patch.object(linux_net, 'add_bridge_port'),
|
mock.patch.object(linux_net, 'add_bridge_port'),
|
||||||
mock.patch.object(linux_net, 'create_ovs_vif_port')
|
mock.patch.object(linux_net, 'create_ovs_vif_port'),
|
||||||
|
mock.patch.object(linux_net, 'ensure_ovs_bridge')
|
||||||
) as (ensure_bridge, device_exists, create_veth_pair,
|
) as (ensure_bridge, device_exists, create_veth_pair,
|
||||||
add_bridge_port, create_ovs_vif_port):
|
add_bridge_port, create_ovs_vif_port, ensure_ovs_bridge):
|
||||||
plugin = ovs.OvsPlugin.load("ovs")
|
plugin = ovs.OvsPlugin.load("ovs")
|
||||||
plugin.plug(self.vif_ovs_hybrid, self.instance)
|
plugin.plug(self.vif_ovs_hybrid, self.instance)
|
||||||
ensure_bridge.assert_has_calls(calls['ensure_bridge'])
|
ensure_bridge.assert_has_calls(calls['ensure_bridge'])
|
||||||
|
@ -128,6 +136,7 @@ class PluginTest(testtools.TestCase):
|
||||||
create_veth_pair.assert_has_calls(calls['create_veth_pair'])
|
create_veth_pair.assert_has_calls(calls['create_veth_pair'])
|
||||||
add_bridge_port.assert_has_calls(calls['add_bridge_port'])
|
add_bridge_port.assert_has_calls(calls['add_bridge_port'])
|
||||||
create_ovs_vif_port.assert_has_calls(calls['create_ovs_vif_port'])
|
create_ovs_vif_port.assert_has_calls(calls['create_ovs_vif_port'])
|
||||||
|
ensure_ovs_bridge.assert_has_calls(calls['ensure_ovs_bridge'])
|
||||||
|
|
||||||
def test_unplug_ovs(self):
|
def test_unplug_ovs(self):
|
||||||
unplug_bridge_mock = mock.Mock()
|
unplug_bridge_mock = mock.Mock()
|
||||||
|
@ -160,14 +169,19 @@ class PluginTest(testtools.TestCase):
|
||||||
'f0000000-0000-0000-0000-000000000001',
|
'f0000000-0000-0000-0000-000000000001',
|
||||||
1500,
|
1500,
|
||||||
interface_type='dpdkvhostuser',
|
interface_type='dpdkvhostuser',
|
||||||
timeout=120)]
|
timeout=120)],
|
||||||
|
'ensure_ovs_bridge': [mock.call('br0',
|
||||||
|
constants.OVS_DATAPATH_NETDEV)]
|
||||||
}
|
}
|
||||||
|
|
||||||
with mock.patch.object(linux_net, 'create_ovs_vif_port') \
|
with nested(
|
||||||
as (create_ovs_vif_port):
|
mock.patch.object(linux_net, 'create_ovs_vif_port'),
|
||||||
|
mock.patch.object(linux_net, 'ensure_ovs_bridge')
|
||||||
|
) as (create_ovs_vif_port, ensure_ovs_bridge):
|
||||||
plugin = ovs.OvsPlugin.load("ovs")
|
plugin = ovs.OvsPlugin.load("ovs")
|
||||||
plugin.plug(self.vif_vhostuser, self.instance)
|
plugin.plug(self.vif_vhostuser, self.instance)
|
||||||
create_ovs_vif_port.assert_has_calls(calls['create_ovs_vif_port'])
|
create_ovs_vif_port.assert_has_calls(calls['create_ovs_vif_port'])
|
||||||
|
ensure_ovs_bridge.assert_has_calls(calls['ensure_ovs_bridge'])
|
||||||
|
|
||||||
def test_unplug_ovs_vhostuser(self):
|
def test_unplug_ovs_vhostuser(self):
|
||||||
calls = {
|
calls = {
|
||||||
|
|
Loading…
Reference in New Issue