Merge "Re-submit "ML2 plugin should not delete ports on subnet deletion""
This commit is contained in:
commit
6eb4c8a91b
@ -567,10 +567,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
|
|
||||||
def delete_subnet(self, context, id):
|
def delete_subnet(self, context, id):
|
||||||
# REVISIT(rkukura) The super(Ml2Plugin, self).delete_subnet()
|
# REVISIT(rkukura) The super(Ml2Plugin, self).delete_subnet()
|
||||||
# function is not used because it auto-deletes ports from the
|
# function is not used because it deallocates the subnet's addresses
|
||||||
# DB without invoking the derived class's delete_port(),
|
# from ports in the DB without invoking the derived class's
|
||||||
# preventing mechanism drivers from being called. This
|
# update_port(), preventing mechanism drivers from being called.
|
||||||
# approach should be revisited when the API layer is reworked
|
# This approach should be revisited when the API layer is reworked
|
||||||
# during icehouse.
|
# during icehouse.
|
||||||
|
|
||||||
LOG.debug(_("Deleting subnet %s"), id)
|
LOG.debug(_("Deleting subnet %s"), id)
|
||||||
@ -578,13 +578,13 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
while True:
|
while True:
|
||||||
with session.begin(subtransactions=True):
|
with session.begin(subtransactions=True):
|
||||||
subnet = self.get_subnet(context, id)
|
subnet = self.get_subnet(context, id)
|
||||||
# Get ports to auto-delete.
|
# Get ports to auto-deallocate
|
||||||
allocated = (session.query(models_v2.IPAllocation).
|
allocated = (session.query(models_v2.IPAllocation).
|
||||||
filter_by(subnet_id=id).
|
filter_by(subnet_id=id).
|
||||||
join(models_v2.Port).
|
join(models_v2.Port).
|
||||||
filter_by(network_id=subnet['network_id']).
|
filter_by(network_id=subnet['network_id']).
|
||||||
with_lockmode('update').all())
|
with_lockmode('update').all())
|
||||||
LOG.debug(_("Ports to auto-delete: %s"), allocated)
|
LOG.debug(_("Ports to auto-deallocate: %s"), allocated)
|
||||||
only_auto_del = all(not a.port_id or
|
only_auto_del = all(not a.port_id or
|
||||||
a.ports.device_owner in db_base_plugin_v2.
|
a.ports.device_owner in db_base_plugin_v2.
|
||||||
AUTO_DELETE_PORT_OWNERS
|
AUTO_DELETE_PORT_OWNERS
|
||||||
@ -607,12 +607,21 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
break
|
break
|
||||||
|
|
||||||
for a in allocated:
|
for a in allocated:
|
||||||
|
if a.port_id:
|
||||||
|
# calling update_port() for each allocation to remove the
|
||||||
|
# IP from the port and call the MechanismDrivers
|
||||||
|
data = {'port':
|
||||||
|
{'fixed_ips': [{'subnet_id': ip.subnet_id,
|
||||||
|
'ip_address': ip.ip_address}
|
||||||
|
for ip in a.ports.fixed_ips
|
||||||
|
if ip.subnet_id != id]}}
|
||||||
try:
|
try:
|
||||||
self.delete_port(context, a.port_id)
|
self.update_port(context, a.port_id, data)
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
LOG.exception(_("Exception auto-deleting port %s"),
|
LOG.exception(_("Exception deleting fixed_ip from "
|
||||||
a.port_id)
|
"port %s"), a.port_id)
|
||||||
|
session.delete(a)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.mechanism_manager.delete_subnet_postcommit(mech_context)
|
self.mechanism_manager.delete_subnet_postcommit(mech_context)
|
||||||
|
@ -597,7 +597,11 @@ class TestN1kvNetworks(test_plugin.TestNetworksV2,
|
|||||||
class TestN1kvSubnets(test_plugin.TestSubnetsV2,
|
class TestN1kvSubnets(test_plugin.TestSubnetsV2,
|
||||||
N1kvPluginTestCase):
|
N1kvPluginTestCase):
|
||||||
|
|
||||||
pass
|
def setUp(self):
|
||||||
|
super(TestN1kvSubnets, self).setUp()
|
||||||
|
|
||||||
|
# Create some of the database entries that we require.
|
||||||
|
self._make_test_policy_profile(name='dhcp_pp')
|
||||||
|
|
||||||
|
|
||||||
class TestN1kvL3Test(test_l3_plugin.L3NatExtensionTestCase):
|
class TestN1kvL3Test(test_l3_plugin.L3NatExtensionTestCase):
|
||||||
|
@ -97,6 +97,11 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2,
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TestMl2SubnetsV2(test_plugin.TestSubnetsV2,
|
||||||
|
Ml2PluginV2TestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
||||||
|
|
||||||
def test_update_port_status_build(self):
|
def test_update_port_status_build(self):
|
||||||
|
@ -2460,6 +2460,39 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase):
|
|||||||
res = req.get_response(self.api)
|
res = req.get_response(self.api)
|
||||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||||
|
|
||||||
|
def test_delete_subnet_dhcp_port_associated_with_other_subnets(self):
|
||||||
|
res = self._create_network(fmt=self.fmt, name='net',
|
||||||
|
admin_state_up=True)
|
||||||
|
network = self.deserialize(self.fmt, res)
|
||||||
|
subnet1 = self._make_subnet(self.fmt, network, '10.0.0.1',
|
||||||
|
'10.0.0.0/24', ip_version=4)
|
||||||
|
subnet2 = self._make_subnet(self.fmt, network, '10.0.1.1',
|
||||||
|
'10.0.1.0/24', ip_version=4)
|
||||||
|
res = self._create_port(self.fmt,
|
||||||
|
network['network']['id'],
|
||||||
|
device_owner=constants.DEVICE_OWNER_DHCP,
|
||||||
|
fixed_ips=[
|
||||||
|
{'subnet_id': subnet1['subnet']['id']},
|
||||||
|
{'subnet_id': subnet2['subnet']['id']}
|
||||||
|
])
|
||||||
|
port = self.deserialize(self.fmt, res)
|
||||||
|
expected_subnets = [subnet1['subnet']['id'], subnet2['subnet']['id']]
|
||||||
|
self.assertEqual(expected_subnets,
|
||||||
|
[s['subnet_id'] for s in port['port']['fixed_ips']])
|
||||||
|
req = self.new_delete_request('subnets', subnet1['subnet']['id'])
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
self.assertEqual(res.status_int, 204)
|
||||||
|
port = self._show('ports', port['port']['id'])
|
||||||
|
|
||||||
|
expected_subnets = [subnet2['subnet']['id']]
|
||||||
|
self.assertEqual(expected_subnets,
|
||||||
|
[s['subnet_id'] for s in port['port']['fixed_ips']])
|
||||||
|
req = self.new_delete_request('subnets', subnet2['subnet']['id'])
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
self.assertEqual(res.status_int, 204)
|
||||||
|
port = self._show('ports', port['port']['id'])
|
||||||
|
self.assertFalse(port['port']['fixed_ips'])
|
||||||
|
|
||||||
def test_delete_subnet_port_exists_owned_by_other(self):
|
def test_delete_subnet_port_exists_owned_by_other(self):
|
||||||
with self.subnet() as subnet:
|
with self.subnet() as subnet:
|
||||||
with self.port(subnet=subnet):
|
with self.port(subnet=subnet):
|
||||||
|
Loading…
Reference in New Issue
Block a user