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
This commit is contained in:
Mathieu Mitchell
2013-06-28 12:31:54 -04:00
committed by Mathieu Gagné
parent e685a72424
commit 27fc4648b7
3 changed files with 68 additions and 29 deletions

View File

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

View File

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

View File

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