Ensure to remove auto delete ports from OFC in NEC plugin

When deleting a network, dhcp ports are removed automatically
in db_plugin. This causes a failure network deletion since the
corresponding port exists on OFC and the network on OFC cannot
be deleted unless a subnet on the network is deleted explicitly.
This commit gets auto-delete ports and delete the corresponding
ports on the controller before deleting the network.

Fixes bug #1190163

Change-Id: Ifffaa1a28b5fac0b0a98036a926550255cc25c9d
This commit is contained in:
Akihiro MOTOKI 2013-06-12 17:18:55 +09:00
parent 08561f35ac
commit da6816c6c7
2 changed files with 50 additions and 0 deletions

View File

@ -24,6 +24,7 @@ from quantum.common import rpc as q_rpc
from quantum.common import topics from quantum.common import topics
from quantum.db import agents_db from quantum.db import agents_db
from quantum.db import agentschedulers_db from quantum.db import agentschedulers_db
from quantum.db import db_base_plugin_v2
from quantum.db import dhcp_rpc_base from quantum.db import dhcp_rpc_base
from quantum.db import extraroute_db from quantum.db import extraroute_db
from quantum.db import l3_gwmode_db from quantum.db import l3_gwmode_db
@ -317,6 +318,15 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base,
net = super(NECPluginV2, self).get_network(context, id) net = super(NECPluginV2, self).get_network(context, id)
tenant_id = net['tenant_id'] tenant_id = net['tenant_id']
# Make sure auto-delete ports on OFC are deleted.
filter = {'network_id': [id],
'device_owner': db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS}
auto_delete_ports = self.get_ports(context, filters=filter)
for port in auto_delete_ports:
LOG.debug(_('delete_network(): deleting auto-delete port'
' from OFC: %s'), port)
self.deactivate_port(context, port)
# get packet_filters associated with the network # get packet_filters associated with the network
if self.packet_filter_enabled: if self.packet_filter_enabled:
filters = dict(network_id=[id]) filters = dict(network_id=[id])

View File

@ -288,6 +288,13 @@ class TestNecPluginOfcManager(NecPluginV2TestCase):
super(TestNecPluginOfcManager, self).setUp() super(TestNecPluginOfcManager, self).setUp()
self.ofc = self.plugin.ofc self.ofc = self.plugin.ofc
def _create_resource(self, resource, data):
collection = resource + 's'
data = {resource: data}
req = self.new_create_request(collection, data)
res = self.deserialize(self.fmt, req.get_response(self.api))
return res[resource]
def _update_resource(self, resource, id, data): def _update_resource(self, resource, id, data):
collection = resource + 's' collection = resource + 's'
data = {resource: data} data = {resource: data}
@ -496,6 +503,39 @@ class TestNecPluginOfcManager(NecPluginV2TestCase):
] ]
self.ofc.assert_has_calls(expected) self.ofc.assert_has_calls(expected)
def test_delete_network_with_dhcp_port(self):
self.ofc.exists_ofc_tenant.return_value = False
self.ofc.exists_ofc_port.side_effect = [False, True]
ctx = mock.ANY
with self.network() as network:
with self.subnet(network=network):
net = network['network']
p = self._create_resource('port',
{'network_id': net['id'],
'tenant_id': net['tenant_id'],
'device_owner': 'network:dhcp',
'device_id': 'dhcp-port1'})
# Make sure that the port is created on OFC.
portinfo = {'id': p['id'], 'port_no': 123}
self._rpcapi_update_ports(added=[portinfo])
# In a case of dhcp port, the port is deleted automatically
# when delete_network.
expected = [
mock.call.exists_ofc_tenant(ctx, self._tenant_id),
mock.call.create_ofc_tenant(ctx, self._tenant_id),
mock.call.create_ofc_network(ctx, self._tenant_id,
net['id'], net['name']),
mock.call.exists_ofc_port(ctx, p['id']),
mock.call.create_ofc_port(ctx, p['id'], mock.ANY),
mock.call.exists_ofc_port(ctx, p['id']),
mock.call.delete_ofc_port(ctx, p['id'], mock.ANY),
mock.call.delete_ofc_network(ctx, net['id'], mock.ANY),
mock.call.delete_ofc_tenant(ctx, self._tenant_id)
]
self.ofc.assert_has_calls(expected)
def test_update_port(self): def test_update_port(self):
self._test_update_port_with_admin_state(resource='port') self._test_update_port_with_admin_state(resource='port')