summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Riedemann <mriedem@us.ibm.com>2016-07-12 13:17:34 -0400
committerMatt Riedemann <mriedem@us.ibm.com>2016-07-12 19:00:32 -0400
commit92a388a1e34559b2ce69d31fdef996ff029495a6 (patch)
tree4bc3f9350b806d0763cd5c3236c5d3c35d36463f
parentae9c58792c7a34f129794fa3f1928199bb859b70 (diff)
downloadnova-92a388a1e34559b2ce69d31fdef996ff029495a6.tar.gz
neutron: delete VIFs when deallocating networking
In e2eb6659a426bae05a54b93ebf31ff3247125258 we started creating VirtualInterface objects for instances/ports when allocating networking in the neutronv2 API code. This is used to support virtual device tagging. We need to delete the VIFs when deallocating the networking for the instance though otherwise we can hit unique constraint failures when trying to re-use an existing port from one instance to another since the VIF has a unique constraint on the address which is the port's MAC and uuid when using neutron. Change-Id: I2254bad0df3ccc00cd5c9438fa2684e705442e2d Closes-Bug: #1602357
-rw-r--r--nova/network/neutronv2/api.py13
-rw-r--r--nova/tests/unit/network/test_neutronv2.py11
2 files changed, 23 insertions, 1 deletions
diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py
index 4acc275804..cc211e3ca1 100644
--- a/nova/network/neutronv2/api.py
+++ b/nova/network/neutronv2/api.py
@@ -1033,6 +1033,10 @@ class API(base_api.NetworkAPI):
# Delete the rest of the ports
self._delete_ports(neutron, instance, ports, raise_if_fail=True)
+ # deallocate vifs (mac addresses)
+ objects.VirtualInterface.delete_by_instance_uuid(
+ context, instance.uuid)
+
# NOTE(arosen): This clears out the network_cache only if the instance
# hasn't already been deleted. This is needed when an instance fails to
# launch and is rescheduled onto another compute node. If the instance
@@ -1065,6 +1069,15 @@ class API(base_api.NetworkAPI):
else:
self._delete_ports(neutron, instance, [port_id],
raise_if_fail=True)
+
+ # Delete the VirtualInterface for the given port_id.
+ vif = objects.VirtualInterface.get_by_uuid(context, port_id)
+ if vif:
+ vif.destroy()
+ else:
+ LOG.debug('VirtualInterface not found for port: %s',
+ port_id, instance=instance)
+
return self.get_instance_nw_info(context, instance)
def list_ports(self, context, **search_opts):
diff --git a/nova/tests/unit/network/test_neutronv2.py b/nova/tests/unit/network/test_neutronv2.py
index 287626f899..82b6a61e33 100644
--- a/nova/tests/unit/network/test_neutronv2.py
+++ b/nova/tests/unit/network/test_neutronv2.py
@@ -3737,7 +3737,9 @@ class TestNeutronv2WithMock(test.TestCase):
@mock.patch('nova.network.neutronv2.api.API._unbind_ports')
@mock.patch('nova.network.neutronv2.api.API._get_preexisting_port_ids')
@mock.patch('nova.network.neutronv2.api.get_client')
- def test_preexisting_deallocate_for_instance(self, mock_ntrn,
+ @mock.patch.object(objects.VirtualInterface, 'delete_by_instance_uuid')
+ def test_preexisting_deallocate_for_instance(self, mock_delete_vifs,
+ mock_ntrn,
mock_gppids,
mock_unbind,
mock_deletep,
@@ -3772,12 +3774,15 @@ class TestNeutronv2WithMock(test.TestCase):
mock_inst,
set([uuids.portid_2]),
raise_if_fail=True)
+ mock_delete_vifs.assert_called_once_with(mock.sentinel.ctx, 'inst-1')
@mock.patch('nova.network.neutronv2.api.API.get_instance_nw_info')
@mock.patch('nova.network.neutronv2.api.API._unbind_ports')
@mock.patch('nova.network.neutronv2.api.compute_utils')
@mock.patch('nova.network.neutronv2.api.get_client')
+ @mock.patch.object(objects.VirtualInterface, 'get_by_uuid')
def test_preexisting_deallocate_port_for_instance(self,
+ mock_get_vif_by_uuid,
mock_ntrn,
mock_comp_utils,
mock_unbind,
@@ -3791,10 +3796,14 @@ class TestNeutronv2WithMock(test.TestCase):
uuid='inst-1')
mock_client = mock.Mock()
mock_ntrn.return_value = mock_client
+ mock_vif = mock.MagicMock(spec=objects.VirtualInterface)
+ mock_get_vif_by_uuid.return_value = mock_vif
self.api.deallocate_port_for_instance(mock.sentinel.ctx,
mock_inst, '2')
mock_unbind.assert_called_once_with(mock.sentinel.ctx, ['2'],
mock_client)
+ mock_get_vif_by_uuid.assert_called_once_with(mock.sentinel.ctx, '2')
+ mock_vif.destroy.assert_called_once_with()
@mock.patch('nova.network.neutronv2.api.API.'
'_check_external_network_attach')