Disable PUT for IPv6 subnet attributes
In Juno we are not ready for allowing the IPv6 attributes on a subnet to be updated after the subnet is created, because: - The implementation for supporting updates is incomplete. - Perceived lack of usefulness, no good use cases known yet. - Allowing updates causes more complexity in the code. - Have not tested that radvd, dhcp, etc. behave OK after update. Therefore, for now, we set 'allow_put' to False for the two IPv6 attributes, ipv6_ra_mode and ipv6_address_mode. This prevents the modes from being updated via the PUT:subnets API. Closes-bug: #1378952 Change-Id: Id6ce894d223c91421b62f82d266cfc15fa63ed0e
This commit is contained in:
parent
2bdb52d98f
commit
88609cd34e
@ -729,11 +729,11 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'default': True,
|
||||
'convert_to': convert_to_boolean,
|
||||
'is_visible': True},
|
||||
'ipv6_ra_mode': {'allow_post': True, 'allow_put': True,
|
||||
'ipv6_ra_mode': {'allow_post': True, 'allow_put': False,
|
||||
'default': ATTR_NOT_SPECIFIED,
|
||||
'validate': {'type:values': constants.IPV6_MODES},
|
||||
'is_visible': True},
|
||||
'ipv6_address_mode': {'allow_post': True, 'allow_put': True,
|
||||
'ipv6_address_mode': {'allow_post': True, 'allow_put': False,
|
||||
'default': ATTR_NOT_SPECIFIED,
|
||||
'validate': {'type:values':
|
||||
constants.IPV6_MODES},
|
||||
|
@ -740,24 +740,17 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
||||
raise n_exc.InvalidSharedSetting(network=original.name)
|
||||
|
||||
def _validate_ipv6_attributes(self, subnet, cur_subnet):
|
||||
if cur_subnet:
|
||||
self._validate_ipv6_update_dhcp(subnet, cur_subnet)
|
||||
return
|
||||
ra_mode_set = attributes.is_attr_set(subnet.get('ipv6_ra_mode'))
|
||||
address_mode_set = attributes.is_attr_set(
|
||||
subnet.get('ipv6_address_mode'))
|
||||
if cur_subnet:
|
||||
ra_mode = (subnet['ipv6_ra_mode'] if ra_mode_set
|
||||
else cur_subnet['ipv6_ra_mode'])
|
||||
addr_mode = (subnet['ipv6_address_mode'] if address_mode_set
|
||||
else cur_subnet['ipv6_address_mode'])
|
||||
if ra_mode_set or address_mode_set:
|
||||
# Check that updated subnet ipv6 attributes do not conflict
|
||||
self._validate_ipv6_combination(ra_mode, addr_mode)
|
||||
self._validate_ipv6_update_dhcp(subnet, cur_subnet)
|
||||
else:
|
||||
self._validate_ipv6_dhcp(ra_mode_set, address_mode_set,
|
||||
subnet['enable_dhcp'])
|
||||
if ra_mode_set and address_mode_set:
|
||||
self._validate_ipv6_combination(subnet['ipv6_ra_mode'],
|
||||
subnet['ipv6_address_mode'])
|
||||
self._validate_ipv6_dhcp(ra_mode_set, address_mode_set,
|
||||
subnet['enable_dhcp'])
|
||||
if ra_mode_set and address_mode_set:
|
||||
self._validate_ipv6_combination(subnet['ipv6_ra_mode'],
|
||||
subnet['ipv6_address_mode'])
|
||||
if address_mode_set:
|
||||
self._validate_eui64_applicable(subnet)
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import contextlib
|
||||
import copy
|
||||
import itertools
|
||||
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
@ -3038,15 +3039,48 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
res = subnet_req.get_response(self.api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPClientError.code)
|
||||
|
||||
def test_create_subnet_ipv6_attributes(self):
|
||||
gateway_ip = 'fe80::1'
|
||||
cidr = 'fe80::/64'
|
||||
def _test_validate_subnet_ipv6_modes(self, cur_subnet=None,
|
||||
expect_success=True, **modes):
|
||||
plugin = manager.NeutronManager.get_plugin()
|
||||
ctx = context.get_admin_context(load_admin_roles=False)
|
||||
new_subnet = {'ip_version': 6,
|
||||
'cidr': 'fe80::/64',
|
||||
'enable_dhcp': True}
|
||||
for mode, value in modes.items():
|
||||
new_subnet[mode] = value
|
||||
if expect_success:
|
||||
plugin._validate_subnet(ctx, new_subnet, cur_subnet)
|
||||
else:
|
||||
self.assertRaises(n_exc.InvalidInput, plugin._validate_subnet,
|
||||
ctx, new_subnet, cur_subnet)
|
||||
|
||||
for mode in constants.IPV6_MODES:
|
||||
self._test_create_subnet(gateway_ip=gateway_ip,
|
||||
cidr=cidr, ip_version=6,
|
||||
ipv6_ra_mode=mode,
|
||||
ipv6_address_mode=mode)
|
||||
def test_create_subnet_ipv6_ra_modes(self):
|
||||
# Test all RA modes with no address mode specified
|
||||
for ra_mode in constants.IPV6_MODES:
|
||||
self._test_validate_subnet_ipv6_modes(
|
||||
ipv6_ra_mode=ra_mode)
|
||||
|
||||
def test_create_subnet_ipv6_addr_modes(self):
|
||||
# Test all address modes with no RA mode specified
|
||||
for addr_mode in constants.IPV6_MODES:
|
||||
self._test_validate_subnet_ipv6_modes(
|
||||
ipv6_address_mode=addr_mode)
|
||||
|
||||
def test_create_subnet_ipv6_same_ra_and_addr_modes(self):
|
||||
# Test all ipv6 modes with ra_mode==addr_mode
|
||||
for ipv6_mode in constants.IPV6_MODES:
|
||||
self._test_validate_subnet_ipv6_modes(
|
||||
ipv6_ra_mode=ipv6_mode,
|
||||
ipv6_address_mode=ipv6_mode)
|
||||
|
||||
def test_create_subnet_ipv6_different_ra_and_addr_modes(self):
|
||||
# Test all ipv6 modes with ra_mode!=addr_mode
|
||||
for ra_mode, addr_mode in itertools.permutations(
|
||||
constants.IPV6_MODES, 2):
|
||||
self._test_validate_subnet_ipv6_modes(
|
||||
expect_success=not (ra_mode and addr_mode),
|
||||
ipv6_ra_mode=ra_mode,
|
||||
ipv6_address_mode=addr_mode)
|
||||
|
||||
def test_create_subnet_ipv6_out_of_cidr_global(self):
|
||||
gateway_ip = '2000::1'
|
||||
@ -3108,31 +3142,6 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
self.assertEqual(ctx_manager.exception.code,
|
||||
webob.exc.HTTPClientError.code)
|
||||
|
||||
def test_create_subnet_invalid_ipv6_combination(self):
|
||||
gateway_ip = 'fe80::1'
|
||||
cidr = 'fe80::/80'
|
||||
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='stateful',
|
||||
ipv6_address_mode='stateless')
|
||||
self.assertEqual(ctx_manager.exception.code,
|
||||
webob.exc.HTTPClientError.code)
|
||||
|
||||
def test_create_subnet_ipv6_single_attribute_set(self):
|
||||
gateway_ip = 'fe80::1'
|
||||
cidr = 'fe80::/64'
|
||||
for mode in constants.IPV6_MODES:
|
||||
self._test_create_subnet(gateway_ip=gateway_ip,
|
||||
cidr=cidr, ip_version=6,
|
||||
ipv6_ra_mode=None,
|
||||
ipv6_address_mode=mode)
|
||||
self._test_create_subnet(gateway_ip=gateway_ip,
|
||||
cidr=cidr, ip_version=6,
|
||||
ipv6_ra_mode=mode,
|
||||
ipv6_address_mode=None)
|
||||
|
||||
def test_create_subnet_ipv6_ra_mode_ip_version_4(self):
|
||||
cidr = '10.0.2.0/24'
|
||||
with testlib_api.ExpectedException(
|
||||
@ -3312,7 +3321,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
self.assertEqual(res.status_int,
|
||||
webob.exc.HTTPConflict.code)
|
||||
|
||||
def test_update_subnet_ipv6_attributes(self):
|
||||
def test_update_subnet_ipv6_attributes_fails(self):
|
||||
with self.subnet(ip_version=6, cidr='fe80::/64',
|
||||
ipv6_ra_mode=constants.IPV6_SLAAC,
|
||||
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
|
||||
@ -3320,16 +3329,13 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
'ipv6_address_mode': constants.DHCPV6_STATEFUL}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
subnet['subnet']['id'])
|
||||
res = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self.assertEqual(res['subnet']['ipv6_ra_mode'],
|
||||
data['subnet']['ipv6_ra_mode'])
|
||||
self.assertEqual(res['subnet']['ipv6_address_mode'],
|
||||
data['subnet']['ipv6_address_mode'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(res.status_int,
|
||||
webob.exc.HTTPClientError.code)
|
||||
|
||||
def test_update_subnet_ipv6_inconsistent_ra_attribute(self):
|
||||
def test_update_subnet_ipv6_ra_mode_fails(self):
|
||||
with self.subnet(ip_version=6, cidr='fe80::/64',
|
||||
ipv6_ra_mode=constants.IPV6_SLAAC,
|
||||
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
|
||||
ipv6_ra_mode=constants.IPV6_SLAAC) as subnet:
|
||||
data = {'subnet': {'ipv6_ra_mode': constants.DHCPV6_STATEFUL}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
subnet['subnet']['id'])
|
||||
@ -3337,9 +3343,8 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
self.assertEqual(res.status_int,
|
||||
webob.exc.HTTPClientError.code)
|
||||
|
||||
def test_update_subnet_ipv6_inconsistent_address_attribute(self):
|
||||
def test_update_subnet_ipv6_ra_mode_fails(self):
|
||||
with self.subnet(ip_version=6, cidr='fe80::/64',
|
||||
ipv6_ra_mode=constants.IPV6_SLAAC,
|
||||
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
|
||||
data = {'subnet': {'ipv6_address_mode': constants.DHCPV6_STATEFUL}}
|
||||
req = self.new_update_request('subnets', data,
|
||||
@ -3348,7 +3353,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
||||
self.assertEqual(res.status_int,
|
||||
webob.exc.HTTPClientError.code)
|
||||
|
||||
def test_update_subnet_ipv6_inconsistent_enable_dhcp(self):
|
||||
def test_update_subnet_ipv6_cannot_disable_dhcp(self):
|
||||
with self.subnet(ip_version=6, cidr='fe80::/64',
|
||||
ipv6_ra_mode=constants.IPV6_SLAAC,
|
||||
ipv6_address_mode=constants.IPV6_SLAAC) as subnet:
|
||||
|
Loading…
Reference in New Issue
Block a user