← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~chad.smith/cloud-init:sysconfig-has-default into cloud-init:master

 

Chad Smith has proposed merging ~chad.smith/cloud-init:sysconfig-has-default into cloud-init:master.

Requested reviews:
  cloud init development team (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~chad.smith/cloud-init/+git/cloud-init/+merge/323819

sysconfig: Properly set Route.has_set_default_(ipv4|ipv6) when processing default gateways.

This fixes a regression when Route class definition changed to track ipv6 vs ipv4 default gateways. Added unit tests to exercise the intended logic which would raise a ValueError if multiple default gateway for ipv4 or ipv6 were found.
-- 
Your team cloud init development team is requested to review the proposed merge of ~chad.smith/cloud-init:sysconfig-has-default into cloud-init:master.
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 504e4d0..d981277 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -232,12 +232,8 @@ class Renderer(renderer.Renderer):
                                                       iface_cfg.name))
         if 'netmask' in subnet:
             iface_cfg['NETMASK'] = subnet['netmask']
+        is_ipv6 = subnet.get('ipv6')
         for route in subnet.get('routes', []):
-            if subnet.get('ipv6'):
-                gw_cfg = 'IPV6_DEFAULTGW'
-            else:
-                gw_cfg = 'GATEWAY'
-
             if _is_default_route(route):
                 if (
                         (subnet.get('ipv4') and
@@ -258,8 +254,12 @@ class Renderer(renderer.Renderer):
                 # also provided the default route?
                 iface_cfg['DEFROUTE'] = True
                 if 'gateway' in route:
-                    iface_cfg[gw_cfg] = route['gateway']
-                route_cfg.has_set_default = True
+                    if is_ipv6:
+                        iface_cfg['IPV6_DEFAULTGW'] = route['gateway']
+                        route_cfg.has_set_default_ipv6 = True
+                    else:
+                        iface_cfg['GATEWAY'] = route['gateway']
+                        route_cfg.has_set_default_ipv4 = True
             else:
                 gw_key = 'GATEWAY%s' % route_cfg.last_idx
                 nm_key = 'NETMASK%s' % route_cfg.last_idx
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 89e7536..eec4159 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -880,6 +880,82 @@ USERCTL=no
 """.lstrip()
             self.assertEqual(expected_content, content)
 
+    def test_multiple_ipv4_default_gateways(self):
+        """ValueError is raised when duplicate ipv4 gateways exist."""
+        net_json = {
+            "services": [{"type": "dns", "address": "172.19.0.12"}],
+            "networks": [{
+                "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4",
+                "type": "ipv4", "netmask": "255.255.252.0",
+                "link": "tap1a81968a-79",
+                "routes": [{
+                    "netmask": "0.0.0.0",
+                    "network": "0.0.0.0",
+                    "gateway": "172.19.3.254",
+                }, {
+                    "netmask": "0.0.0.0",  # A second default gateway
+                    "network": "0.0.0.0",
+                    "gateway": "172.20.3.254",
+                }],
+                "ip_address": "172.19.1.34", "id": "network0"
+            }],
+            "links": [
+                {
+                    "ethernet_mac_address": "fa:16:3e:ed:9a:59",
+                    "mtu": None, "type": "bridge", "id":
+                    "tap1a81968a-79",
+                    "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f"
+                },
+            ],
+        }
+        macs = {'fa:16:3e:ed:9a:59': 'eth0'}
+        render_dir = self.tmp_dir()
+        network_cfg = openstack.convert_net_json(net_json, known_macs=macs)
+        ns = network_state.parse_net_config_data(network_cfg,
+                                                 skip_broken=False)
+        renderer = sysconfig.Renderer()
+        with self.assertRaises(ValueError):
+            renderer.render_network_state(ns, render_dir)
+        self.assertEqual([], os.listdir(render_dir))
+
+    def test_multiple_ipv6_default_gateways(self):
+        """ValueError is raised when duplicate ipv6 gateways exist."""
+        net_json = {
+            "services": [{"type": "dns", "address": "172.19.0.12"}],
+            "networks": [{
+                "network_id": "public-ipv6",
+                "type": "ipv6", "netmask": "",
+                "link": "tap1a81968a-79",
+                "routes": [{
+                    "gateway": "2001:DB8::1",
+                    "netmask": "::",
+                    "network": "::"
+                }, {
+                    "gateway": "2001:DB9::1",
+                    "netmask": "::",
+                    "network": "::"
+                }],
+                "ip_address": "2001:DB8::10", "id": "network1"
+            }],
+            "links": [
+                {
+                    "ethernet_mac_address": "fa:16:3e:ed:9a:59",
+                    "mtu": None, "type": "bridge", "id":
+                    "tap1a81968a-79",
+                    "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f"
+                },
+            ],
+        }
+        macs = {'fa:16:3e:ed:9a:59': 'eth0'}
+        render_dir = self.tmp_dir()
+        network_cfg = openstack.convert_net_json(net_json, known_macs=macs)
+        ns = network_state.parse_net_config_data(network_cfg,
+                                                 skip_broken=False)
+        renderer = sysconfig.Renderer()
+        with self.assertRaises(ValueError):
+            renderer.render_network_state(ns, render_dir)
+        self.assertEqual([], os.listdir(render_dir))
+
     def test_openstack_rendering_samples(self):
         for os_sample in OS_SAMPLES:
             render_dir = self.tmp_dir()

Follow ups