Revert "Fix DetachedInstanceError on subnet delete"
This reverts commit b9242c348c
.
The patch made us loop indefinitely on network delete request.
Change-Id: I67eed7c0cb9ca738cea1e827676b4f8f350e5aef
Closes-Bug: #1680912
This commit is contained in:
parent
7ec87f4947
commit
a919f2b354
|
@ -1068,11 +1068,11 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
session = context.session
|
session = context.session
|
||||||
deallocated = set()
|
deallocated = set()
|
||||||
while True:
|
while True:
|
||||||
|
# NOTE(kevinbenton): this loop keeps db objects in scope
|
||||||
|
# so we must expire them or risk stale reads.
|
||||||
|
# see bug/1623990
|
||||||
|
session.expire_all()
|
||||||
with session.begin(subtransactions=True):
|
with session.begin(subtransactions=True):
|
||||||
# NOTE(kevinbenton): this loop keeps db objects in scope
|
|
||||||
# so we must expire them or risk stale reads.
|
|
||||||
# see bug/1623990
|
|
||||||
session.expire_all()
|
|
||||||
record = self._get_subnet(context, id)
|
record = self._get_subnet(context, id)
|
||||||
subnet = self._make_subnet_dict(record, None, context=context)
|
subnet = self._make_subnet_dict(record, None, context=context)
|
||||||
qry_allocated = (session.query(models_v2.IPAllocation).
|
qry_allocated = (session.query(models_v2.IPAllocation).
|
||||||
|
@ -1089,7 +1089,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
qry_allocated = (
|
qry_allocated = (
|
||||||
qry_allocated.filter(models_v2.Port.device_owner.
|
qry_allocated.filter(models_v2.Port.device_owner.
|
||||||
in_(db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS)))
|
in_(db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS)))
|
||||||
allocated = set(ipal.port_id for ipal in qry_allocated)
|
allocated = set(qry_allocated.all())
|
||||||
LOG.debug("Ports to auto-deallocate: %s", allocated)
|
LOG.debug("Ports to auto-deallocate: %s", allocated)
|
||||||
if not is_auto_addr_subnet:
|
if not is_auto_addr_subnet:
|
||||||
user_alloc = self._subnet_get_user_allocation(
|
user_alloc = self._subnet_get_user_allocation(
|
||||||
|
@ -1152,20 +1152,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
LOG.debug("Committing transaction")
|
LOG.debug("Committing transaction")
|
||||||
break
|
break
|
||||||
|
|
||||||
for port_id in to_deallocate:
|
for a in to_deallocate:
|
||||||
try:
|
if a.port:
|
||||||
port = self.get_port(context, port_id)
|
|
||||||
except exc.PortNotFound:
|
|
||||||
LOG.debug("Port %s deleted concurrently", port_id)
|
|
||||||
deallocated.add(port_id)
|
|
||||||
continue
|
|
||||||
if port:
|
|
||||||
# calling update_port() for each allocation to remove the
|
# calling update_port() for each allocation to remove the
|
||||||
# IP from the port and call the MechanismDrivers
|
# IP from the port and call the MechanismDrivers
|
||||||
fixed_ips = [{'subnet_id': ip['subnet_id'],
|
fixed_ips = [{'subnet_id': ip.subnet_id,
|
||||||
'ip_address': ip['ip_address']}
|
'ip_address': ip.ip_address}
|
||||||
for ip in port['fixed_ips']
|
for ip in a.port.fixed_ips
|
||||||
if ip['subnet_id'] != id]
|
if ip.subnet_id != id]
|
||||||
# By default auto-addressed ips are not removed from port
|
# By default auto-addressed ips are not removed from port
|
||||||
# on port update, so mark subnet with 'delete_subnet' flag
|
# on port update, so mark subnet with 'delete_subnet' flag
|
||||||
# to force ip deallocation on port update.
|
# to force ip deallocation on port update.
|
||||||
|
@ -1174,8 +1168,11 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
'delete_subnet': True})
|
'delete_subnet': True})
|
||||||
data = {attributes.PORT: {'fixed_ips': fixed_ips}}
|
data = {attributes.PORT: {'fixed_ips': fixed_ips}}
|
||||||
try:
|
try:
|
||||||
|
# NOTE Don't inline port_id; needed for PortNotFound.
|
||||||
|
port_id = a.port_id
|
||||||
self.update_port(context, port_id, data)
|
self.update_port(context, port_id, data)
|
||||||
except exc.PortNotFound:
|
except exc.PortNotFound:
|
||||||
|
# NOTE Attempting to access a.port_id here is an error.
|
||||||
LOG.debug("Port %s deleted concurrently", port_id)
|
LOG.debug("Port %s deleted concurrently", port_id)
|
||||||
except exc.SubnetNotFound:
|
except exc.SubnetNotFound:
|
||||||
# NOTE we hit here if another subnet was concurrently
|
# NOTE we hit here if another subnet was concurrently
|
||||||
|
@ -1188,7 +1185,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
utils.attach_exc_details(
|
utils.attach_exc_details(
|
||||||
e, _LE("Exception deleting fixed_ip from "
|
e, _LE("Exception deleting fixed_ip from "
|
||||||
"port %s"), port_id)
|
"port %s"), port_id)
|
||||||
deallocated.add(port_id)
|
deallocated.add(a)
|
||||||
|
|
||||||
kwargs = {'context': context, 'subnet': subnet}
|
kwargs = {'context': context, 'subnet': subnet}
|
||||||
registry.notify(resources.SUBNET, events.AFTER_DELETE, self, **kwargs)
|
registry.notify(resources.SUBNET, events.AFTER_DELETE, self, **kwargs)
|
||||||
|
|
|
@ -474,32 +474,6 @@ class TestMl2SubnetsV2(test_plugin.TestSubnetsV2,
|
||||||
kwargs = after_create.mock_calls[0][2]
|
kwargs = after_create.mock_calls[0][2]
|
||||||
self.assertEqual(s['subnet']['id'], kwargs['subnet']['id'])
|
self.assertEqual(s['subnet']['id'], kwargs['subnet']['id'])
|
||||||
|
|
||||||
def test_subnet_delete_no_DetachedInstanceError_for_port_update(self):
|
|
||||||
mock_check_subnet_not_used = mock.patch.object(
|
|
||||||
base_plugin, '_check_subnet_not_used').start()
|
|
||||||
with self.network() as n:
|
|
||||||
with self.subnet(network=n, cidr='1.1.1.0/24') as s1,\
|
|
||||||
self.subnet(network=n, cidr='1.1.2.0/24') as s2:
|
|
||||||
fixed_ips = [{'subnet_id': s1['subnet']['id']},
|
|
||||||
{'subnet_id': s2['subnet']['id']}]
|
|
||||||
with self.port(subnet=s1, fixed_ips=fixed_ips,
|
|
||||||
device_owner=constants.DEVICE_OWNER_DHCP) as p:
|
|
||||||
|
|
||||||
def subnet_not_used(ctx, subnet_id):
|
|
||||||
# Make the session invalid after the query.
|
|
||||||
ctx.session.expunge_all()
|
|
||||||
mock_check_subnet_not_used.side_effect = None
|
|
||||||
mock_check_subnet_not_used.side_effect = subnet_not_used
|
|
||||||
req = self.new_delete_request('subnets',
|
|
||||||
s1['subnet']['id'])
|
|
||||||
res = req.get_response(self.api)
|
|
||||||
self.assertEqual(204, res.status_int)
|
|
||||||
# ensure port only has 1 IP on s2
|
|
||||||
port = self._show('ports', p['port']['id'])['port']
|
|
||||||
self.assertEqual(1, len(port['fixed_ips']))
|
|
||||||
self.assertEqual(s2['subnet']['id'],
|
|
||||||
port['fixed_ips'][0]['subnet_id'])
|
|
||||||
|
|
||||||
def test_port_update_subnetnotfound(self):
|
def test_port_update_subnetnotfound(self):
|
||||||
with self.network() as n:
|
with self.network() as n:
|
||||||
with self.subnet(network=n, cidr='1.1.1.0/24') as s1,\
|
with self.subnet(network=n, cidr='1.1.1.0/24') as s1,\
|
||||||
|
|
Loading…
Reference in New Issue