Don't break traffic if port already exists
Nova compute service plugs VIF on service init, it triggers rules reinitialization for iptables filter. But it breaks traffic in case isolate_vif is used by assigning dead VLAN to the port. This patch prevents dead VLAN assingment for ports that exists. Co-Authored-By: aarefiev@mirantis.com Closes-Bug: #2023300 Change-Id: Ib1b7467fce9facfbfcd698bf6e9f950c0cead650
This commit is contained in:
parent
da742a849a
commit
0a0dec37e4
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
An issue when after nova-compute service restart configured with
|
||||||
|
`isolate_vif=True` instances lost connectivity unless neutron
|
||||||
|
rebinds ports. Which is normally happening by agent restart or port
|
||||||
|
update.
|
@ -186,6 +186,13 @@ class OvsPlugin(plugin.PluginBase):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _isolate_vif(self, vif_name, bridge):
|
||||||
|
# NOTE(vsaienko): don't break traffic if port already exists,
|
||||||
|
# we assume it is called when nova-compute is initialized and
|
||||||
|
# since port is present it should be bound already.
|
||||||
|
return (self.config.isolate_vif and
|
||||||
|
not self.ovsdb.port_exists(vif_name, bridge))
|
||||||
|
|
||||||
def _create_vif_port(self, vif, vif_name, instance_info, **kwargs):
|
def _create_vif_port(self, vif, vif_name, instance_info, **kwargs):
|
||||||
mtu = self._get_mtu(vif)
|
mtu = self._get_mtu(vif)
|
||||||
# NOTE(sean-k-mooney): As part of a partial fix to bug #1734320
|
# NOTE(sean-k-mooney): As part of a partial fix to bug #1734320
|
||||||
@ -200,7 +207,8 @@ class OvsPlugin(plugin.PluginBase):
|
|||||||
# TODO(sean-k-mooney): Extend neutron to record what ml2 driver
|
# TODO(sean-k-mooney): Extend neutron to record what ml2 driver
|
||||||
# bound the interface in the vif binding details so isolation
|
# bound the interface in the vif binding details so isolation
|
||||||
# can be enabled automatically in the future.
|
# can be enabled automatically in the future.
|
||||||
if self.config.isolate_vif:
|
bridge = kwargs.pop('bridge', vif.network.bridge)
|
||||||
|
if self._isolate_vif(vif_name, bridge):
|
||||||
kwargs['tag'] = constants.DEAD_VLAN
|
kwargs['tag'] = constants.DEAD_VLAN
|
||||||
qos_type = self._get_qos_type(vif)
|
qos_type = self._get_qos_type(vif)
|
||||||
if qos_type is not None:
|
if qos_type is not None:
|
||||||
@ -215,7 +223,6 @@ class OvsPlugin(plugin.PluginBase):
|
|||||||
# for more details.
|
# for more details.
|
||||||
if not self.ovsdb.port_exists(vif_name, vif.network.bridge):
|
if not self.ovsdb.port_exists(vif_name, vif.network.bridge):
|
||||||
kwargs['qos_type'] = qos_type
|
kwargs['qos_type'] = qos_type
|
||||||
bridge = kwargs.pop('bridge', vif.network.bridge)
|
|
||||||
self.ovsdb.create_ovs_vif_port(
|
self.ovsdb.create_ovs_vif_port(
|
||||||
bridge,
|
bridge,
|
||||||
vif_name,
|
vif_name,
|
||||||
@ -302,7 +309,9 @@ class OvsPlugin(plugin.PluginBase):
|
|||||||
vif, vif.vif_name, instance_info, bridge=port_bridge_name,
|
vif, vif.vif_name, instance_info, bridge=port_bridge_name,
|
||||||
set_ids=False
|
set_ids=False
|
||||||
)
|
)
|
||||||
tag = constants.DEAD_VLAN if self.config.isolate_vif else None
|
tag = (constants.DEAD_VLAN
|
||||||
|
if self._isolate_vif(int_bridge_patch, int_bridge_name)
|
||||||
|
else None)
|
||||||
iface_id = vif.id
|
iface_id = vif.id
|
||||||
mac = vif.address
|
mac = vif.address
|
||||||
instance_id = instance_info.uuid
|
instance_id = instance_info.uuid
|
||||||
|
@ -187,8 +187,28 @@ class PluginTest(testtools.TestCase):
|
|||||||
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE)
|
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE)
|
||||||
|
|
||||||
@mock.patch.object(ovsdb_lib.BaseOVS, 'create_ovs_vif_port')
|
@mock.patch.object(ovsdb_lib.BaseOVS, 'create_ovs_vif_port')
|
||||||
def test_create_vif_port_isolate(self, mock_create_ovs_vif_port):
|
@mock.patch.object(ovsdb_lib.BaseOVS, 'port_exists')
|
||||||
|
def test_create_vif_port_isolate_port_no_isolate_vif_no_port(
|
||||||
|
self, mock_port_exists, mock_create_ovs_vif_port):
|
||||||
plugin = ovs.OvsPlugin.load(constants.PLUGIN_NAME)
|
plugin = ovs.OvsPlugin.load(constants.PLUGIN_NAME)
|
||||||
|
mock_port_exists.return_value = False
|
||||||
|
with mock.patch.object(plugin.config, 'isolate_vif', False):
|
||||||
|
plugin._create_vif_port(
|
||||||
|
self.vif_ovs, mock.sentinel.vif_name, self.instance,
|
||||||
|
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE)
|
||||||
|
mock_create_ovs_vif_port.assert_called_once_with(
|
||||||
|
self.vif_ovs.network.bridge, mock.sentinel.vif_name,
|
||||||
|
self.vif_ovs.port_profile.interface_id,
|
||||||
|
self.vif_ovs.address, self.instance.uuid,
|
||||||
|
mtu=plugin.config.network_device_mtu,
|
||||||
|
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE)
|
||||||
|
|
||||||
|
@mock.patch.object(ovsdb_lib.BaseOVS, 'create_ovs_vif_port')
|
||||||
|
@mock.patch.object(ovsdb_lib.BaseOVS, 'port_exists')
|
||||||
|
def test_create_vif_port_isolate_port_isolate_vif_no_port(
|
||||||
|
self, mock_port_exists, mock_create_ovs_vif_port):
|
||||||
|
plugin = ovs.OvsPlugin.load(constants.PLUGIN_NAME)
|
||||||
|
mock_port_exists.return_value = False
|
||||||
with mock.patch.object(plugin.config, 'isolate_vif', True):
|
with mock.patch.object(plugin.config, 'isolate_vif', True):
|
||||||
plugin._create_vif_port(
|
plugin._create_vif_port(
|
||||||
self.vif_ovs, mock.sentinel.vif_name, self.instance,
|
self.vif_ovs, mock.sentinel.vif_name, self.instance,
|
||||||
@ -201,6 +221,23 @@ class PluginTest(testtools.TestCase):
|
|||||||
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE,
|
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE,
|
||||||
tag=constants.DEAD_VLAN)
|
tag=constants.DEAD_VLAN)
|
||||||
|
|
||||||
|
@mock.patch.object(ovsdb_lib.BaseOVS, 'create_ovs_vif_port')
|
||||||
|
@mock.patch.object(ovsdb_lib.BaseOVS, 'port_exists')
|
||||||
|
def test_create_vif_port_isolate_port_isolate_vif_port_exists(
|
||||||
|
self, mock_port_exists, mock_create_ovs_vif_port):
|
||||||
|
plugin = ovs.OvsPlugin.load(constants.PLUGIN_NAME)
|
||||||
|
mock_port_exists.return_value = True
|
||||||
|
with mock.patch.object(plugin.config, 'isolate_vif', True):
|
||||||
|
plugin._create_vif_port(
|
||||||
|
self.vif_ovs, mock.sentinel.vif_name, self.instance,
|
||||||
|
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE)
|
||||||
|
mock_create_ovs_vif_port.assert_called_once_with(
|
||||||
|
self.vif_ovs.network.bridge, mock.sentinel.vif_name,
|
||||||
|
self.vif_ovs.port_profile.interface_id,
|
||||||
|
self.vif_ovs.address, self.instance.uuid,
|
||||||
|
mtu=plugin.config.network_device_mtu,
|
||||||
|
interface_type=constants.OVS_VHOSTUSER_INTERFACE_TYPE)
|
||||||
|
|
||||||
@mock.patch.object(ovs, 'sys')
|
@mock.patch.object(ovs, 'sys')
|
||||||
@mock.patch.object(ovs.OvsPlugin, '_plug_vif_generic')
|
@mock.patch.object(ovs.OvsPlugin, '_plug_vif_generic')
|
||||||
def test_plug_ovs_port_bridge_false(self, plug_vif_generic, mock_sys):
|
def test_plug_ovs_port_bridge_false(self, plug_vif_generic, mock_sys):
|
||||||
|
Loading…
Reference in New Issue
Block a user