sailesh1993 / rpms / cloud-init

Forked from rpms/cloud-init a year ago
Clone
3956c3
From 335d2b7270c151fd981d9e500f239ab75a59a4b3 Mon Sep 17 00:00:00 2001
3956c3
From: Ryan Harper <ryan.harper@canonical.com>
3956c3
Date: Wed, 25 Jan 2017 15:45:40 -0600
3956c3
Subject: [PATCH] Fix eni rendering of multiple IPs per interface
3956c3
3956c3
The iface:alias syntax for eni rendering is brittle with ipv6.
3956c3
Replace it with using multiple iface stanzas with the same iface
3956c3
name which is supported.  Side-effect is that one can no longer
3956c3
do 'ifup $iface:$alias' but requires instead use of ip address
3956c3
{add|delete} instead.
3956c3
3956c3
LP: #1657940
3956c3
(cherry picked from commit 2de1c247e285cce0b25ab70abdc56ccd41019c27)
3956c3
3956c3
Signed-off-by: Ryan McCabe <rmccabe@redhat.com>
3956c3
Resolves: rhbz#bz1497954
3956c3
---
3956c3
 cloudinit/net/eni.py        | 33 ++++++++++++++++++--------------
3956c3
 tests/unittests/test_net.py | 46 +++++++++++++++++++++++++++++++++------------
3956c3
 2 files changed, 53 insertions(+), 26 deletions(-)
3956c3
3956c3
diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py
3956c3
index b06ffac9..5b249f1f 100644
3956c3
--- a/cloudinit/net/eni.py
3956c3
+++ b/cloudinit/net/eni.py
3956c3
@@ -90,8 +90,6 @@ def _iface_add_attrs(iface, index):
3956c3
 
3956c3
 def _iface_start_entry(iface, index, render_hwaddress=False):
3956c3
     fullname = iface['name']
3956c3
-    if index != 0:
3956c3
-        fullname += ":%s" % index
3956c3
 
3956c3
     control = iface['control']
3956c3
     if control == "auto":
3956c3
@@ -113,6 +111,16 @@ def _iface_start_entry(iface, index, render_hwaddress=False):
3956c3
     return lines
3956c3
 
3956c3
 
3956c3
+def _subnet_is_ipv6(subnet):
3956c3
+    # 'static6' or 'dhcp6'
3956c3
+    if subnet['type'].endswith('6'):
3956c3
+        # This is a request for DHCPv6.
3956c3
+        return True
3956c3
+    elif subnet['type'] == 'static' and ":" in subnet['address']:
3956c3
+        return True
3956c3
+    return False
3956c3
+
3956c3
+
3956c3
 def _parse_deb_config_data(ifaces, contents, src_dir, src_path):
3956c3
     """Parses the file contents, placing result into ifaces.
3956c3
 
3956c3
@@ -354,21 +362,23 @@ class Renderer(renderer.Renderer):
3956c3
         sections = []
3956c3
         subnets = iface.get('subnets', {})
3956c3
         if subnets:
3956c3
-            for index, subnet in zip(range(0, len(subnets)), subnets):
3956c3
+            for index, subnet in enumerate(subnets):
3956c3
                 iface['index'] = index
3956c3
                 iface['mode'] = subnet['type']
3956c3
                 iface['control'] = subnet.get('control', 'auto')
3956c3
                 subnet_inet = 'inet'
3956c3
-                if iface['mode'].endswith('6'):
3956c3
-                    # This is a request for DHCPv6.
3956c3
-                    subnet_inet += '6'
3956c3
-                elif iface['mode'] == 'static' and ":" in subnet['address']:
3956c3
-                    # This is a static IPv6 address.
3956c3
+                if _subnet_is_ipv6(subnet):
3956c3
                     subnet_inet += '6'
3956c3
                 iface['inet'] = subnet_inet
3956c3
-                if iface['mode'].startswith('dhcp'):
3956c3
+                if subnet['type'].startswith('dhcp'):
3956c3
                     iface['mode'] = 'dhcp'
3956c3
 
3956c3
+                # do not emit multiple 'auto $IFACE' lines as older (precise)
3956c3
+                # ifupdown complains
3956c3
+                if True in ["auto %s" % (iface['name']) in line
3956c3
+                            for line in sections]:
3956c3
+                    iface['control'] = 'alias'
3956c3
+
3956c3
                 lines = list(
3956c3
                     _iface_start_entry(
3956c3
                         iface, index, render_hwaddress=render_hwaddress) +
3956c3
@@ -378,11 +388,6 @@ class Renderer(renderer.Renderer):
3956c3
                 for route in subnet.get('routes', []):
3956c3
                     lines.extend(self._render_route(route, indent="    "))
3956c3
 
3956c3
-                if len(subnets) > 1 and index == 0:
3956c3
-                    tmpl = "    post-up ifup %s:%s\n"
3956c3
-                    for i in range(1, len(subnets)):
3956c3
-                        lines.append(tmpl % (iface['name'], i))
3956c3
-
3956c3
                 sections.append(lines)
3956c3
         else:
3956c3
             # ifenslave docs say to auto the slave devices
3956c3
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
3956c3
index ffa911cc..4c0e3ad3 100644
3956c3
--- a/tests/unittests/test_net.py
3956c3
+++ b/tests/unittests/test_net.py
3956c3
@@ -376,11 +376,9 @@ NETWORK_CONFIGS = {
3956c3
 
3956c3
             auto eth99
3956c3
             iface eth99 inet dhcp
3956c3
-                post-up ifup eth99:1
3956c3
 
3956c3
-
3956c3
-            auto eth99:1
3956c3
-            iface eth99:1 inet static
3956c3
+            # control-alias eth99
3956c3
+            iface eth99 inet static
3956c3
                 address 192.168.21.3/24
3956c3
                 dns-nameservers 8.8.8.8 8.8.4.4
3956c3
                 dns-search barley.maas sach.maas
3956c3
@@ -418,6 +416,27 @@ NETWORK_CONFIGS = {
3956c3
                     - wark.maas
3956c3
         """),
