Last active
April 28, 2016 14:35
-
-
Save zioproto/9aba7336b18e9769a85d55d520540456 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 74252dd0915310013dbdf7b53fe813590bb4ca0a | |
Author: Saverio Proto <[email protected]> | |
Date: Thu Apr 21 16:50:07 2016 +0200 | |
Check if namespace exists before exec commands | |
If a neutron router has no ports defined, its namespace is deleted. | |
It is required to check if the namespace exists before calling | |
exec commands against the namespace. | |
It is not enough for the string of the namespace uuid to be defined, | |
the namespace must really exist on the network node. | |
Otherwise the agent log file will be flooded with messages like | |
Cannot open network namespace "qrouter-<uuid>": No such file or directory | |
Failed to process compatible router '<uuid>' | |
Related-bug: 1573073 | |
Change-Id: I744ef11529f9da5cbfdb812de0b35b95f9d078bb | |
diff --git a/neutron/agent/linux/ip_lib.py b/neutron/agent/linux/ip_lib.py | |
index 903e68f..9e6ba79 100644 | |
--- a/neutron/agent/linux/ip_lib.py | |
+++ b/neutron/agent/linux/ip_lib.py | |
@@ -92,16 +92,19 @@ class IPWrapper(SubProcessBase): | |
def get_devices(self, exclude_loopback=False): | |
retval = [] | |
+ output = [] | |
if self.namespace: | |
- # we call out manually because in order to avoid screen scraping | |
- # iproute2 we use find to see what is in the sysfs directory, as | |
- # suggested by Stephen Hemminger (iproute2 dev). | |
- output = utils.execute(['ip', 'netns', 'exec', self.namespace, | |
- 'find', SYS_NET_PATH, '-maxdepth', '1', | |
- '-type', 'l', '-printf', '%f '], | |
- run_as_root=True, | |
- log_fail_as_error=self.log_fail_as_error | |
- ).split() | |
+ if self.netns.exists(self.namespace): | |
+ # we call out manually because in order to avoid screen | |
+ # scraping iproute2 we use find to see what is in the sysfs | |
+ # directory, as suggested by Stephen Hemminger (iproute2 dev). | |
+ output = utils.execute(['ip', 'netns', 'exec', self.namespace, | |
+ 'find', SYS_NET_PATH, '-maxdepth', '1', | |
+ '-type', 'l', '-printf', '%f '], | |
+ run_as_root=True, | |
+ log_fail_as_error=self.log_fail_as_error | |
+ ).split() | |
+ # if self.namespace is not defined handle the default namespace devices | |
else: | |
output = ( | |
i for i in os.listdir(SYS_NET_PATH) | |
diff --git a/neutron/agent/linux/ipset_manager.py b/neutron/agent/linux/ipset_manager.py | |
index 4120693..e63c4ad 100644 | |
--- a/neutron/agent/linux/ipset_manager.py | |
+++ b/neutron/agent/linux/ipset_manager.py | |
@@ -14,6 +14,7 @@ | |
import netaddr | |
from neutron.agent.linux import utils as linux_utils | |
+from neutron.agent.linux import ip_lib | |
from neutron.common import utils | |
IPSET_ADD_BULK_THRESHOLD = 5 | |
@@ -134,9 +135,15 @@ class IpsetManager(object): | |
cmd_ns = [] | |
if self.namespace: | |
cmd_ns.extend(['ip', 'netns', 'exec', self.namespace]) | |
- cmd_ns.extend(cmd) | |
- self.execute(cmd_ns, run_as_root=True, process_input=input, | |
- check_exit_code=fail_on_errors) | |
+ cmd_ns.extend(cmd) | |
+ ip = ip_lib.IPWrapper() | |
+ if ip.netns.exists(self.namespace): | |
+ self.execute(cmd_ns, run_as_root=True, process_input=input, | |
+ check_exit_code=fail_on_errors) | |
+ else: | |
+ cmd_ns.extend(cmd) | |
+ self.execute(cmd_ns, run_as_root=True, process_input=input, | |
+ check_exit_code=fail_on_errors) | |
def _get_new_set_ips(self, set_name, expected_ips): | |
new_member_ips = (set(expected_ips) - | |
diff --git a/neutron/agent/linux/iptables_manager.py b/neutron/agent/linux/iptables_manager.py | |
index 604db0c..4c463ea 100644 | |
--- a/neutron/agent/linux/iptables_manager.py | |
+++ b/neutron/agent/linux/iptables_manager.py | |
@@ -32,6 +32,7 @@ from oslo_utils import excutils | |
from neutron.agent.common import config | |
from neutron.agent.linux import iptables_comments as ic | |
from neutron.agent.linux import utils as linux_utils | |
+from neutron.agent.linux import ip_lib | |
from neutron.common import exceptions as n_exc | |
from neutron.common import utils | |
from neutron.i18n import _LE, _LW | |
@@ -445,8 +446,17 @@ class IptablesManager(object): | |
args = ['%s-save' % (cmd,), '-c'] | |
if self.namespace: | |
args = ['ip', 'netns', 'exec', self.namespace] + args | |
- all_tables = self.execute(args, run_as_root=True) | |
+ ip = ip_lib.IPWrapper() | |
+ if ip.netns.exists(self.namespace): | |
+ all_tables = self.execute(args, run_as_root=True) | |
+ else: | |
+ LOG.debug("IPTablesManager.apply tried to access a not " | |
+ "existing namespace on the network node.") | |
+ return | |
+ else: | |
+ all_tables = self.execute(args, run_as_root=True) | |
all_lines = all_tables.split('\n') | |
+ commands = [] | |
# Traverse tables in sorted order for predictable dump output | |
for table_name in sorted(tables): | |
table = tables[table_name] | |
diff --git a/neutron/tests/unit/agent/linux/test_ip_lib.py b/neutron/tests/unit/agent/linux/test_ip_lib.py | |
index 6ad7b50..d7bcdac 100644 | |
--- a/neutron/tests/unit/agent/linux/test_ip_lib.py | |
+++ b/neutron/tests/unit/agent/linux/test_ip_lib.py | |
@@ -253,13 +253,15 @@ class TestIpWrapper(base.BaseTestCase): | |
fake_str = mock.Mock() | |
fake_str.split.return_value = ['lo'] | |
mocked_execute.return_value = fake_str | |
- retval = ip_lib.IPWrapper(namespace='foo').get_devices() | |
- mocked_execute.assert_called_once_with( | |
- ['ip', 'netns', 'exec', 'foo', 'find', '/sys/class/net', | |
- '-maxdepth', '1', '-type', 'l', '-printf', '%f '], | |
- run_as_root=True, log_fail_as_error=True) | |
- self.assertTrue(fake_str.split.called) | |
- self.assertEqual(retval, [ip_lib.IPDevice('lo', namespace='foo')]) | |
+ with mock.patch.object(ip_lib, 'IpNetnsCommand') as ip_ns_cmd: | |
+ ip_ns_cmd.exists.return_value = True | |
+ retval = ip_lib.IPWrapper(namespace='foo').get_devices() | |
+ mocked_execute.assert_called_once_with( | |
+ ['ip', 'netns', 'exec', 'foo', 'find', '/sys/class/net', | |
+ '-maxdepth', '1', '-type', 'l', '-printf', '%f '], | |
+ run_as_root=True, log_fail_as_error=True) | |
+ self.assertTrue(fake_str.split.called) | |
+ self.assertEqual(retval, [ip_lib.IPDevice('lo', namespace='foo')]) | |
def test_get_namespaces(self): | |
self.execute.return_value = '\n'.join(NETNS_SAMPLE) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment