]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Linux device name can have '@' or ':' characters
authorÉdouard Thuleau <edouard.thuleau@cloudwatt.com>
Tue, 29 Oct 2013 09:43:18 +0000 (09:43 +0000)
committerÉdouard Thuleau <edouard.thuleau@cloudwatt.com>
Tue, 12 Nov 2013 10:27:31 +0000 (10:27 +0000)
It's possible to set '@' or ':' character in Linux device name. But
Neutron IP lib doesn't handle correctly these names.

To distinguish VLAN devices from others devices with '@' in their name,
the details option in iproute2 is used.

Change-Id: I7ed24ec00f481207d97bdef052f86388f24d9b21
Closes-Bug: #1245799

neutron/agent/linux/ip_lib.py
neutron/tests/unit/test_linux_ip_lib.py

index e46c7b4809f644e8dbe1ec33564a13cd90b6e566..aa44b1e2994bc435a2f2a589ccc105045d23ee8a 100644 (file)
@@ -29,6 +29,11 @@ OPTS = [
 
 
 LOOPBACK_DEVNAME = 'lo'
+# NOTE(ethuleau): depend of the version of iproute2, the vlan
+# interface details vary.
+VLAN_INTERFACE_DETAIL = ['vlan protocol 802.1q',
+                         'vlan protocol 802.1Q',
+                         'vlan id']
 
 
 class SubProcessBase(object):
@@ -87,14 +92,18 @@ class IPWrapper(SubProcessBase):
 
     def get_devices(self, exclude_loopback=False):
         retval = []
-        output = self._execute('o', 'link', ('list',),
+        output = self._execute(['o', 'd'], 'link', ('list',),
                                self.root_helper, self.namespace)
         for line in output.split('\n'):
             if '<' not in line:
                 continue
-            tokens = line.split(':', 2)
-            if len(tokens) >= 3:
-                name = tokens[1].split('@', 1)[0].strip()
+            tokens = line.split(' ', 2)
+            if len(tokens) == 3:
+                if any(v in tokens[2] for v in VLAN_INTERFACE_DETAIL):
+                    delimiter = '@'
+                else:
+                    delimiter = ':'
+                name = tokens[1].rpartition(delimiter)[0].strip()
 
                 if exclude_loopback and name == LOOPBACK_DEVNAME:
                     continue
index e17dc8baf05f094e224fe14174caca993e807c51..7ae10670bfc638c94f1037b453961fc9cbd49de5 100644 (file)
@@ -28,17 +28,51 @@ NETNS_SAMPLE = [
 
 LINK_SAMPLE = [
     '1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN \\'
-    'link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00',
+    'link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0',
     '2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP '
     'qlen 1000\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff'
     '\    alias openvswitch',
     '3: br-int: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN '
-    '\    link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff',
+    '\    link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff promiscuity 0',
     '4: gw-ddc717df-49: <BROADCAST,MULTICAST> mtu 1500 qdisc noop '
-    'state DOWN \    link/ether fe:dc:ba:fe:dc:ba brd ff:ff:ff:ff:ff:ff',
-    '5: eth0.50@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc '
+    'state DOWN \    link/ether fe:dc:ba:fe:dc:ba brd ff:ff:ff:ff:ff:ff '
+    'promiscuity 0',
+    '5: foo:foo: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state '
+    'UP qlen 1000\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff '
+    'promiscuity 0',
+    '6: foo@foo: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state '
+    'UP qlen 1000\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff '
+    'promiscuity 0',
+    '7: foo:foo@foo: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq '
+    'state UP qlen 1000'
+    '\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff promiscuity 0',
+    '8: foo@foo:foo: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq '
+    'state UP qlen 1000'
+    '\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff promiscuity 0',
+    '9: bar.9@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc '
     ' noqueue master brq0b24798c-07 state UP mode DEFAULT'
-    '\    link/ether ab:04:49:b6:ab:a0 brd ff:ff:ff:ff:ff:ff']
+    '\    link/ether ab:04:49:b6:ab:a0 brd ff:ff:ff:ff:ff:ff promiscuity 0'
+    '\    vlan protocol 802.1q id 9 <REORDER_HDR>',
+    '10: bar@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc '
+    ' noqueue master brq0b24798c-07 state UP mode DEFAULT'
+    '\    link/ether ab:04:49:b6:ab:a0 brd ff:ff:ff:ff:ff:ff promiscuity 0'
+    '\    vlan protocol 802.1Q id 10 <REORDER_HDR>',
+    '11: bar:bar@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq '
+    'state UP qlen 1000'
+    '\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff promiscuity 0'
+    '\    vlan id 11 <REORDER_HDR>',
+    '12: bar@bar@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq '
+    'state UP qlen 1000'
+    '\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff promiscuity 0'
+    '\    vlan id 12 <REORDER_HDR>',
+    '13: bar:bar@bar@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 '
+    'qdisc mq state UP qlen 1000'
+    '\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff promiscuity 0'
+    '\    vlan protocol 802.1q id 13 <REORDER_HDR>',
+    '14: bar@bar:bar@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 '
+    'qdisc mq state UP qlen 1000'
+    '\    link/ether cc:dd:ee:ff:ab:cd brd ff:ff:ff:ff:ff:ff promiscuity 0'
+    '\    vlan protocol 802.1Q id 14 <REORDER_HDR>']
 
 ADDR_SAMPLE = ("""
 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
@@ -168,9 +202,18 @@ class TestIpWrapper(base.BaseTestCase):
                           ip_lib.IPDevice('eth0'),
                           ip_lib.IPDevice('br-int'),
                           ip_lib.IPDevice('gw-ddc717df-49'),
-                          ip_lib.IPDevice('eth0.50')])
-
-        self.execute.assert_called_once_with('o', 'link', ('list',),
+                          ip_lib.IPDevice('foo:foo'),
+                          ip_lib.IPDevice('foo@foo'),
+                          ip_lib.IPDevice('foo:foo@foo'),
+                          ip_lib.IPDevice('foo@foo:foo'),
+                          ip_lib.IPDevice('bar.9'),
+                          ip_lib.IPDevice('bar'),
+                          ip_lib.IPDevice('bar:bar'),
+                          ip_lib.IPDevice('bar@bar'),
+                          ip_lib.IPDevice('bar:bar@bar'),
+                          ip_lib.IPDevice('bar@bar:bar')])
+
+        self.execute.assert_called_once_with(['o', 'd'], 'link', ('list',),
                                              'sudo', None)
 
     def test_get_devices_malformed_line(self):
@@ -181,9 +224,18 @@ class TestIpWrapper(base.BaseTestCase):
                           ip_lib.IPDevice('eth0'),
                           ip_lib.IPDevice('br-int'),
                           ip_lib.IPDevice('gw-ddc717df-49'),
-                          ip_lib.IPDevice('eth0.50')])
-
-        self.execute.assert_called_once_with('o', 'link', ('list',),
+                          ip_lib.IPDevice('foo:foo'),
+                          ip_lib.IPDevice('foo@foo'),
+                          ip_lib.IPDevice('foo:foo@foo'),
+                          ip_lib.IPDevice('foo@foo:foo'),
+                          ip_lib.IPDevice('bar.9'),
+                          ip_lib.IPDevice('bar'),
+                          ip_lib.IPDevice('bar:bar'),
+                          ip_lib.IPDevice('bar@bar'),
+                          ip_lib.IPDevice('bar:bar@bar'),
+                          ip_lib.IPDevice('bar@bar:bar')])
+
+        self.execute.assert_called_once_with(['o', 'd'], 'link', ('list',),
                                              'sudo', None)
 
     def test_get_namespaces(self):