Handle AAI Update and Delete events for PMSH
Change-Id: I7f84e4429011bbaea4de23077ce23629b897fd7d
Issue-ID: DCAEGEN2-1846
Signed-off-by: emartin <ephraim.martin@est.tech>
diff --git a/components/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py b/components/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py
new file mode 100755
index 0000000..f8254e5
--- /dev/null
+++ b/components/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py
@@ -0,0 +1,90 @@
+# ============LICENSE_START===================================================
+# Copyright (C) 2020 Nordix Foundation.
+# ============================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+
+import json
+from enum import Enum
+
+from mod import pmsh_logging as logger
+from mod.network_function import NetworkFunction
+from mod.subscription import NetworkFunctionFilter
+
+
+class XNFType(Enum):
+ PNF = 'pnf'
+ VNF = 'vnf'
+
+
+class AAIEvent(Enum):
+ DELETE = 'DELETE'
+ UPDATE = 'UPDATE'
+
+
+class OrchestrationStatus(Enum):
+ ACTIVE = 'Active'
+ INVENTORIED = 'Inventoried'
+
+
+def process_aai_events(mr_sub, subscription, mr_pub, app):
+ """
+ Processes AAI UPDATE events for each filtered xNFs where orchestration status is set to Active.
+
+ Args:
+ mr_sub (_MrSub): MR subscriber
+ subscription (Subscription): The current subscription object
+ mr_pub (_MrPub): MR publisher
+ app (db): DB application
+ """
+ app.app_context().push()
+ aai_events = mr_sub.get_from_topic('AAI-EVENT')
+
+ if _aai_event_exists(aai_events):
+ for entry in aai_events:
+ logger.debug(f'AAI-EVENT entry: {entry}')
+ entry = json.loads(entry)
+ event_header = entry['event-header']
+ aai_xnf = entry['entity']
+ action = event_header['action']
+ entity_type = event_header['entity-type']
+ xnf_name = aai_xnf['pnf-name'] if entity_type == XNFType.PNF.value else aai_xnf[
+ 'vnf-name']
+ new_status = aai_xnf['orchestration-status']
+
+ if NetworkFunctionFilter(**subscription.nfFilter).is_nf_in_filter(xnf_name):
+ _process_event(action, new_status, xnf_name, subscription, mr_pub)
+
+
+def _process_event(action, new_status, xnf_name, subscription, mr_pub):
+ if action == AAIEvent.UPDATE.value:
+ logger.debug(f'Update event found for network function {xnf_name}')
+ local_xnf = NetworkFunction.get(xnf_name)
+
+ if local_xnf is None:
+ logger.debug(f'Activating subscription for network function {xnf_name}')
+ subscription.process_subscription([NetworkFunction(
+ nf_name=xnf_name, orchestration_status=new_status)], mr_pub)
+ else:
+ logger.debug(f"Update Event for network function {xnf_name} will not be processed "
+ f" as it's state is set to {local_xnf.orchestration_status}.")
+ elif action == AAIEvent.DELETE.value:
+ logger.debug(f'Delete event found for network function {xnf_name}')
+ NetworkFunction.delete(nf_name=xnf_name)
+ logger.debug(f'{xnf_name} successfully deleted.')
+
+
+def _aai_event_exists(aai_events):
+ return aai_events is not None and len(aai_events) != 0
diff --git a/components/pm-subscription-handler/pmsh_service/mod/db_models.py b/components/pm-subscription-handler/pmsh_service/mod/db_models.py
index 479d40e..d183676 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/db_models.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/db_models.py
@@ -67,6 +67,9 @@
class NfSubRelationalModel(db.Model):
__tablename__ = 'nf_to_sub_rel'
+ __mapper_args__ = {
+ 'confirm_deleted_rows': False
+ }
id = Column(Integer, primary_key=True, autoincrement=True)
subscription_name = Column(
String,
diff --git a/components/pm-subscription-handler/pmsh_service/mod/network_function.py b/components/pm-subscription-handler/pmsh_service/mod/network_function.py
index 9f21cc6..c4b9b56 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/network_function.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/network_function.py
@@ -32,6 +32,13 @@
def __str__(self):
return f'nf-name: {self.nf_name}, orchestration-status: {self.orchestration_status}'
+ def __eq__(self, other):
+ return self.nf_name == other.nf_name and \
+ self.orchestration_status == other.orchestration_status
+
+ def __hash__(self):
+ return hash((self.nf_name, self.orchestration_status))
+
def create(self):
""" Creates a NetworkFunction database entry """
existing_nf = NetworkFunctionModel.query.filter(
@@ -72,8 +79,7 @@
def delete(**kwargs):
""" Deletes a network function from the database """
nf_name = kwargs['nf_name']
- NetworkFunctionModel.query.filter(
- NetworkFunctionModel.nf_name == nf_name). \
- delete(synchronize_session='evaluate')
+ nf = NetworkFunctionModel.query.filter(
+ NetworkFunctionModel.nf_name == nf_name).one_or_none()
- db.session.commit()
+ db.session.delete(nf) if nf else None
diff --git a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py b/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
index 4a77543..9ff0c65 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
@@ -18,14 +18,15 @@
import json
import threading
import uuid
+from threading import Timer
import requests
from requests.auth import HTTPBasicAuth
from tenacity import retry, wait_fixed, retry_if_exception_type
import mod.pmsh_logging as logger
-from mod.subscription import Subscription, SubNfState, AdministrativeState
from mod.network_function import NetworkFunction
+from mod.subscription import Subscription, SubNfState, AdministrativeState
class AppConfig:
@@ -163,6 +164,7 @@
try:
session = requests.Session()
headers = {'accept': 'application/json', 'content-type': 'application/json'}
+ logger.debug(f'Request sent to MR topic: {self.topic_url}')
response = session.get(f'{self.topic_url}/{consumer_group}/{consumer_id}'
f'?timeout={timeout}',
auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), headers=headers,
@@ -241,3 +243,12 @@
'failed': Subscription.update_sub_nf_status
}
}
+
+
+class PeriodicTask(Timer):
+ """
+ See :class:`Timer`.
+ """
+ def run(self):
+ while not self.finished.wait(self.interval):
+ self.function(*self.args, **self.kwargs)
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription.py b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
index 031609a..7a0b88c 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
@@ -143,12 +143,19 @@
db.session.commit()
def delete_subscription(self):
- """ Deletes a subscription from the database """
- SubscriptionModel.query.filter(
- SubscriptionModel.subscription_name == self.subscriptionName). \
- delete(synchronize_session='evaluate')
-
- db.session.commit()
+ """ Deletes a subscription and all its association from the database. A network function
+ that is only associated with the subscription being removed will also be deleted."""
+ subscription = SubscriptionModel.query.filter(
+ SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
+ if subscription:
+ for nf_relationship in subscription.nfs:
+ other_nf_relationship = NfSubRelationalModel.query.filter(
+ NfSubRelationalModel.subscription_name != self.subscriptionName,
+ NfSubRelationalModel.nf_name == nf_relationship.nf_name).one_or_none()
+ if not other_nf_relationship:
+ db.session.delete(nf_relationship.nf)
+ db.session.delete(subscription)
+ db.session.commit()
@retry(wait=wait_exponential(multiplier=1, min=30, max=120), stop=stop_after_attempt(3),
retry=retry_if_exception_type(Exception))
diff --git a/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py b/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py
index 5c81250..31d1d07 100755
--- a/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py
+++ b/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py
@@ -21,12 +21,14 @@
import mod.aai_client as aai
import mod.pmsh_logging as logger
from mod import db, create_app, launch_api_server
+from mod.aai_event_handler import process_aai_events
from mod.config_handler import ConfigHandler
-from mod.pmsh_utils import AppConfig
+from mod.pmsh_utils import AppConfig, PeriodicTask
from mod.subscription import Subscription, AdministrativeState
-def subscription_processor(config_handler, administrative_state, mr_pub, app):
+def subscription_processor(config_handler, administrative_state, mr_pub, app,
+ mr_aai_event_subscriber):
"""
Checks for changes of administrative state in config and proceeds to process
the Subscription if a change has occurred
@@ -36,10 +38,10 @@
administrative_state (str): The administrative state
mr_pub (_MrPub): MR publisher
app (db): DB application
+ mr_aai_event_subscriber (_MrSub): AAI events MR subscriber
"""
app.app_context().push()
config = config_handler.get_config()
- sub, nfs = aai.get_pmsh_subscription_data(config)
new_administrative_state = config['policy']['subscription']['administrativeState']
polling_period = 30.0
@@ -47,17 +49,29 @@
if administrative_state == new_administrative_state:
logger.debug('Administrative State did not change in the Config')
else:
+ logger.debug(f'Administrative State changed from "{administrative_state}" "to '
+ f'"{new_administrative_state}".')
+ sub, nfs = aai.get_pmsh_subscription_data(config)
sub.process_subscription(nfs, mr_pub)
+ aai_event_thread = PeriodicTask(10, process_aai_events, args=(mr_aai_event_subscriber,
+ sub, mr_pub, app))
+
+ if new_administrative_state == AdministrativeState.UNLOCKED.value:
+ logger.debug('Listening to AAI-EVENT topic in MR.')
+ aai_event_thread.start()
+ else:
+ logger.debug('Stopping to listen to AAI-EVENT topic in MR.')
+ aai_event_thread.cancel()
except Exception as err:
logger.debug(f'Error occurred during the activation/deactivation process {err}')
threading.Timer(polling_period, subscription_processor,
- [config_handler, new_administrative_state, mr_pub, app]).start()
+ [config_handler, new_administrative_state, mr_pub, app,
+ mr_aai_event_subscriber]).start()
def main():
-
try:
config_handler = ConfigHandler()
config = config_handler.get_config()
@@ -68,6 +82,7 @@
sub, nfs = aai.get_pmsh_subscription_data(config)
mr_pub = app_conf.get_mr_pub('policy_pm_publisher')
mr_sub = app_conf.get_mr_sub('policy_pm_subscriber')
+ mr_aai_event_subscriber = app_conf.get_mr_sub('aai_subscriber')
initial_start_delay = 5.0
administrative_state = AdministrativeState.LOCKED.value
@@ -76,7 +91,8 @@
administrative_state = subscription_in_db.status
threading.Timer(initial_start_delay, subscription_processor,
- [config_handler, administrative_state, mr_pub, app]).start()
+ [config_handler, administrative_state, mr_pub,
+ app, mr_aai_event_subscriber]).start()
threading.Timer(20.0, mr_sub.poll_policy_topic, [sub.subscriptionName, app]).start()
diff --git a/components/pm-subscription-handler/tests/data/mr_aai_events.json b/components/pm-subscription-handler/tests/data/mr_aai_events.json
new file mode 100755
index 0000000..202d133
--- /dev/null
+++ b/components/pm-subscription-handler/tests/data/mr_aai_events.json
@@ -0,0 +1,6 @@
+{
+ "mr_response": [
+ "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"UPDATE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3640\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"ipaddress-v4-oam\":\"10.10.10.37\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_newly_discovered\",\"orchestration-status\":\"Active\"}}",
+ "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"UPDATE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3640\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"orchestration-status\":\"Active\",\"ipaddress-v4-oam\":\"10.10.10.37\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_already_active\",\"orchestration-status\":\"Active\"}}",
+ "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"DELETE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3640\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"ipaddress-v4-oam\":\"10.10.10.37\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_to_be_deleted\",\"orchestration-status\":\"Active\"}}"]
+}
diff --git a/components/pm-subscription-handler/tests/test_aai_event_handler.py b/components/pm-subscription-handler/tests/test_aai_event_handler.py
new file mode 100755
index 0000000..add7b3f
--- /dev/null
+++ b/components/pm-subscription-handler/tests/test_aai_event_handler.py
@@ -0,0 +1,53 @@
+# ============LICENSE_START===================================================
+# Copyright (C) 2020 Nordix Foundation.
+# ============================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+import json
+from os import path
+from unittest import TestCase
+from unittest.mock import patch, Mock
+
+from mod.aai_event_handler import OrchestrationStatus, process_aai_events
+from mod.network_function import NetworkFunction
+
+
+class AAIEventHandlerTest(TestCase):
+
+ def setUp(self):
+ with open(path.join(path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
+ self.cbs_data_1 = json.load(data)
+ with open(path.join(path.dirname(__file__), 'data/mr_aai_events.json'), 'r') as data:
+ self.mr_aai_events = json.load(data)["mr_response"]
+ self.mock_sub = Mock(nfFilter={'swVersions': ['1.0.0', '1.0.1'],
+ 'nfNames': ['^pnf.*', '^vnf.*']})
+ self.mock_mr_sub = Mock(get_from_topic=Mock(return_value=self.mr_aai_events))
+ self.mock_mr_pub = Mock()
+ self.mock_app = Mock()
+
+ @patch('mod.aai_event_handler.NetworkFunction.delete')
+ @patch('mod.aai_event_handler.NetworkFunction.get')
+ def test_process_aai_update_and_delete_events(self, mock_nf_get, mock_nf_delete):
+ pnf_already_active = NetworkFunction(nf_name='pnf_already_active',
+ orchestration_status=OrchestrationStatus.ACTIVE.value)
+ mock_nf_get.side_effect = [None, pnf_already_active]
+ expected_nf_for_processing = NetworkFunction(
+ nf_name='pnf_newly_discovered', orchestration_status=OrchestrationStatus.ACTIVE.value)
+
+ process_aai_events(self.mock_mr_sub, self.mock_sub, self.mock_mr_pub, self.mock_app)
+
+ self.mock_sub.process_subscription.assert_called_once_with([expected_nf_for_processing],
+ self.mock_mr_pub)
+ mock_nf_delete.assert_called_once_with(nf_name='pnf_to_be_deleted')
diff --git a/components/pm-subscription-handler/tests/test_network_function.py b/components/pm-subscription-handler/tests/test_network_function.py
index e9394b4..4fca077 100755
--- a/components/pm-subscription-handler/tests/test_network_function.py
+++ b/components/pm-subscription-handler/tests/test_network_function.py
@@ -21,6 +21,7 @@
from mod import db, create_app
from mod.network_function import NetworkFunction
+from mod.subscription import Subscription
class NetworkFunctionTests(TestCase):
@@ -69,7 +70,13 @@
def test_delete_network_function(self):
self.nf_1.create()
self.nf_2.create()
- self.nf_1.delete(nf_name='pnf_1')
- nfs = NetworkFunction.get_all()
+ sub = Subscription(**{"subscriptionName": "sub"})
+ sub.add_network_functions_to_subscription([self.nf_1, self.nf_2])
+ NetworkFunction.delete(nf_name=self.nf_1.nf_name)
+
+ nfs = NetworkFunction.get_all()
self.assertEqual(1, len(nfs))
+ self.assertEqual(1, len(Subscription.get_all_nfs_subscription_relations()))
+ pnf_1_deleted = [nf for nf in nfs if nf.nf_name != self.nf_1.nf_name]
+ self.assertTrue(pnf_1_deleted)
diff --git a/components/pm-subscription-handler/tests/test_pmsh_service.py b/components/pm-subscription-handler/tests/test_pmsh_service.py
index 4a6032b..b722567 100644
--- a/components/pm-subscription-handler/tests/test_pmsh_service.py
+++ b/components/pm-subscription-handler/tests/test_pmsh_service.py
@@ -38,19 +38,22 @@
self.mock_sub = mock_sub
self.mock_mr_pub = mock_mr_pub
self.mock_config_handler = mock_config_handler
+ self.mock_aai_sub = mock_sub
self.nf_1 = NetworkFunction(nf_name='pnf_1')
self.nf_2 = NetworkFunction(nf_name='pnf_2')
self.nfs = [self.nf_1, self.nf_2]
@patch('threading.Timer')
@patch('mod.aai_client.get_pmsh_subscription_data')
- def test_subscription_processor_changed_state(self, mock_get_aai, mock_thread):
+ @patch('pmsh_service_main.PeriodicTask')
+ def test_subscription_processor_changed_state(self, periodic_task, mock_get_aai, mock_thread):
self.mock_config_handler.get_config.return_value = self.cbs_data_1
mock_get_aai.return_value = self.mock_sub, self.nfs
mock_thread.start.return_value = 1
+ periodic_task.start.return_value = 1
pmsh_service.subscription_processor(self.mock_config_handler, 'LOCKED',
- self.mock_mr_pub, self.mock_app)
+ self.mock_mr_pub, self.mock_app, self.mock_aai_sub)
self.mock_sub.process_subscription.assert_called_with(self.nfs, self.mock_mr_pub)
@@ -63,7 +66,7 @@
mock_thread.start.return_value = 1
pmsh_service.subscription_processor(self.mock_config_handler, 'UNLOCKED', self.mock_mr_pub,
- self.mock_app)
+ self.mock_app, self.mock_aai_sub)
mock_logger.assert_called_with('Administrative State did not change in the Config')
@@ -77,6 +80,6 @@
self.mock_sub.process_subscription.side_effect = Exception
pmsh_service.subscription_processor(self.mock_config_handler, 'LOCKED', self.mock_mr_pub,
- self.mock_app)
+ self.mock_app, self.mock_aai_sub)
mock_logger.assert_called_with(f'Error occurred during the '
f'activation/deactivation process ')
diff --git a/components/pm-subscription-handler/tests/test_subscription.py b/components/pm-subscription-handler/tests/test_subscription.py
index 8fe233e..c357ad7 100755
--- a/components/pm-subscription-handler/tests/test_subscription.py
+++ b/components/pm-subscription-handler/tests/test_subscription.py
@@ -134,13 +134,16 @@
self.assertEqual('new_status', sub.status)
def test_delete_subscription(self):
- self.sub_1.create()
- subs = self.sub_1.get_all()
- self.assertEqual(1, len(subs))
+ self.sub_1.add_network_functions_to_subscription([self.nf_1, self.nf_2])
+ self.sub_2.add_network_functions_to_subscription([self.nf_2])
self.sub_1.delete_subscription()
- new_subs = self.sub_1.get_all()
- self.assertEqual(0, len(new_subs))
+
+ self.assertEqual(1, len(Subscription.get_all()))
+ self.assertEqual(None, Subscription.get(self.sub_1.subscriptionName))
+ self.assertEqual(1, len(Subscription.get_all_nfs_subscription_relations()))
+ self.assertEqual(1, len(NetworkFunction.get_all()))
+ self.assertEqual(None, NetworkFunction.get(nf_name=self.nf_1.nf_name))
def test_update_sub_nf_status(self):
sub_name = 'ExtraPM-All-gNB-R2B'