Fix IPv6 PD with pluggable IPAM

A PD-sepcific check that was present in the non-pluggable IPAM
backend was missing from the pluggable version, causing router
interfaces to be created with a '::1' IP (equal to the gateway on
PD subnets). The resulting command:

ip netns exec <router_namespace> ip -6 addr add ::1/64

would then fail. This patch restores the check to ensure that
'::1' is not used for router interface ports, and introduces a
test to protect against future regressions.

Change-Id: I6a2e7cd60dd42d92b900a57bd8f3ffbc5909908e
Closes-Bug: 1631693
(cherry picked from commit 14ffea4444)
This commit is contained in:
John Davidge 2016-10-10 14:05:03 +01:00
parent 287bb35e16
commit 93828c7e33
2 changed files with 24 additions and 1 deletions

View File

@ -24,6 +24,7 @@ from oslo_utils import excutils
from sqlalchemy import and_
from neutron._i18n import _, _LE, _LW
from neutron.common import constants as n_const
from neutron.common import ipv6_utils
from neutron.db import ipam_backend_mixin
from neutron.db import models_v2
@ -249,7 +250,8 @@ class IpamPluggableBackend(ipam_backend_mixin.IpamBackendMixin):
subnet = self._get_subnet_for_fixed_ip(context, fixed, subnets)
is_auto_addr_subnet = ipv6_utils.is_auto_address_subnet(subnet)
if 'ip_address' in fixed:
if ('ip_address' in fixed and
subnet['cidr'] != n_const.PROVISIONAL_IPV6_PD_PREFIX):
if (is_auto_addr_subnet and device_owner not in
constants.ROUTER_INTERFACE_OWNERS):
msg = (_("IPv6 address %(address)s can not be directly "

View File

@ -338,6 +338,27 @@ class TestDbBasePluginIpam(test_db_base.NeutronDbPluginV2TestCase):
ips)
mocks['subnets'].allocate.assert_called_once_with(mock.ANY)
def test_test_fixed_ips_for_port_pd_gateway(self):
context = mock.Mock()
pluggable_backend = ipam_pluggable_backend.IpamPluggableBackend()
with self.subnet(cidr=n_const.PROVISIONAL_IPV6_PD_PREFIX,
ip_version=6) as subnet:
subnet = subnet['subnet']
fixed_ips = [{'subnet_id': subnet['id'],
'ip_address': '::1'}]
filtered_ips = (pluggable_backend.
_test_fixed_ips_for_port(context,
subnet['network_id'],
fixed_ips,
constants.DEVICE_OWNER_ROUTER_INTF,
[subnet]))
# Assert that ports created on prefix delegation subnets
# will be returned without an ip address. This prevents router
# interfaces being given the ::1 gateway address.
self.assertEqual(1, len(filtered_ips))
self.assertEqual(subnet['id'], filtered_ips[0]['subnet_id'])
self.assertNotIn('ip_address', filtered_ips[0])
@mock.patch('neutron.ipam.driver.Pool')
def test_create_subnet_over_ipam(self, pool_mock):
mocks = self._prepare_mocks_with_pool_mock(pool_mock)