From 4f262692cef46f2a7f78f3491c31bd5bf245de00 Mon Sep 17 00:00:00 2001 From: Aaron Rosen Date: Mon, 3 Mar 2014 22:55:35 -0800 Subject: [PATCH] network_info cache should be cleared before being rescheduled If an instance fails to boot due to a non-networking error the instance then gets rescheduled and launched on another compute node. In these cases deallocate_for_instance() is called which deletes the network ports allocated though the info_cache for the instance is never cleared. This patch adds a call to update_instance_cache_with_nw_info() which causes the cache to get cleared out. Note: the cache is only cleared if the instance hasn't been marked for deletion. This is due to how instance_info_cache_update() is implemented. Change-Id: If967884c9a6276f5949a7a04b597cedcce12ba09 Closes-bug: #1285158 (cherry picked from commit 3538a9cd06e1e46ec5698edf4018c8d3075b619b) --- nova/network/neutronv2/api.py | 7 +++++++ nova/tests/network/test_neutronv2.py | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index a6e534452124..86d3add8910b 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -422,6 +422,13 @@ class API(base.Base): LOG.exception(_("Failed to delete neutron port %s"), port) + # 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 + # has already been deleted this call does nothing. + update_instance_info_cache(self, context, instance, + network_model.NetworkInfo([])) + def allocate_port_for_instance(self, context, instance, port_id, network_id=None, requested_ip=None, conductor_api=None): diff --git a/nova/tests/network/test_neutronv2.py b/nova/tests/network/test_neutronv2.py index 37e5ebe8560b..e0494ce3c4f6 100644 --- a/nova/tests/network/test_neutronv2.py +++ b/nova/tests/network/test_neutronv2.py @@ -876,6 +876,7 @@ class TestNeutronv2(TestNeutronv2Base): self.instance, requested_networks=requested_networks) def _deallocate_for_instance(self, number): + api = neutronapi.API() port_data = number == 1 and self.port_data1 or self.port_data2 self.moxed_client.list_ports( device_id=self.instance['uuid']).AndReturn( @@ -883,6 +884,10 @@ class TestNeutronv2(TestNeutronv2Base): for port in reversed(port_data): self.moxed_client.delete_port(port['id']) + self.mox.StubOutWithMock(api.db, 'instance_info_cache_update') + api.db.instance_info_cache_update(self.context, + self.instance['uuid'], + {'network_info': '[]'}) self.mox.ReplayAll() api = neutronapi.API()