diff --git a/nova/tests/network/test_network_info.py b/nova/tests/network/test_network_info.py index 5840308c7b0b..821a9cf62097 100644 --- a/nova/tests/network/test_network_info.py +++ b/nova/tests/network/test_network_info.py @@ -378,8 +378,8 @@ class NetworkInfoTests(test.TestCase): fake_network_cache_model.new_ip( {'address': '10.10.0.3'})] * 4) - def _test_injected_network_template(self, should_inject, use_ipv6=False, - gateway=True): + def _test_injected_network_template(self, should_inject, use_ipv4=True, + use_ipv6=False, gateway=True): """Check that netutils properly decides whether to inject based on whether the supplied subnet is static or dynamic. """ @@ -391,7 +391,9 @@ class NetworkInfoTests(test.TestCase): if not should_inject: subnet_dict['dhcp_server'] = '10.10.0.1' - network.add_subnet(fake_network_cache_model.new_subnet(subnet_dict)) + if use_ipv4: + 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( @@ -419,22 +421,25 @@ class NetworkInfoTests(test.TestCase): if not should_inject: self.assertTrue(template is None) else: - self.assertTrue('auto eth0' in template) - self.assertTrue('iface eth0 inet static' in template) - 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) - 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_ipv4: + self.assertTrue('auto eth0' in template) + self.assertTrue('iface eth0 inet static' in template) + 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) + 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) if gateway: self.assertTrue('gateway 1234:567::1' in template) + if not use_ipv4 and not use_ipv6: + self.assertTrue(template is None) def test_injection_static(self): self._test_injected_network_template(should_inject=True) @@ -456,3 +461,22 @@ class NetworkInfoTests(test.TestCase): def test_injection_dynamic_nogateway(self): self._test_injected_network_template(should_inject=False, gateway=False) + + def test_injection_static_with_ipv4_off(self): + self._test_injected_network_template(should_inject=True, + use_ipv4=False) + + def test_injection_static_ipv6_with_ipv4_off(self): + self._test_injected_network_template(should_inject=True, + use_ipv6=True, + use_ipv4=False) + + def test_injection_static_ipv6_nogateway_with_ipv4_off(self): + self._test_injected_network_template(should_inject=True, + use_ipv6=True, + use_ipv4=False, + gateway=False) + + def test_injection_dynamic_with_ipv4_off(self): + self._test_injected_network_template(should_inject=False, + use_ipv4=False) diff --git a/nova/virt/netutils.py b/nova/virt/netutils.py index b36b533bdf30..fe0f3d46d43d 100644 --- a/nova/virt/netutils.py +++ b/nova/virt/netutils.py @@ -50,6 +50,17 @@ def get_ip_version(cidr): return int(net.version) +def _get_first_network(network, version): + # Using a generator expression with a next() call for the first element + # of a list since we don't want to evaluate the whole list as we can + # have a lot of subnets + try: + return (i for i in network['subnets'] + if i['version'] == version).next() + except StopIteration: + pass + + def get_injected_network_template(network_info, use_ipv6=CONF.use_ipv6, template=CONF.injected_network_template): """Returns a rendered network template for the given network_info. @@ -75,39 +86,45 @@ def get_injected_network_template(network_info, use_ipv6=CONF.use_ipv6, # NOTE(bnemec): The template only supports a single subnet per # interface and I'm not sure how/if that can be fixed, so this # code only takes the first subnet of the appropriate type. - subnet_v4 = [i for i in network['subnets'] if i['version'] == 4][0] - subnet_v6 = [i for i in network['subnets'] if i['version'] == 6] - if subnet_v6: - subnet_v6 = subnet_v6[0] + subnet_v4 = _get_first_network(network, 4) + subnet_v6 = _get_first_network(network, 6) ifc_num += 1 - if (not network.get_meta('injected') or not subnet_v4['ips'] or - subnet_v4.get_meta('dhcp_server') is not None): + if not network.get_meta('injected'): continue - ip = subnet_v4['ips'][0] - address = ip['address'] - netmask = model.get_netmask(ip, subnet_v4) + address = None + netmask = None gateway = '' - if subnet_v4['gateway']: - gateway = subnet_v4['gateway']['address'] - broadcast = str(subnet_v4.as_netaddr().broadcast) - dns = ' '.join([i['address'] for i in subnet_v4['dns']]) - # NOTE(bnemec): I don't think this code would handle a pure IPv6 - # environment properly, but I don't have such an environment in - # which to test/fix that. + broadcast = None + dns = None + if subnet_v4: + if subnet_v4.get_meta('dhcp_server') is not None: + continue + + if subnet_v4['ips']: + ip = subnet_v4['ips'][0] + address = ip['address'] + netmask = model.get_netmask(ip, subnet_v4) + if subnet_v4['gateway']: + gateway = subnet_v4['gateway']['address'] + broadcast = str(subnet_v4.as_netaddr().broadcast) + dns = ' '.join([i['address'] for i in subnet_v4['dns']]) + address_v6 = None - gateway_v6 = None + gateway_v6 = '' netmask_v6 = None have_ipv6 = (use_ipv6 and subnet_v6) if have_ipv6: + if subnet_v6.get_meta('dhcp_server') is not None: + continue + if subnet_v6['ips']: ipv6_is_available = True ip_v6 = subnet_v6['ips'][0] address_v6 = ip_v6['address'] netmask_v6 = model.get_netmask(ip_v6, subnet_v6) - gateway_v6 = '' if subnet_v6['gateway']: gateway_v6 = subnet_v6['gateway']['address']