From a298fd775b537839214802f161634215d2f827a8 Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Tue, 9 May 2017 20:23:05 -0600 Subject: [PATCH] sysconfig: Raise ValueError when multiple default gateways are present. Fixed setting Route.has_set_default_ipv6 or *_ipv4 to track whether a route already has a default gateway defined. The code was setting Route.has_set_default which wasn't checked when raising "duplicate gateway" ValueErrors. Added unit tests to exercise this expected raised ValueError. Also moved is_ipv6 = subnet.get('ipv6') logic out of a for loop because we don't need to recalculate the same value every route iteration. LP: #1687485 (cherry picked from commit dd03bb411c9a6f10854a3bbc3223b204c3d4d174) Resolves: rhbz#1438082 --- cloudinit/net/sysconfig.py | 14 ++++----- tests/unittests/test_net.py | 76 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py index 29c906f..d521d5c 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py @@ -230,12 +230,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 @@ -256,8 +252,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 ce13664..262c6d5 100755 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -515,6 +515,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): tmp_dir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, tmp_dir)