diff --git a/magnum/common/octavia.py b/magnum/common/octavia.py index f069a4c61d..010795b61a 100644 --- a/magnum/common/octavia.py +++ b/magnum/common/octavia.py @@ -14,6 +14,7 @@ import re import time +import heatclient.exc as heat_exc from osc_lib import exceptions as osc_exc from oslo_config import cfg from oslo_log import log as logging @@ -106,9 +107,14 @@ def delete_loadbalancers(context, cluster): # Get load balancers created for Kubernetes api/etcd lbs = [] - lb_resources = heat_client.resources.list( - cluster.stack_id, nested_depth=2, - filters={"type": lb_resource_type}) + try: + lb_resources = heat_client.resources.list( + cluster.stack_id, nested_depth=2, + filters={"type": lb_resource_type}) + except heat_exc.HTTPNotFound: + # NOTE(mnaser): It's possible that the stack has been deleted + # but Magnum still has a `stack_id` pointing. + return for lb_res in lb_resources: lb_id = lb_res.physical_resource_id if not lb_id: diff --git a/magnum/tests/unit/common/test_octavia.py b/magnum/tests/unit/common/test_octavia.py index 675a328d21..094df7bfe5 100644 --- a/magnum/tests/unit/common/test_octavia.py +++ b/magnum/tests/unit/common/test_octavia.py @@ -14,6 +14,8 @@ from unittest import mock +import heatclient.exc as heat_exc + from magnum.common import exception from magnum.common import octavia from magnum import objects @@ -169,3 +171,26 @@ class OctaviaTest(base.TestCase): self.assertFalse(mock_octavia_client.load_balancer_show.called) self.assertFalse(mock_octavia_client.load_balancer_delete.called) + + @mock.patch("magnum.common.neutron.delete_floatingip") + @mock.patch('magnum.common.clients.OpenStackClients') + def test_delete_loadbalancers_with_stack_not_found(self, mock_clients, + mock_delete_fip): + mock_octavia_client = mock.MagicMock() + mock_octavia_client.load_balancer_list.return_value = { + "loadbalancers": [] + } + + mock_heat_client = mock.MagicMock() + mock_heat_client.resources.list.side_effect = \ + heat_exc.HTTPNotFound + + osc = mock.MagicMock() + mock_clients.return_value = osc + osc.octavia.return_value = mock_octavia_client + osc.heat.return_value = mock_heat_client + + octavia.delete_loadbalancers(self.context, self.cluster) + + self.assertFalse(mock_octavia_client.load_balancer_show.called) + self.assertFalse(mock_octavia_client.load_balancer_delete.called)