summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-11-26 20:29:35 +0000
committerGerrit Code Review <review@openstack.org>2014-11-26 20:29:36 +0000
commit4e4110b166c49ce913b6226c53e5885407403ddf (patch)
tree03fd0112753881fa9d2e62389aded37f5394c596
parent679246d7280e9fb374f8db0972b21b3653724c42 (diff)
parent63b43376b3818a28af496d3a6f4e6957df9427f2 (diff)
downloadneutron-4e4110b166c49ce913b6226c53e5885407403ddf.tar.gz
Merge "Subnet delete for IPv6 SLAAC should not require prior port disassoc" into stable/juno
-rw-r--r--neutron/db/db_base_plugin_v2.py8
-rw-r--r--neutron/plugins/ml2/plugin.py4
-rw-r--r--neutron/tests/unit/test_db_plugin.py30
3 files changed, 39 insertions, 3 deletions
diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py
index 70827c58af..903332de0a 100644
--- a/neutron/db/db_base_plugin_v2.py
+++ b/neutron/db/db_base_plugin_v2.py
@@ -1276,9 +1276,13 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
filter_by(network_id=subnet['network_id']).
with_lockmode('update'))
- # remove network owned ports
+ # Remove network owned ports, and delete IP allocations
+ # for IPv6 addresses which were automatically generated
+ # via SLAAC
+ is_ipv6_slaac_subnet = ipv6_utils.is_slaac_subnet(subnet)
for a in allocated:
- if a.ports.device_owner in AUTO_DELETE_PORT_OWNERS:
+ if (is_ipv6_slaac_subnet or
+ a.ports.device_owner in AUTO_DELETE_PORT_OWNERS):
NeutronDbPluginV2._delete_ip_allocation(
context, subnet.network_id, id, a.ip_address)
else:
diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py
index d29deda6ce..fe3a6face8 100644
--- a/neutron/plugins/ml2/plugin.py
+++ b/neutron/plugins/ml2/plugin.py
@@ -29,6 +29,7 @@ from neutron.api.rpc.handlers import securitygroups_rpc
from neutron.api.v2 import attributes
from neutron.common import constants as const
from neutron.common import exceptions as exc
+from neutron.common import ipv6_utils
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron.common import utils
@@ -726,7 +727,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
LOG.debug(_("Ports to auto-deallocate: %s"), allocated)
only_auto_del = all(not a.port_id or
a.ports.device_owner in db_base_plugin_v2.
- AUTO_DELETE_PORT_OWNERS
+ AUTO_DELETE_PORT_OWNERS or
+ ipv6_utils.is_slaac_subnet(subnet)
for a in allocated)
if not only_auto_del:
LOG.debug(_("Tenant-owned ports exist"))
diff --git a/neutron/tests/unit/test_db_plugin.py b/neutron/tests/unit/test_db_plugin.py
index 24eab08440..ec624c59fb 100644
--- a/neutron/tests/unit/test_db_plugin.py
+++ b/neutron/tests/unit/test_db_plugin.py
@@ -2641,6 +2641,36 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
self.assertEqual(res.status_int,
webob.exc.HTTPNoContent.code)
+ def test_delete_subnet_ipv6_slaac_port_exists(self):
+ """Test IPv6 SLAAC subnet delete when a port is still using subnet."""
+ res = self._create_network(fmt=self.fmt, name='net',
+ admin_state_up=True)
+ network = self.deserialize(self.fmt, res)
+ # Create an IPv6 SLAAC subnet and a port using that subnet
+ subnet = self._make_subnet(self.fmt, network, gateway='fe80::1',
+ cidr='fe80::/64', ip_version=6,
+ ipv6_ra_mode=constants.IPV6_SLAAC,
+ ipv6_address_mode=constants.IPV6_SLAAC)
+ res = self._create_port(self.fmt, net_id=network['network']['id'])
+ port = self.deserialize(self.fmt, res)
+ self.assertEqual(1, len(port['port']['fixed_ips']))
+
+ # The port should have an address from the subnet
+ req = self.new_show_request('ports', port['port']['id'], self.fmt)
+ res = req.get_response(self.api)
+ sport = self.deserialize(self.fmt, req.get_response(self.api))
+ self.assertEqual(1, len(sport['port']['fixed_ips']))
+
+ # Delete the subnet
+ req = self.new_delete_request('subnets', subnet['subnet']['id'])
+ res = req.get_response(self.api)
+ self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
+ # The port should no longer have an address from the deleted subnet
+ req = self.new_show_request('ports', port['port']['id'], self.fmt)
+ res = req.get_response(self.api)
+ sport = self.deserialize(self.fmt, req.get_response(self.api))
+ self.assertEqual(0, len(sport['port']['fixed_ips']))
+
def test_delete_network(self):
gateway_ip = '10.0.0.1'
cidr = '10.0.0.0/24'