Merge "Make sure that gateway is in CIDR range by default"

This commit is contained in:
Jenkins 2014-08-05 07:54:22 +00:00 committed by Gerrit Code Review
commit 5ec2f9e5b4
8 changed files with 72 additions and 38 deletions

View File

@ -115,8 +115,10 @@ lock_path = $state_path/lock
# Attention: the following parameter MUST be set to False if Neutron is
# being used in conjunction with nova security groups
# allow_overlapping_ips = False
# Ensure that configured gateway is on subnet
# force_gateway_on_subnet = False
# Ensure that configured gateway is on subnet. For IPv6, validate only if
# gateway is not a link local address. Deprecated, to be removed during the
# K release, at which point the check will be mandatory.
# force_gateway_on_subnet = True
# Default maximum number of items returned in a single response,
# value == infinite and value < 0 means no max limit, and value must

View File

@ -80,8 +80,12 @@ core_opts = [
help=_("Allow overlapping IP support in Neutron")),
cfg.StrOpt('host', default=utils.get_hostname(),
help=_("The hostname Neutron is running on")),
cfg.BoolOpt('force_gateway_on_subnet', default=False,
help=_("Ensure that configured gateway is on subnet")),
cfg.BoolOpt('force_gateway_on_subnet', default=True,
help=_("Ensure that configured gateway is on subnet. "
"For IPv6, validate only if gateway is not a link "
"local address. Deprecated, to be removed during the "
"K release, at which point the check will be "
"mandatory.")),
cfg.BoolOpt('notify_nova_on_port_status_changes', default=True,
help=_("Send notification to nova when port status changes")),
cfg.BoolOpt('notify_nova_on_port_data_changes', default=True,

View File

@ -317,8 +317,16 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
return True
return False
@staticmethod
def _check_subnet_ip(cidr, ip_address):
@classmethod
def _check_gateway_in_subnet(cls, cidr, gateway):
"""Validate that the gateway is on the subnet."""
ip = netaddr.IPAddress(gateway)
if ip.version == 4 or (ip.version == 6 and not ip.is_link_local()):
return cls._check_subnet_ip(cidr, gateway)
return True
@classmethod
def _check_subnet_ip(cls, cidr, ip_address):
"""Validate that the IP address is on the subnet."""
ip = netaddr.IPAddress(ip_address)
net = netaddr.IPNetwork(cidr)
@ -375,8 +383,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
filter = {'network_id': [network_id]}
subnets = self.get_subnets(context, filters=filter)
for subnet in subnets:
if NeutronDbPluginV2._check_subnet_ip(subnet['cidr'],
fixed['ip_address']):
if self._check_subnet_ip(subnet['cidr'],
fixed['ip_address']):
found = True
subnet_id = subnet['id']
break
@ -405,8 +413,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
# Ensure that the IP is valid on the subnet
if (not found and
not NeutronDbPluginV2._check_subnet_ip(
subnet['cidr'], fixed['ip_address'])):
not self._check_subnet_ip(subnet['cidr'],
fixed['ip_address'])):
msg = _('IP address %s is not a valid IP for the defined '
'subnet') % fixed['ip_address']
raise n_exc.InvalidInput(error_message=msg)
@ -930,8 +938,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
if attributes.is_attr_set(s.get('gateway_ip')):
self._validate_ip_version(ip_ver, s['gateway_ip'], 'gateway_ip')
if (cfg.CONF.force_gateway_on_subnet and
not NeutronDbPluginV2._check_subnet_ip(s['cidr'],
s['gateway_ip'])):
not self._check_gateway_in_subnet(
s['cidr'], s['gateway_ip'])):
error_message = _("Gateway is not valid on subnet")
raise n_exc.InvalidInput(error_message=error_message)
# Ensure the gateway IP is not assigned to any port

View File

