Convert missing exception on device.link.delete()

Once we started using oslo.privsep the call to device.link.delete()
should return RuntimeError when the device can't be handled by ip link
for example, when it's an ovs internal device.

Closes-Bug: #1776469

Change-Id: Ibf4b0bbb54aef38fc569036880668c745cb5c096
This commit is contained in:
Miguel Angel Ajo 2018-06-12 14:35:39 +02:00
parent 5106dfe521
commit 7458575cfb
2 changed files with 38 additions and 9 deletions

View File

@ -62,6 +62,21 @@ class NetworkInterfaceNotFound(RuntimeError):
super(NetworkInterfaceNotFound, self).__init__(message)
class InterfaceOperationNotSupported(RuntimeError):
message = _("Operation not supported on interface %(device)s, namespace "
"%(namespace)s.")
def __init__(self, message=None, device=None, namespace=None):
# NOTE(slaweq): 'message' can be passed as an optional argument
# because of how privsep daemon works. If exception is raised in
# function called by privsep daemon, it will then try to reraise it
# and will call it always with passing only message from originally
# raised exception.
message = message or self.message % {
'device': device, 'namespace': namespace}
super(InterfaceOperationNotSupported, self).__init__(message)
class IpAddressAlreadyExists(RuntimeError):
message = _("IP address %(ip)s already configured on %(device)s.")
@ -116,6 +131,15 @@ def _get_iproute(namespace):
return pyroute2.IPRoute()
def _translate_ip_device_exception(e, device=None, namespace=None):
if e.code == errno.ENODEV:
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
if e.code == errno.EOPNOTSUPP:
raise InterfaceOperationNotSupported(device=device,
namespace=namespace)
raise
def _get_link_id(device, namespace):
try:
with _get_iproute(namespace) as ip:
@ -130,9 +154,7 @@ def _run_iproute_link(command, device, namespace=None, **kwargs):
idx = _get_link_id(device, namespace)
return ip.link(command, index=idx, **kwargs)
except NetlinkError as e:
if e.code == errno.ENODEV:
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
raise
_translate_ip_device_exception(e, device, namespace)
except OSError as e:
if e.errno == errno.ENOENT:
raise NetworkNamespaceNotFound(netns_name=namespace)
@ -145,9 +167,7 @@ def _run_iproute_neigh(command, device, namespace, **kwargs):
idx = _get_link_id(device, namespace)
return ip.neigh(command, ifindex=idx, **kwargs)
except NetlinkError as e:
if e.code == errno.ENODEV:
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
raise
_translate_ip_device_exception(e, device, namespace)
except OSError as e:
if e.errno == errno.ENOENT:
raise NetworkNamespaceNotFound(netns_name=namespace)
@ -160,9 +180,7 @@ def _run_iproute_addr(command, device, namespace, **kwargs):
idx = _get_link_id(device, namespace)
return ip.addr(command, index=idx, **kwargs)
except NetlinkError as e:
if e.code == errno.ENODEV:
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
raise
_translate_ip_device_exception(e, device, namespace)
except OSError as e:
if e.errno == errno.ENOENT:
raise NetworkNamespaceNotFound(netns_name=namespace)

View File

@ -62,6 +62,17 @@ class IpLibTestCase(base.BaseTestCase):
priv_lib._run_iproute_link,
"test_cmd", "eth0", None, test_param="test_value")
def test_run_iproute_link_op_not_supported(self):
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
ip_mock = iproute_mock()
ip_mock.__enter__().link_lookup.return_value = [2]
ip_mock.__enter__().link.side_effect = pyroute2.NetlinkError(
code=errno.EOPNOTSUPP)
self.assertRaises(
priv_lib.InterfaceOperationNotSupported,
priv_lib._run_iproute_link,
"test_cmd", "eth0", None, test_param="test_value")
def test_run_iproute_link_namespace_not_exists(self):
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
iproute_mock.side_effect = OSError(