Merge "Repeat few times put new interface in the namespace" into stable/ussuri
This commit is contained in:
commit
ee1b021464
|
@ -371,6 +371,48 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
|
||||||
ovs = ovs_lib.OVSBridge(bridge)
|
ovs = ovs_lib.OVSBridge(bridge)
|
||||||
ovs.replace_port(device_name, *attrs)
|
ovs.replace_port(device_name, *attrs)
|
||||||
|
|
||||||
|
def _set_device_address(self, device, mac_address):
|
||||||
|
for i in range(9):
|
||||||
|
# workaround for the OVS shy port syndrome. ports sometimes
|
||||||
|
# hide for a bit right after they are first created.
|
||||||
|
# see bug/1618987
|
||||||
|
try:
|
||||||
|
device.link.set_address(mac_address)
|
||||||
|
break
|
||||||
|
except RuntimeError as e:
|
||||||
|
LOG.warning("Got error trying to set mac, retrying: %s",
|
||||||
|
str(e))
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
# didn't break, we give it one last shot without catching
|
||||||
|
device.link.set_address(mac_address)
|
||||||
|
|
||||||
|
def _add_device_to_namespace(self, ip_wrapper, device, namespace):
|
||||||
|
namespace_obj = ip_wrapper.ensure_namespace(namespace)
|
||||||
|
for i in range(9):
|
||||||
|
try:
|
||||||
|
namespace_obj.add_device_to_namespace(device)
|
||||||
|
break
|
||||||
|
except ip_lib.NetworkInterfaceNotFound:
|
||||||
|
# NOTE(slaweq): if the exception was NetworkInterfaceNotFound
|
||||||
|
# then lets try again, otherwise lets simply raise it as this
|
||||||
|
# is some different issue than retry tries to workaround
|
||||||
|
LOG.warning("Failed to set interface %s into namespace %s. "
|
||||||
|
"Interface not found, attempt: %s, retrying.",
|
||||||
|
device, namespace, i + 1)
|
||||||
|
time.sleep(1)
|
||||||
|
except utils.WaitTimeout:
|
||||||
|
# NOTE(slaweq): if the exception was WaitTimeout then it means
|
||||||
|
# that probably device wasn't found in the desired namespace
|
||||||
|
# for 5 seconds, so lets try again too
|
||||||
|
LOG.warning("Failed to set interface %s into namespace %s. "
|
||||||
|
"Interface not found in namespace, attempt: %s, "
|
||||||
|
"retrying.", device, namespace, i + 1)
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
# didn't break, we give it one last shot without catching
|
||||||
|
namespace_obj.add_device_to_namespace(device)
|
||||||
|
|
||||||
def plug_new(self, network_id, port_id, device_name, mac_address,
|
def plug_new(self, network_id, port_id, device_name, mac_address,
|
||||||
bridge=None, namespace=None, prefix=None, mtu=None,
|
bridge=None, namespace=None, prefix=None, mtu=None,
|
||||||
link_up=True):
|
link_up=True):
|
||||||
|
@ -395,31 +437,25 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
|
||||||
internal = not self.conf.ovs_use_veth
|
internal = not self.conf.ovs_use_veth
|
||||||
self._ovs_add_port(bridge, tap_name, port_id, mac_address,
|
self._ovs_add_port(bridge, tap_name, port_id, mac_address,
|
||||||
internal=internal)
|
internal=internal)
|
||||||
for i in range(9):
|
|
||||||
# workaround for the OVS shy port syndrome. ports sometimes
|
|
||||||
# hide for a bit right after they are first created.
|
|
||||||
# see bug/1618987
|
|
||||||
try:
|
try:
|
||||||
ns_dev.link.set_address(mac_address)
|
self._set_device_address(ns_dev, mac_address)
|
||||||
break
|
except Exception:
|
||||||
except RuntimeError as e:
|
LOG.warning("Failed to set mac for interface %s", ns_dev)
|
||||||
LOG.warning("Got error trying to set mac, retrying: %s",
|
with excutils.save_and_reraise_exception():
|
||||||
str(e))
|
ovs = ovs_lib.OVSBridge(bridge)
|
||||||
time.sleep(1)
|
ovs.delete_port(tap_name)
|
||||||
else:
|
|
||||||
# didn't break, we give it one last shot without catching
|
|
||||||
ns_dev.link.set_address(mac_address)
|
|
||||||
|
|
||||||
# Add an interface created by ovs to the namespace.
|
# Add an interface created by ovs to the namespace.
|
||||||
if not self.conf.ovs_use_veth and namespace:
|
if not self.conf.ovs_use_veth and namespace:
|
||||||
try:
|
try:
|
||||||
namespace_obj = ip.ensure_namespace(namespace)
|
self._add_device_to_namespace(ip, ns_dev, namespace)
|
||||||
namespace_obj.add_device_to_namespace(ns_dev)
|
except (pyroute2_exc.NetlinkError, OSError, RuntimeError):
|
||||||
except (pyroute2_exc.NetlinkError, OSError):
|
|
||||||
# To prevent the namespace failure from blasting OVS, the OVS
|
# To prevent the namespace failure from blasting OVS, the OVS
|
||||||
# port creation should be reverted. Possible exceptions:
|
# port creation should be reverted. Possible exceptions:
|
||||||
# - NetlinkError in case of duplicated interface
|
# - NetlinkError in case of duplicated interface
|
||||||
# - OSError in case of corrupted namespace
|
# - OSError in case of corrupted namespace
|
||||||
|
# - RuntimeError in case of any issue with interface, like e.g.
|
||||||
|
# Interface not found
|
||||||
LOG.warning("Failed to plug interface %s into bridge %s, "
|
LOG.warning("Failed to plug interface %s into bridge %s, "
|
||||||
"cleaning up", device_name, bridge)
|
"cleaning up", device_name, bridge)
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
|
|
|
@ -449,6 +449,11 @@ class TestOVSInterfaceDriver(TestBase):
|
||||||
self.device_exists.side_effect = device_exists
|
self.device_exists.side_effect = device_exists
|
||||||
link = self.ip.return_value.device.return_value.link
|
link = self.ip.return_value.device.return_value.link
|
||||||
link.set_address.side_effect = (RuntimeError, None)
|
link.set_address.side_effect = (RuntimeError, None)
|
||||||
|
namespace_obj = (
|
||||||
|
self.ip.return_value.ensure_namespace.return_value)
|
||||||
|
self.ip.ensure_namespace.return_value = namespace_obj
|
||||||
|
namespace_obj.add_device_to_namespace.side_effect = (
|
||||||
|
ip_lib.NetworkInterfaceNotFound, utils.WaitTimeout, None)
|
||||||
ovs.plug('01234567-1234-1234-99',
|
ovs.plug('01234567-1234-1234-99',
|
||||||
'port-1234',
|
'port-1234',
|
||||||
'tap0',
|
'tap0',
|
||||||
|
@ -472,6 +477,10 @@ class TestOVSInterfaceDriver(TestBase):
|
||||||
if namespace:
|
if namespace:
|
||||||
expected.extend(
|
expected.extend(
|
||||||
[mock.call().ensure_namespace(namespace),
|
[mock.call().ensure_namespace(namespace),
|
||||||
|
mock.call().ensure_namespace().add_device_to_namespace(
|
||||||
|
mock.ANY),
|
||||||
|
mock.call().ensure_namespace().add_device_to_namespace(
|
||||||
|
mock.ANY),
|
||||||
mock.call().ensure_namespace().add_device_to_namespace(
|
mock.call().ensure_namespace().add_device_to_namespace(
|
||||||
mock.ANY)])
|
mock.ANY)])
|
||||||
expected.extend([
|
expected.extend([
|
||||||
|
@ -496,7 +505,8 @@ class TestOVSInterfaceDriver(TestBase):
|
||||||
reraise.start()
|
reraise.start()
|
||||||
ip_wrapper = mock.Mock()
|
ip_wrapper = mock.Mock()
|
||||||
for exception in (OSError(),
|
for exception in (OSError(),
|
||||||
pyroute2_exc.NetlinkError(22)):
|
pyroute2_exc.NetlinkError(22),
|
||||||
|
RuntimeError()):
|
||||||
ip_wrapper.ensure_namespace.side_effect = exception
|
ip_wrapper.ensure_namespace.side_effect = exception
|
||||||
self.ip.return_value = ip_wrapper
|
self.ip.return_value = ip_wrapper
|
||||||
delete_port.reset_mock()
|
delete_port.reset_mock()
|
||||||
|
|
Loading…
Reference in New Issue