@ -550,7 +550,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase):
'name': 'subnet1',
'tenant_id':
network['network']['tenant_id'],
'gateway_ip': '10.0.2.1'}}
'gateway_ip': '10.0.20.1'}}
req = self.new_create_request('subnets', data)
res = req.get_response(self.api)
self.assertEqual(500, res.status_int)
@ -577,7 +577,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase):
'name': 'subnet1',
'tenant_id':
network['network']['tenant_id'],
'gateway_ip': '10.0.2.1'}}
'gateway_ip': '10.0.20.1'}}
subnet_req = self.new_create_request('subnets', data)
subnet_res = subnet_req.get_response(self.api)
self.assertEqual(201, subnet_res.status_int)
@ -608,7 +608,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase):
'name': 'subnet1',
'tenant_id':
network['network']['tenant_id'],
'gateway_ip': '10.0.2.1'}}
'gateway_ip': '10.0.20.1'}}
subnet_req = self.new_create_request('subnets', data)
subnet_res = subnet_req.get_response(self.api)
self.assertEqual(201, subnet_res.status_int)

View File

@ -216,6 +216,10 @@ class TestNuageSubnetsV2(NuagePluginV2TestCase,
self.skipTest("Plugin does not support "
"Neutron Subnet no-gateway option")
def test_create_subnet_nonzero_cidr(self):
self.skipTest("Plugin does not support "
"Neutron Subnet no-gateway option")
def test_create_subnet_with_none_gateway_fully_allocated(self):
self.skipTest("Plugin does not support Neutron "
"Subnet no-gateway option")
@ -235,7 +239,9 @@ class TestNuagePluginPortBinding(NuagePluginV2TestCase,
class TestNuagePortsV2(NuagePluginV2TestCase,
test_db_plugin.TestPortsV2):
pass
def test_no_more_port_exception(self):
self.skipTest("Plugin does not support "
"Neutron Subnet no-gateway option")
class TestNuageL3NatTestCase(NuagePluginV2TestCase,

View File

@ -87,6 +87,12 @@ class TestOneConvergencePluginSubnetsV2(test_plugin.TestSubnetsV2,
def test_update_subnet_ipv6_inconsistent_address_attribute(self):
self.skipTest("NVSD Plugin does not support IPV6.")
def test_create_subnet_ipv6_out_of_cidr_global(self):
self.skipTest("NVSD Plugin does not support IPV6.")
def test_create_subnet_ipv6_out_of_cidr_lla(self):
self.skipTest("NVSD Plugin does not support IPV6.")
class TestOneConvergencePluginPortsV2(test_plugin.TestPortsV2,
test_bindings.PortBindingsTestCase,

View File

@ -1148,7 +1148,7 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s
data['port']['fixed_ips'])
def test_no_more_port_exception(self):
with self.subnet(cidr='10.0.0.0/32') as subnet:
with self.subnet(cidr='10.0.0.0/32', gateway_ip=None) as subnet:
id = subnet['subnet']['network_id']
res = self._create_port(self.fmt, id)
data = self.deserialize(self.fmt, res)
@ -2587,7 +2587,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
self.subnet(cidr='14.129.122.5/22'),
self.subnet(cidr='15.129.122.5/24'),
self.subnet(cidr='16.129.122.5/28'),
self.subnet(cidr='17.129.122.5/32')
self.subnet(cidr='17.129.122.5/32', gateway_ip=None)
) as subs:
# the API should accept and correct these for users
self.assertEqual(subs[0]['subnet']['cidr'], '10.0.0.0/8')
@ -2728,15 +2728,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
allocation_pools)
def test_create_subnet_gw_values(self):
# Gateway not in subnet
gateway = '100.0.0.1'
cidr = '10.0.0.0/24'
allocation_pools = [{'start': '10.0.0.1',
'end': '10.0.0.254'}]
expected = {'gateway_ip': gateway,
'cidr': cidr,
'allocation_pools': allocation_pools}
self._test_create_subnet(expected=expected, gateway_ip=gateway)
# Gateway is last IP in range
gateway = '10.0.0.254'
allocation_pools = [{'start': '10.0.0.1',
@ -2755,8 +2747,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
self._test_create_subnet(expected=expected,
gateway_ip=gateway)
def test_create_subnet_gw_outside_cidr_force_on_returns_400(self):
cfg.CONF.set_override('force_gateway_on_subnet', True)
def test_create_subnet_gw_outside_cidr_returns_400(self):
with self.network() as network:
self._create_subnet(self.fmt,
network['network']['id'],
@ -2764,8 +2755,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
webob.exc.HTTPClientError.code,
gateway_ip='100.0.0.1')
def test_create_subnet_gw_of_network_force_on_returns_400(self):
cfg.CONF.set_override('force_gateway_on_subnet', True)
def test_create_subnet_gw_of_network_returns_400(self):
with self.network() as network:
self._create_subnet(self.fmt,
network['network']['id'],
@ -2773,8 +2763,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
webob.exc.HTTPClientError.code,
gateway_ip='10.0.0.0')
def test_create_subnet_gw_bcast_force_on_returns_400(self):
cfg.CONF.set_override('force_gateway_on_subnet', True)
def test_create_subnet_gw_bcast_returns_400(self):
with self.network() as network:
self._create_subnet(self.fmt,
network['network']['id'],
@ -3042,6 +3031,28 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
ipv6_ra_mode=mode,
ipv6_address_mode=mode)
def test_create_subnet_ipv6_out_of_cidr_global(self):
gateway_ip = '2000::1'
cidr = '2001::/64'
with testlib_api.ExpectedException(
webob.exc.HTTPClientError) as ctx_manager:
self._test_create_subnet(
gateway_ip=gateway_ip, cidr=cidr, ip_version=6,
ipv6_ra_mode=constants.DHCPV6_STATEFUL,
ipv6_address_mode=constants.DHCPV6_STATEFUL)
self.assertEqual(ctx_manager.exception.code,
webob.exc.HTTPClientError.code)
def test_create_subnet_ipv6_out_of_cidr_lla(self):
gateway_ip = 'fe80::1'
cidr = '2001::/64'
self._test_create_subnet(
gateway_ip=gateway_ip, cidr=cidr, ip_version=6,
ipv6_ra_mode=constants.IPV6_SLAAC,
ipv6_address_mode=constants.IPV6_SLAAC)
def test_create_subnet_ipv6_attributes_no_dhcp_enabled(self):
gateway_ip = 'fe80::1'
cidr = 'fe80::/80'
@ -3126,7 +3137,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
def test_update_subnet_no_gateway(self):
with self.subnet() as subnet:
data = {'subnet': {'gateway_ip': '11.0.0.1'}}
data = {'subnet': {'gateway_ip': '10.0.0.1'}}
req = self.new_update_request('subnets', data,
subnet['subnet']['id'])
res = self.deserialize(self.fmt, req.get_response(self.api))
@ -3140,7 +3151,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
def test_update_subnet(self):
with self.subnet() as subnet:
data = {'subnet': {'gateway_ip': '11.0.0.1'}}
data = {'subnet': {'gateway_ip': '10.0.0.1'}}
req = self.new_update_request('subnets', data,
subnet['subnet']['id'])
res = self.deserialize(self.fmt, req.get_response(self.api))
@ -3186,8 +3197,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
self.assertEqual(res.status_int,
webob.exc.HTTPClientError.code)
def test_update_subnet_gw_outside_cidr_force_on_returns_400(self):
cfg.CONF.set_override('force_gateway_on_subnet', True)
def test_update_subnet_gw_outside_cidr_returns_400(self):
with self.network() as network:
with self.subnet(network=network) as subnet:
data = {'subnet': {'gateway_ip': '100.0.0.1'}}

View File

@ -943,8 +943,6 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
try_overlapped_cidr('10.0.1.0/24')
# another subnet with overlapped cidr including s1
try_overlapped_cidr('10.0.0.0/16')
# another subnet with overlapped cidr included by s1
try_overlapped_cidr('10.0.1.1/32')
# clean-up
self._router_interface_action('remove',
r['router']['id'],