From 1d7fa33ffdd43fe36f8a83088b5b51bc0d875925 Mon Sep 17 00:00:00 2001 From: elumalai Date: Tue, 12 Apr 2022 12:54:37 +0530 Subject: [PATCH] Feature 10916 Remove VNF Instance from NS - NS Update Added support to remove a VNF's policies using NS Update Added unit test cases Change-Id: Ia38a57a86ebe6b1d54073ed8331e0719215ed5fc Signed-off-by: elumalai --- osm_policy_module/alarming/service.py | 12 ++++- osm_policy_module/autoscaling/service.py | 14 ++++-- osm_policy_module/core/agent.py | 23 ++++++++- .../tests/unit/core/test_policy_agent.py | 48 +++++++++++++++++++ 4 files changed, 90 insertions(+), 7 deletions(-) diff --git a/osm_policy_module/alarming/service.py b/osm_policy_module/alarming/service.py index d1d1ea5..4b393e5 100644 --- a/osm_policy_module/alarming/service.py +++ b/osm_policy_module/alarming/service.py @@ -25,6 +25,8 @@ import asyncio import json import logging +import operator +import functools import requests from requests.exceptions import ConnectionError, RequestException @@ -195,12 +197,18 @@ class AlarmingService: finally: database.db.close() - async def delete_vnf_alarms(self, nsr_id): + async def delete_vnf_alarms(self, nsr_id, vnf_member_index=None): log.info("Deleting vnf alarms for network service %s", nsr_id) database.db.connect() try: with database.db.atomic(): - for alarm in VnfAlarmRepository.list(VnfAlarm.nsr_id == nsr_id): + if vnf_member_index is None: + alarm_conditions = VnfAlarm.nsr_id == nsr_id + else: + query_list = [VnfAlarm.nsr_id == nsr_id, + VnfAlarm.vnf_member_index == vnf_member_index] + alarm_conditions = functools.reduce(operator.and_, query_list) + for alarm in VnfAlarmRepository.list(alarm_conditions): log.debug("Deleting vnf alarm %s", alarm.alarm_uuid) try: await self.mon_client.delete_alarm( diff --git a/osm_policy_module/autoscaling/service.py b/osm_policy_module/autoscaling/service.py index a8c36e0..41731b4 100644 --- a/osm_policy_module/autoscaling/service.py +++ b/osm_policy_module/autoscaling/service.py @@ -26,6 +26,8 @@ import asyncio import datetime import json import logging +import operator +import functools from osm_policy_module.common.common_db_client import CommonDbClient from osm_policy_module.common.lcm_client import LcmClient @@ -245,15 +247,19 @@ class AutoscalingService: finally: database.db.close() - async def delete_scaling_groups(self, nsr_id: str): + async def delete_scaling_groups(self, nsr_id: str, vnf_member_index=None): log.debug("Deleting scaling groups for network service %s", nsr_id) database.db.connect() try: with database.db.atomic() as tx: try: - for scaling_group in ScalingGroupRepository.list( - ScalingGroup.nsr_id == nsr_id - ): + if vnf_member_index is None: + scale_conditions = ScalingGroup.nsr_id == nsr_id + else: + query_list = [ScalingGroup.nsr_id == nsr_id, + ScalingGroup.vnf_member_index == vnf_member_index] + scale_conditions = functools.reduce(operator.and_, query_list) + for scaling_group in ScalingGroupRepository.list(scale_conditions): for scaling_policy in scaling_group.scaling_policies: for scaling_criteria in scaling_policy.scaling_criterias: for alarm in scaling_criteria.scaling_alarms: diff --git a/osm_policy_module/core/agent.py b/osm_policy_module/core/agent.py index 95cc830..a73cd5b 100644 --- a/osm_policy_module/core/agent.py +++ b/osm_policy_module/core/agent.py @@ -36,7 +36,7 @@ from osm_policy_module.core.config import Config log = logging.getLogger(__name__) -ALLOWED_KAFKA_KEYS = ["instantiated", "scaled", "terminated", "notify_alarm"] +ALLOWED_KAFKA_KEYS = ["instantiated", "scaled", "terminated", "notify_alarm", "vnf_terminated"] class PolicyModuleAgent: @@ -78,6 +78,9 @@ class PolicyModuleAgent: if key == "notify_alarm": await self._handle_alarm_notification(msg) + + if key == "vnf_terminated": + await self._handle_vnf_terminated(msg) else: log.debug("Key %s is not in ALLOWED_KAFKA_KEYS", key) except peewee.PeeweeException: @@ -151,3 +154,21 @@ class PolicyModuleAgent: "Current state is %s. Skipping...", content["operationState"], ) + + async def _handle_vnf_terminated(self, content): + nsr_id = content['nsr_id'] + vnf_member_index = content['vnf_member_index'] + if ( + content["operationState"] == "COMPLETED" + or content["operationState"] == "PARTIALLY_COMPLETED" + ): + log.info( + "Deleting policies of VNF with nsr_id: %s and vnf-member-index: %s" + % (nsr_id, vnf_member_index)) + await self.autoscaling_service.delete_scaling_groups(nsr_id, vnf_member_index) + await self.alarming_service.delete_vnf_alarms(nsr_id, vnf_member_index) + else: + log.info( + "Network service is not in COMPLETED or PARTIALLY_COMPLETED state. " + "Current state is %s. Skipping...", + content['operationState']) diff --git a/osm_policy_module/tests/unit/core/test_policy_agent.py b/osm_policy_module/tests/unit/core/test_policy_agent.py index 77c285d..f9f78cc 100644 --- a/osm_policy_module/tests/unit/core/test_policy_agent.py +++ b/osm_policy_module/tests/unit/core/test_policy_agent.py @@ -136,6 +136,54 @@ class PolicyAgentTest(unittest.TestCase): autoscaling_handle_alarm.assert_called_with("test_alarm_uuid", "alarm") alarming_handle_alarm.assert_called_with("test_alarm_uuid", "alarm", content) + @mock.patch.object(CommonDbClient, "__init__", lambda *args, **kwargs: None) + @mock.patch("osm_policy_module.alarming.service.MonClient") + @mock.patch("osm_policy_module.alarming.service.LcmClient") + @mock.patch("osm_policy_module.autoscaling.service.MonClient") + @mock.patch("osm_policy_module.autoscaling.service.LcmClient") + @mock.patch.object(AutoscalingService, "delete_scaling_groups") + @mock.patch.object(AlarmingService, "delete_vnf_alarms") + def test_handle_vnf_terminated( + self, + delete_vnf_alarms, + delete_scaling_groups, + autoscaling_lcm_client, + autoscaling_mon_client, + alarming_lcm_client, + alarming_mon_client, + ): + async def mock_delete_scaling_groups(nsr_id, vnf_member_index): + pass + + async def mock_delete_vnf_alarms(nsr_id, vnf_member_index): + pass + + config = Config() + agent = PolicyModuleAgent(config, self.loop) + assert autoscaling_lcm_client.called + assert autoscaling_mon_client.called + assert alarming_lcm_client.called + assert alarming_mon_client.called + content = { + "nsr_id": "test_nsr_id", + "vnf_member_index": "1", + "operationState": "COMPLETED" + } + failed_content = { + "nsr_id": "test_nsr_id", + "vnf_member_index": "1", + "operationState": "FAILED" + } + delete_scaling_groups.side_effect = mock_delete_scaling_groups + delete_vnf_alarms.side_effect = mock_delete_vnf_alarms + + self.loop.run_until_complete(agent._handle_vnf_terminated(content)) + delete_scaling_groups.assert_called_with("test_nsr_id", "1") + delete_scaling_groups.reset_mock() + + self.loop.run_until_complete(agent._handle_vnf_terminated(failed_content)) + delete_scaling_groups.assert_not_called() + if __name__ == "__main__": unittest.main() -- 2.17.1