3956c3
     },
3956c3
+    'v4_and_v6': {
3956c3
+        'expected_eni': textwrap.dedent("""\
3956c3
+            auto lo
3956c3
+            iface lo inet loopback
3956c3
+
3956c3
+            auto iface0
3956c3
+            iface iface0 inet dhcp
3956c3
+
3956c3
+            # control-alias iface0
3956c3
+            iface iface0 inet6 dhcp
3956c3
+        """).rstrip(' '),
3956c3
+        'yaml': textwrap.dedent("""\
3956c3
+            version: 1
3956c3
+            config:
3956c3
+              - type: 'physical'
3956c3
+                name: 'iface0'
3956c3
+                subnets:
3956c3
+                - {'type': 'dhcp4'}
3956c3
+                - {'type': 'dhcp6'}
3956c3
+        """).rstrip(' '),
3956c3
+    },
3956c3
     'all': {
3956c3
         'expected_eni': ("""\
3956c3
 auto lo
3956c3
@@ -455,11 +474,9 @@ iface br0 inet static
3956c3
     address 192.168.14.2/24
3956c3
     bridge_ports eth3 eth4
3956c3
     bridge_stp off
3956c3
-    post-up ifup br0:1
3956c3
-
3956c3
 
3956c3
-auto br0:1
3956c3
-iface br0:1 inet6 static
3956c3
+# control-alias br0
3956c3
+iface br0 inet6 static
3956c3
     address 2001:1::1/64
3956c3
 
3956c3
 auto bond0.200
3956c3
@@ -476,11 +493,9 @@ iface eth0.101 inet static
3956c3
     mtu 1500
3956c3
     vlan-raw-device eth0
3956c3
     vlan_id 101
3956c3
-    post-up ifup eth0.101:1
3956c3
-
3956c3
 
3956c3
-auto eth0.101:1
3956c3
-iface eth0.101:1 inet static
3956c3
+# control-alias eth0.101
3956c3
+iface eth0.101 inet static
3956c3
     address 192.168.2.10/24
3956c3
 
3956c3
 post-up route add -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
3956c3
@@ -1007,6 +1022,13 @@ class TestEniRoundTrip(TestCase):
3956c3
             entry['expected_eni'].splitlines(),
3956c3
             files['/etc/network/interfaces'].splitlines())
3956c3
 
3956c3
+    def testsimple_render_v4_and_v6(self):
3956c3
+        entry = NETWORK_CONFIGS['v4_and_v6']
3956c3
+        files = self._render_and_read(network_config=yaml.load(entry['yaml']))
3956c3
+        self.assertEqual(
3956c3
+            entry['expected_eni'].splitlines(),
3956c3
+            files['/etc/network/interfaces'].splitlines())
3956c3
+
3956c3
     def test_routes_rendered(self):
3956c3
         # as reported in bug 1649652
3956c3
         conf = [
3956c3
-- 
3956c3
2.13.6
3956c3