From 86b5fb73d042138ce9d432a66d9f8a7999fcd8fb Mon Sep 17 00:00:00 2001 From: Mohammed Naser Date: Fri, 19 Nov 2021 10:26:11 -0500 Subject: [PATCH] Fix deleting clusters if stack is deleted If a stack has been deleted (either by Magnum or the user) but Magnum did not update and set `stack_id` to empty, the cluster will fail to delete inside pre-deletion. This will have a safe failover to skip if it can't find the Heat stack, it assumes things are gone. Change-Id: I6ebe188895e51ed83ad1514a380e4772fed5eb42 (cherry picked from commit 4888f706c8a0280971df398cbc1ff06ad5d63e7f) --- magnum/common/octavia.py | 12 +++++++++--- magnum/tests/unit/common/test_octavia.py | 25 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) 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)