Fix network info injection in pure IPv6 environment

get_non_legacy_network_template assumes that IPv4 is always available

So if i try to use Nova Network without any ipv4 using say
"nova network-create public --fixed-range-v6 fd8c:215d:178e:452:0:0:0:0/64"
then the deployment fails. So fix the code to ensure ipv4 is optional

Fixes LP# 1216178

Change-Id: Ib0c47a49debd4fed83d382a301687df23ca2ec0d
This commit is contained in:
Davanum Srinivas 2013-08-23 22:37:09 -04:00 committed by Gerrit Code Review
parent db6721b5f8
commit 6bee0a889f
2 changed files with 72 additions and 31 deletions

View File

@ -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)

View File

@ -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']