heat notifier: Fix getting unhealthy resource names

In the autoscaling scenario, the resource which should be marked as
unhealthy is always the parent resource of the failed load balancer pool
member.

Change-Id: I30cfe9d1cc8c7209e6f865bdd721494dcb4e33ed
(cherry picked from commit b47550ae44)
This commit is contained in:
Lingxian Kong 2019-10-09 22:55:44 +13:00
parent f041de28ee
commit 9e17daad69
2 changed files with 14 additions and 67 deletions

View File

@ -13,7 +13,6 @@
# limitations under the License.
from oslo_log import log
from oslo_utils import uuidutils
import six
from aodh import keystone_client as aodh_keystone
@ -42,18 +41,6 @@ class TrustHeatAlarmNotifier(notifier.AlarmNotifier):
- Heat top/root stack ID.
- Heat autoscaling group ID.
- The failed Octavia pool members.
In order to find which autoscaling group member that the failed pool member
belongs to, there are two ways supported(both ways require specific
definition in the Heat template):
1. The autoscaling group member resource ID is saved in the Octavia member
tag, the user should define that using 'tags' property of the
OS::Octavia::PoolMember resource. So, only Octavia stable/stein or later
versions are supported.
2. User customizes the autoscaling group member resource identifier
according to
https://docs.openstack.org/heat/latest/template_guide/composition.html#making-your-template-resource-more-transparent
"""
def __init__(self, conf):
@ -92,25 +79,20 @@ class TrustHeatAlarmNotifier(notifier.AlarmNotifier):
)
for member in unhealthy_members:
for tag in member.get("tags", []):
if uuidutils.is_uuid_like(tag):
unhealthy_resources.append(tag)
target_resources = heat_client.resources.list(
stack_id, nested_depth=3,
filters={"physical_resource_id": member["id"]}
)
if len(target_resources) > 0:
# There should be only one item.
unhealthy_resources.append(
target_resources[0].parent_resource
)
if not unhealthy_resources:
# Fall back to search resource by the pool member ID.
for member in unhealthy_members:
target_resources = heat_client.resources.list(
stack_id, nested_depth=3, filters={"id": member["id"]})
if len(target_resources) > 0:
# There should be only one item.
unhealthy_resources.append(
target_resources[0].resource_name)
# If we still can't find expected resources, do nothing.
if not unhealthy_resources:
LOG.warning("No unhealthy resource found for the alarm %s",
alarm_id)
return
LOG.warning("No unhealthy resource found for the alarm %s",
alarm_id)
return
try:
for res in unhealthy_resources:

View File

@ -21,42 +21,7 @@ from aodh.tests.unit.notifier import base
class TestTrustHeatAlarmNotifier(base.TestNotifierBase):
@mock.patch("aodh.keystone_client.get_heat_client_from_trust")
def test_notify_with_tags(self, mock_heatclient):
action = netutils.urlsplit("trust+autohealer://fake_trust_id:delete@")
alarm_id = "fake_alarm_id"
alarm_name = "fake_alarm_name"
severity = "low"
previous = "ok"
current = "alarm"
reason = "no good reason"
reason_data = {
"stack_id": "fake_stack_id",
"asg_id": "fake_asg_id",
"unhealthy_members": [
{"tags": ["3bd8bc5a-7632-11e9-84cd-00224d6b7bc1"]}
]
}
notifier = heat_notifier.TrustHeatAlarmNotifier(self.conf)
notifier.notify(action, alarm_id, alarm_name, severity, previous,
current, reason, reason_data)
mock_heatclient.assert_called_once_with(self.conf, "fake_trust_id")
mock_client = mock_heatclient.return_value
mock_client.resources.mark_unhealthy.assert_called_once_with(
"fake_asg_id",
"3bd8bc5a-7632-11e9-84cd-00224d6b7bc1",
True,
"unhealthy load balancer member"
)
mock_client.stacks.update.assert_called_once_with(
"fake_stack_id", existing=True
)
@mock.patch("aodh.keystone_client.get_heat_client_from_trust")
def test_notify_without_tags(self, mock_heatclient):
def test_notify(self, mock_heatclient):
action = netutils.urlsplit("trust+autohealer://fake_trust_id:delete@")
alarm_id = "fake_alarm_id"
alarm_name = "fake_alarm_name"
@ -74,7 +39,7 @@ class TestTrustHeatAlarmNotifier(base.TestNotifierBase):
class FakeResource(object):
def __init__(self, resource_name):
self.resource_name = resource_name
self.parent_resource = resource_name
mock_client = mock_heatclient.return_value
mock_client.resources.list.return_value = [