From 7bf459598a4b88e88f1d8f19127a8b4a111a02ef Mon Sep 17 00:00:00 2001 From: rabi Date: Thu, 5 Jan 2017 11:11:01 +0530 Subject: [PATCH] Don't try detach interface when server not found If a server is already deleted, don't try interface detachment and check for detach complete. Change-Id: I6305cec75e09ab0b4e3e97b554f385b6627e0216 Closes-Bug: #1654149 --- heat/engine/clients/os/nova.py | 24 +++++++++--------- .../openstack/nova/server_network_mixin.py | 6 ++++- heat/tests/openstack/nova/test_server.py | 25 ++++++++++++++++--- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/heat/engine/clients/os/nova.py b/heat/engine/clients/os/nova.py index ea9b8fbbb1..61e5be1732 100644 --- a/heat/engine/clients/os/nova.py +++ b/heat/engine/clients/os/nova.py @@ -691,12 +691,11 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers return False def interface_detach(self, server_id, port_id): - server = self.fetch_server(server_id) - if server: - server.interface_detach(port_id) - return True - else: - return False + with self.ignore_not_found: + server = self.fetch_server(server_id) + if server: + server.interface_detach(port_id) + return True def interface_attach(self, server_id, port_id=None, net_id=None, fip=None): server = self.fetch_server(server_id) @@ -712,12 +711,13 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers wait=tenacity.wait_fixed(0.5), retry=tenacity.retry_if_result(client_plugin.retry_if_result_is_false)) def check_interface_detach(self, server_id, port_id): - server = self.fetch_server(server_id) - if server: - interfaces = server.interface_list() - for iface in interfaces: - if iface.port_id == port_id: - return False + with self.ignore_not_found: + server = self.fetch_server(server_id) + if server: + interfaces = server.interface_list() + for iface in interfaces: + if iface.port_id == port_id: + return False return True @tenacity.retry( diff --git a/heat/engine/resources/openstack/nova/server_network_mixin.py b/heat/engine/resources/openstack/nova/server_network_mixin.py index 74f6f88804..40349860bd 100644 --- a/heat/engine/resources/openstack/nova/server_network_mixin.py +++ b/heat/engine/resources/openstack/nova/server_network_mixin.py @@ -422,8 +422,12 @@ class ServerNetworkMixin(object): def detach_ports(self, server): existing_server_id = server.resource_id for port in self.get_all_ports(server): - self.client_plugin().interface_detach( + detach_called = self.client_plugin().interface_detach( existing_server_id, port['id']) + + if not detach_called: + return + try: if self.client_plugin().check_interface_detach( existing_server_id, port['id']): diff --git a/heat/tests/openstack/nova/test_server.py b/heat/tests/openstack/nova/test_server.py index eab197bed4..9d762bc414 100644 --- a/heat/tests/openstack/nova/test_server.py +++ b/heat/tests/openstack/nova/test_server.py @@ -4518,7 +4518,8 @@ class ServerInternalPortTest(common.HeatTestCase): external_port_ids = [{'id': 5566}] server._data = {"internal_ports": jsonutils.dumps(port_ids), "external_ports": jsonutils.dumps(external_port_ids)} - self.patchobject(nova.NovaClientPlugin, 'interface_detach') + self.patchobject(nova.NovaClientPlugin, 'interface_detach', + return_value=True) self.patchobject(nova.NovaClientPlugin, 'check_interface_detach', return_value=True) @@ -4530,6 +4531,22 @@ class ServerInternalPortTest(common.HeatTestCase): mock.call('test_server', 3344), mock.call('test_server', 5566)]) + def test_prepare_ports_for_replace_not_found(self): + t, stack, server = self._return_template_stack_and_rsrc_defn( + 'test', tmpl_server_with_network_id) + server.resource_id = 'test_server' + port_ids = [{'id': 1122}, {'id': 3344}] + external_port_ids = [{'id': 5566}] + server._data = {"internal_ports": jsonutils.dumps(port_ids), + "external_ports": jsonutils.dumps(external_port_ids)} + self.patchobject(nova.NovaClientPlugin, 'fetch_server', + side_effect=nova_exceptions.NotFound(404)) + check_detach = self.patchobject(nova.NovaClientPlugin, + 'check_interface_detach') + + server.prepare_for_replace() + check_detach.assert_not_called() + @mock.patch.object(server_network_mixin.ServerNetworkMixin, 'store_external_ports') def test_restore_ports_after_rollback(self, store_ports): @@ -4550,7 +4567,8 @@ class ServerInternalPortTest(common.HeatTestCase): stack._backup_stack().resources.get.return_value = old_server old_server._data_get_ports.side_effect = [port_ids, external_port_ids] - self.patchobject(nova.NovaClientPlugin, 'interface_detach') + self.patchobject(nova.NovaClientPlugin, 'interface_detach', + return_value=True) self.patchobject(nova.NovaClientPlugin, 'check_interface_detach', return_value=True) self.patchobject(nova.NovaClientPlugin, 'interface_attach') @@ -4643,7 +4661,8 @@ class ServerInternalPortTest(common.HeatTestCase): # mock previous resource was replaced by existing resource prev_rsrc.replaced_by = existing_rsrc.id - self.patchobject(nova.NovaClientPlugin, 'interface_detach') + self.patchobject(nova.NovaClientPlugin, 'interface_detach', + return_value=True) self.patchobject(nova.NovaClientPlugin, 'check_interface_detach', return_value=True) self.patchobject(nova.NovaClientPlugin, 'interface_attach')