From 27fc4648b7cc3f748f7d6a56a778e61b1baf799f Mon Sep 17 00:00:00 2001 From: Mathieu Mitchell Date: Fri, 28 Jun 2013 12:31:54 -0400 Subject: [PATCH] Support networks without gateway Launching an instance when using network injection on a network containing a subnet that has no gateway fails in scheduling with a KeyError when using a legacy network_info provider and generates an invalid network file for the others. The following changes were done: * The legacy transformer for network_info now always provides a gateway/gateway_v6 field, with a value of None if no gateway is available (this is similar to the other fields that are empty). * The interfaces template was modified to include the gateway line only if a gateway is provided for the interface. Fixes: bug #1207878 Change-Id: I887757a6bcba528059ace8831a7d23a31b08c630 --- nova/network/model.py | 7 +- nova/tests/network/test_network_info.py | 86 ++++++++++++++++++------- nova/virt/interfaces.template | 4 ++ 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/nova/network/model.py b/nova/network/model.py index 2731d4d810b3..31eafa28b5ad 100644 --- a/nova/network/model.py +++ b/nova/network/model.py @@ -419,6 +419,7 @@ class NetworkInfo(list): 'qbg_params': vif.get('qbg_params'), 'rxtx_cap': vif.get_meta('rxtx_cap', 0), 'dns': [get_ip(ip) for ip in subnet_v4['dns']], + 'gateway': gateway, 'ips': [fixed_ip_dict(ip, subnet) for subnet in v4_subnets for ip in subnet['ips']], @@ -428,12 +429,8 @@ class NetworkInfo(list): if routes: info_dict['routes'] = routes - if gateway: - info_dict['gateway'] = gateway - if v6_subnets: - if subnet_v6['gateway']: - info_dict['gateway_v6'] = get_ip(subnet_v6['gateway']) + info_dict['gateway_v6'] = get_ip(subnet_v6['gateway']) # NOTE(tr3buchet): only supporting single v6 subnet here info_dict['ip6s'] = [fixed_ip_dict(ip, subnet_v6) for ip in subnet_v6['ips']] diff --git a/nova/tests/network/test_network_info.py b/nova/tests/network/test_network_info.py index 38a27b51c7a8..b27a36cdae86 100644 --- a/nova/tests/network/test_network_info.py +++ b/nova/tests/network/test_network_info.py @@ -379,28 +379,34 @@ class NetworkInfoTests(test.TestCase): {'address': '10.10.0.3'})] * 4) def _test_injected_network_template(self, should_inject, use_ipv6=False, - legacy=False): + legacy=False, gateway=True): """Check that netutils properly decides whether to inject based on whether the supplied subnet is static or dynamic. """ network = fake_network_cache_model.new_network({'subnets': []}) - if should_inject: - network.add_subnet(fake_network_cache_model.new_subnet()) - if use_ipv6: - gateway_ip = fake_network_cache_model.new_ip(dict( - address='1234:567::1')) - ip = fake_network_cache_model.new_ip(dict( - address='1234:567::2')) - subnet_dict = dict( - cidr='1234:567::/48', - gateway=gateway_ip, - ips=[ip]) - network.add_subnet(fake_network_cache_model.new_subnet( - subnet_dict)) - else: - subnet_dict = dict(dhcp_server='10.10.0.1') + subnet_dict = {} + if not gateway: + subnet_dict['gateway'] = None + + if not should_inject: + subnet_dict['dhcp_server'] = '10.10.0.1' + + network.add_subnet(fake_network_cache_model.new_subnet(subnet_dict)) + + if should_inject and use_ipv6: + gateway_ip = fake_network_cache_model.new_ip(dict( + address='1234:567::1')) + ip = fake_network_cache_model.new_ip(dict( + address='1234:567::2')) + ipv6_subnet_dict = dict( + cidr='1234:567::/48', + gateway=gateway_ip, + ips=[ip]) + if not gateway: + ipv6_subnet_dict['gateway'] = None network.add_subnet(fake_network_cache_model.new_subnet( - subnet_dict)) + ipv6_subnet_dict)) + # Behave as though CONF.flat_injected is True network['meta']['injected'] = True vif = fake_network_cache_model.new_vif({'network': network}) @@ -424,30 +430,62 @@ class NetworkInfoTests(test.TestCase): self.assertTrue('address 10.10.0.2' in template) self.assertTrue('netmask 255.255.255.0' in template) self.assertTrue('broadcast 10.10.0.255' in template) - self.assertTrue('gateway 10.10.0.1' in template) + if gateway: + self.assertTrue('gateway 10.10.0.1' in template) + else: + self.assertFalse('gateway' in template) self.assertTrue('dns-nameservers 1.2.3.4 2.3.4.5' in template) if use_ipv6: self.assertTrue('iface eth0 inet6 static' in template) self.assertTrue('address 1234:567::2' in template) self.assertTrue('netmask 48' in template) - self.assertTrue('gateway 1234:567::1' in template) + if gateway: + self.assertTrue('gateway 1234:567::1' in template) def test_injection_static(self): self._test_injected_network_template(should_inject=True) - def test_injection_static_ipv6(self): - self._test_injected_network_template(should_inject=True, use_ipv6=True) - - def test_injection_dynamic(self): - self._test_injected_network_template(should_inject=False) + def test_injection_static_nogateway(self): + self._test_injected_network_template(should_inject=True, gateway=False) def test_injection_static_legacy(self): self._test_injected_network_template(should_inject=True, legacy=True) + def test_injection_static_legacy_nogateway(self): + self._test_injected_network_template(should_inject=True, + legacy=True, + gateway=False) + + def test_injection_static_ipv6(self): + self._test_injected_network_template(should_inject=True, use_ipv6=True) + + def test_injection_static_ipv6_nogateway(self): + self._test_injected_network_template(should_inject=True, + use_ipv6=True, + gateway=False) + def test_injection_static_ipv6_legacy(self): self._test_injected_network_template(should_inject=True, use_ipv6=True, legacy=True) + def test_injection_static_ipv6_legacy_nogateway(self): + self._test_injected_network_template(should_inject=True, + use_ipv6=True, + legacy=True, + gateway=False) + + def test_injection_dynamic(self): + self._test_injected_network_template(should_inject=False) + + def test_injection_dynamic_nogateway(self): + self._test_injected_network_template(should_inject=False, + gateway=False) + def test_injection_dynamic_legacy(self): self._test_injected_network_template(should_inject=False, legacy=True) + + def test_injection_dynamic_legacy_nogateway(self): + self._test_injected_network_template(should_inject=False, + legacy=True, + gateway=False) diff --git a/nova/virt/interfaces.template b/nova/virt/interfaces.template index e75c3735743d..ba01064ccc21 100644 --- a/nova/virt/interfaces.template +++ b/nova/virt/interfaces.template @@ -13,7 +13,9 @@ iface ${ifc.name} inet static address ${ifc.address} netmask ${ifc.netmask} broadcast ${ifc.broadcast} +#if $ifc.gateway gateway ${ifc.gateway} +#end if #if $ifc.dns dns-nameservers ${ifc.dns} #end if @@ -22,7 +24,9 @@ iface ${ifc.name} inet static iface ${ifc.name} inet6 static address ${ifc.address_v6} netmask ${ifc.netmask_v6} +#if $ifc.gateway_v6 gateway ${ifc.gateway_v6} #end if +#end if #end for