summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoregernug <gerard.nugent@est.tech>2021-02-22 11:35:35 +0000
committeregernug <gerard.nugent@est.tech>2021-06-21 10:21:46 +0100
commit1ac9847eb66a074b5413264c788152f7c3ffc28d (patch)
treed62f7495af22f7db652303f4b34bf9b34905a8a1
parentee67930973552a69830c30e6b3b1915091af8ebb (diff)
[PMSH] Update filter
User can edit/update the nfFilter to include/exclude selected NFs Changelog and version update Issue-ID: DCAEGEN2-2531 Signed-off-by: egernug <gerard.nugent@est.tech> Change-Id: I61388775a711687525b12087e9b533bee1c6b039
-rwxr-xr-xcomponents/pm-subscription-handler/Changelog.md4
-rwxr-xr-xcomponents/pm-subscription-handler/dpo/data-formats/dcae-cl-output.json6
-rwxr-xr-xcomponents/pm-subscription-handler/log_config.yaml2
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/api/db_models.py16
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py31
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/sub_schema.json3
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/subscription.py101
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py63
-rw-r--r--components/pm-subscription-handler/pom.xml2
-rw-r--r--components/pm-subscription-handler/setup.py2
-rwxr-xr-xcomponents/pm-subscription-handler/tests/data/pm_subscription_event.json2
-rw-r--r--components/pm-subscription-handler/tests/test_policy_response_handler.py48
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_subscription.py24
-rw-r--r--components/pm-subscription-handler/version.properties4
14 files changed, 252 insertions, 56 deletions
diff --git a/components/pm-subscription-handler/Changelog.md b/components/pm-subscription-handler/Changelog.md
index be2a7a73..81595d22 100755
--- a/components/pm-subscription-handler/Changelog.md
+++ b/components/pm-subscription-handler/Changelog.md
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
+## [1.4.0]
+### Changed
+* Update filter to allow updates in realtime (DCAEGEN2-2531)
+
## [1.3.1]
### Changed
* Updated Subscription object retrieving key from App Config data (DCAEGEN2-2713)
diff --git a/components/pm-subscription-handler/dpo/data-formats/dcae-cl-output.json b/components/pm-subscription-handler/dpo/data-formats/dcae-cl-output.json
index b5cfa8bf..9e6e7ae9 100755
--- a/components/pm-subscription-handler/dpo/data-formats/dcae-cl-output.json
+++ b/components/pm-subscription-handler/dpo/data-formats/dcae-cl-output.json
@@ -15,9 +15,9 @@
"type": "string",
"description": "The name of the nf in A&AI."
},
- "ipv4Address": {
+ "ipAddress": {
"type": "string",
- "description": "The ipv4address of the nf being targeted."
+ "description": "The ip address of the nf being targeted."
},
"policyName": {
"type": "string",
@@ -133,7 +133,7 @@
},
"required": [
"nfName",
- "ipv4Address",
+ "ipAddress",
"policyName",
"closedLoopControlName",
"blueprintName",
diff --git a/components/pm-subscription-handler/log_config.yaml b/components/pm-subscription-handler/log_config.yaml
index b2d8f43c..cf9161cc 100755
--- a/components/pm-subscription-handler/log_config.yaml
+++ b/components/pm-subscription-handler/log_config.yaml
@@ -10,7 +10,7 @@ loggers:
handlers:
onap_log_handler:
class: logging.handlers.RotatingFileHandler
- filename: /var/log/ONAP/dcaegen2/services/pmsh/application.log
+ filename: ./application.log
mode: a
maxBytes: 10000000
backupCount: 10
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py b/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py
index a9dd6efe..4501282e 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2019-2020 Nordix Foundation.
+# Copyright (C) 2019-2021 Nordix Foundation.
# ============================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-from sqlalchemy import Column, Integer, String, ForeignKey
+from sqlalchemy import Column, Integer, String, ForeignKey, JSON
from sqlalchemy.orm import relationship
from mod import db
@@ -26,6 +26,7 @@ class SubscriptionModel(db.Model):
__tablename__ = 'subscriptions'
id = Column(Integer, primary_key=True, autoincrement=True)
subscription_name = Column(String(100), unique=True)
+ nfFilter = Column(JSON)
status = Column(String(20))
nfs = relationship(
@@ -33,12 +34,15 @@ class SubscriptionModel(db.Model):
cascade='all, delete-orphan',
backref='subscription')
- def __init__(self, subscription_name, status):
+ def __init__(self, subscription_name, nfFilter, status):
self.subscription_name = subscription_name
+ self.nfFilter = nfFilter
self.status = status
def __repr__(self):
- return f'subscription_name: {self.subscription_name}, status: {self.status}'
+ return f'subscription_name: {self.subscription_name}, ' \
+ f'nfFilter: {self.nfFilter}, ' \
+ f'status: {self.status}'
def __eq__(self, other):
if isinstance(self, other.__class__):
@@ -49,7 +53,9 @@ class SubscriptionModel(db.Model):
sub_nfs = NfSubRelationalModel.query.filter(
NfSubRelationalModel.subscription_name == self.subscription_name).all()
db.session.remove()
- return {'subscription_name': self.subscription_name, 'subscription_status': self.status,
+ return {'subscription_name': self.subscription_name,
+ 'nfFilter': self.nfFilter,
+ 'subscription_status': self.status,
'network_functions': [sub_nf.serialize_nf() for sub_nf in sub_nfs]}
diff --git a/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py b/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py
index 09c97047..ec331791 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2020 Nordix Foundation.
+# Copyright (C) 2020-2021 Nordix Foundation.
# ============================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,6 +31,10 @@ policy_response_handle_functions = {
'success': Subscription.update_sub_nf_status,
'failed': Subscription.update_sub_nf_status
},
+ AdministrativeState.FILTERING.value: {
+ 'success': NetworkFunction.delete,
+ 'failed': Subscription.update_sub_nf_status
+ },
AdministrativeState.LOCKING.value: {
'success': NetworkFunction.delete,
'failed': Subscription.update_sub_nf_status
@@ -38,6 +42,19 @@ policy_response_handle_functions = {
}
+def _set_sub_nf_status(administrative_state, response_message):
+ """
+
+ Args:
+ administrative_state (str): The administrative state of the subscription
+ response_message (str): The message in the response regarding the state (success|failed)
+
+ Returns:
+ str: sub_nf_status
+ """
+ return subscription_nf_states[administrative_state][response_message].value;
+
+
class PolicyResponseHandler:
def __init__(self, mr_sub, app_conf, app):
self.mr_sub = mr_sub
@@ -60,13 +77,14 @@ class PolicyResponseHandler:
== self.app_conf.subscription.subscriptionName:
nf_name = data['status']['nfName']
response_message = data['status']['message']
+ change_type = data['status']['changeType']
self._handle_response(self.app_conf.subscription.subscriptionName,
- administrative_state, nf_name, response_message)
+ administrative_state, nf_name, response_message, change_type)
except Exception as err:
logger.error(f'Error trying to poll policy response topic on MR: {err}', exc_info=True)
@staticmethod
- def _handle_response(subscription_name, administrative_state, nf_name, response_message):
+ def _handle_response(subscription_name, administrative_state, nf_name, response_message, change_type):
"""
Handles the response from Policy, updating the DB
@@ -79,9 +97,14 @@ class PolicyResponseHandler:
logger.info(f'Response from MR: Sub: {subscription_name} for '
f'NF: {nf_name} received, updating the DB')
try:
+ if administrative_state == AdministrativeState.UNLOCKED.value and change_type == "DELETED":
+ administrative_state = AdministrativeState.FILTERING.value
sub_nf_status = subscription_nf_states[administrative_state][response_message].value
policy_response_handle_functions[administrative_state][response_message](
- subscription_name=subscription_name, status=sub_nf_status, nf_name=nf_name)
+ subscription_name=subscription_name, status=sub_nf_status, nf_name=nf_name)
except Exception as err:
logger.error(f'Error changing nf_sub status in the DB: {err}')
raise
+
+
+
diff --git a/components/pm-subscription-handler/pmsh_service/mod/sub_schema.json b/components/pm-subscription-handler/pmsh_service/mod/sub_schema.json
index 18d48174..3ce81f26 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/sub_schema.json
+++ b/components/pm-subscription-handler/pmsh_service/mod/sub_schema.json
@@ -12,7 +12,8 @@
{
"enum":[
"UNLOCKED",
- "LOCKED"
+ "LOCKED",
+ "FILTERING"
]
}
]
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription.py b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
index fdc1394c..9e721c5f 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
@@ -15,6 +15,7 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
+import json
from enum import Enum
from mod import db, logger
@@ -34,6 +35,7 @@ class AdministrativeState(Enum):
UNLOCKED = 'UNLOCKED'
LOCKING = 'LOCKING'
LOCKED = 'LOCKED'
+ FILTERING = 'FILTERING'
subscription_nf_states = {
@@ -48,6 +50,10 @@ subscription_nf_states = {
AdministrativeState.LOCKING.value: {
'success': SubNfState.DELETED,
'failed': SubNfState.DELETE_FAILED
+ },
+ AdministrativeState.FILTERING.value: {
+ 'success': SubNfState.DELETED,
+ 'failed': SubNfState.DELETE_FAILED
}
}
@@ -61,6 +67,27 @@ def _get_nf_objects(nf_sub_relationships):
return nfs
+def get_nfs_for_creation_and_deletion(existing_nfs, new_nfs, action, mrpub, app_conf):
+ """ Finds new/old nfs for creation/deletion from subscription """
+ for existing_nf in existing_nfs:
+ _compare_nfs(action, app_conf, existing_nf, mrpub, new_nfs)
+
+
+def _compare_nfs(action, app_conf, existing_nf, mrpub, new_nfs):
+ """ Compares old nfs list to existing nfs list"""
+ for new_nf in new_nfs:
+ if existing_nf.nf_name != new_nf.nf_name:
+ _apply_action_to_nfs(action, app_conf, existing_nf, mrpub, new_nf)
+
+
+def _apply_action_to_nfs(action, app_conf, existing_nf, mrpub, new_nf):
+ """ Performs create/delete of nf from subscription as required"""
+ if action == 'create':
+ app_conf.subscription.create_subscription_on_nfs([new_nf], mrpub, app_conf)
+ elif action == 'delete':
+ app_conf.subscription.delete_subscription_from_nfs([existing_nf], mrpub, app_conf)
+
+
class Subscription:
def __init__(self, **kwargs):
self.subscriptionName = kwargs.get('subscriptionName')
@@ -83,30 +110,58 @@ class Subscription:
Returns:
Subscription object
"""
+ existing_subscription = (SubscriptionModel.query.filter(
+ SubscriptionModel.subscription_name == self.subscriptionName).one_or_none())
+ if existing_subscription is None:
+ return self.create_new_sub()
+ else:
+ if existing_subscription.nfFilter and \
+ self._filter_diff(existing_subscription.nfFilter) and \
+ existing_subscription.status == AdministrativeState.UNLOCKED.value:
+ return self.update_existing_sub(existing_subscription)
+
+ def update_existing_sub(self, existing_subscription):
+ """Update subscription status
+
+ Args:
+ existing_subscription: the current subscription
+
+ Returns:
+ Subscription: updated subscription
+ """
+ self.administrativeState = \
+ AdministrativeState.FILTERING.value
+ self.nfFilter = existing_subscription.nfFilter
+ self.update_subscription_status()
+ logger.debug(f'Subscription {self.subscriptionName} already exists,'
+ f' returning this subscription..')
+ return existing_subscription
+
+ def create_new_sub(self):
try:
- existing_subscription = (SubscriptionModel.query.filter(
- SubscriptionModel.subscription_name == self.subscriptionName).one_or_none())
- if existing_subscription is None:
- new_subscription = SubscriptionModel(subscription_name=self.subscriptionName,
- status=AdministrativeState.LOCKED.value)
- db.session.add(new_subscription)
- db.session.commit()
- return new_subscription
- else:
- logger.debug(f'Subscription {self.subscriptionName} already exists,'
- f' returning this subscription..')
- return existing_subscription
+ new_subscription = SubscriptionModel(subscription_name=self.subscriptionName,
+ nfFilter=self.nfFilter,
+ status=AdministrativeState.LOCKED.value)
+ db.session.add(new_subscription)
+ db.session.commit()
+ return new_subscription
except Exception as e:
logger.error(f'Failed to create subscription {self.subscriptionName} in the DB: {e}',
exc_info=True)
finally:
db.session.remove()
+ def _filter_diff(self, existing_subscription_filter):
+ existing_subscription_filter, nf_filter = \
+ json.dumps(existing_subscription_filter, sort_keys=True), \
+ json.dumps(self.nfFilter, sort_keys=True)
+ return existing_subscription_filter != nf_filter
+
def update_subscription_status(self):
""" Updates the status of subscription in subscription table """
try:
SubscriptionModel.query.filter(
- SubscriptionModel.subscription_name == self.subscriptionName)\
+ SubscriptionModel.subscription_name == self.subscriptionName) \
.update({SubscriptionModel.status: self.administrativeState},
synchronize_session='evaluate')
@@ -117,6 +172,21 @@ class Subscription:
finally:
db.session.remove()
+ def update_subscription_filter(self):
+ """ Updates the filter of subscription in subscription table """
+ try:
+ SubscriptionModel.query.filter(
+ SubscriptionModel.subscription_name == self.subscriptionName) \
+ .update({SubscriptionModel.nfFilter: self.nfFilter},
+ synchronize_session='evaluate')
+
+ db.session.commit()
+ except Exception as e:
+ logger.error(f'Failed to update status of subscription: {self.subscriptionName}: {e}',
+ exc_info=True)
+ finally:
+ db.session.remove()
+
def prepare_subscription_event(self, nf, app_conf):
"""Prepare the sub event for publishing
@@ -128,13 +198,14 @@ class Subscription:
dict: the Subscription event to be published.
"""
try:
- clean_sub = {k: v for k, v in self.__dict__.items() if k != 'nfFilter'}
+ clean_sub = {k: v for k, v in self.__dict__.items()
+ if k != 'nfFilter' and k != 'current_filter'}
if self.administrativeState == AdministrativeState.LOCKING.value:
change_type = 'DELETE'
else:
change_type = 'CREATE'
sub_event = {'nfName': nf.nf_name,
- 'ipv4Address': nf.ip_address,
+ 'ipAddress': nf.ip_address,
'blueprintName': nf.sdnc_model_name,
'blueprintVersion': nf.sdnc_model_version,
'policyName': app_conf.operational_policy_name,
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py b/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
index 6238a298..ffe8ef50 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2020-2021 Nordix Foundation.
+# Copyright (C) 2019-2021 Nordix Foundation.
# ============================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,10 +18,11 @@
from jsonschema import ValidationError
from mod import logger, aai_client
+from mod.aai_client import _filter_nf_data, get_pmsh_nfs_from_aai
from mod.aai_event_handler import process_aai_events
from mod.network_function import NetworkFunctionFilter
from mod.pmsh_utils import PeriodicTask
-from mod.subscription import AdministrativeState
+from mod.subscription import AdministrativeState, Subscription, get_nfs_for_creation_and_deletion
class SubscriptionHandler:
@@ -45,12 +46,8 @@ class SubscriptionHandler:
else:
self.app_conf.refresh_config()
self.app_conf.validate_sub_schema()
- new_administrative_state = self.app_conf.subscription.administrativeState
- if local_admin_state == new_administrative_state:
- logger.info(f'Administrative State did not change in the app config: '
- f'{new_administrative_state}')
- else:
- self._check_state_change(local_admin_state, new_administrative_state)
+ local_admin_state = self.apply_subscription_changes()
+ self.compare_admin_state(local_admin_state)
except (ValidationError, TypeError) as err:
logger.error(f'Error occurred during validation of subscription schema {err}',
exc_info=True)
@@ -58,6 +55,56 @@ class SubscriptionHandler:
logger.error(f'Error occurred during the activation/deactivation process {err}',
exc_info=True)
+ def apply_subscription_changes(self):
+ """ Applies changes to subscription
+
+ Args:
+ local_admin_state(enum): The local adminstrative state
+
+ Returns:
+ Enum: Updated administrative state
+ """
+ local_admin_state = self.app_conf.subscription.get_local_sub_admin_state()
+ if local_admin_state == AdministrativeState.FILTERING.value:
+ existing_nfs = self.app_conf.subscription.get_network_functions()
+ self.app_conf.nf_filter = \
+ NetworkFunctionFilter(**self.app_conf.subscription.nfFilter)
+ new_nfs = get_pmsh_nfs_from_aai(self.app_conf)
+ self.app_conf.subscription.update_subscription_filter()
+ get_nfs_for_creation_and_deletion(existing_nfs, new_nfs, 'delete',
+ self.mr_pub, self.app_conf)
+ get_nfs_for_creation_and_deletion(existing_nfs, new_nfs, 'create',
+ self.mr_pub, self.app_conf)
+
+ return local_admin_state
+
+ def compare_admin_state(self, local_admin_state):
+ """ Check for changes in administrative state
+
+ Args:
+ local_admin_state(enum):
+
+ """
+ new_administrative_state = self.app_conf.subscription.administrativeState
+ if local_admin_state == new_administrative_state:
+ logger.info(f'Administrative State did not change in the app config: '
+ f'{new_administrative_state}')
+ else:
+ self._check_state_change(local_admin_state, new_administrative_state)
+
+ def fetch_aai_nf_data(self):
+ """ Fetchs AAI data
+
+ Returns:
+ dict: the json response from AAI query after filter is applied
+ """
+ aai_nf_data = aai_client._get_all_aai_nf_data(self.app_conf)
+ if aai_nf_data:
+ new_nfs = _filter_nf_data(aai_nf_data, self.app_conf)
+ else:
+ raise RuntimeError('Failed to get data from AAI')
+ return new_nfs
+
def _check_state_change(self, local_admin_state, new_administrative_state):
if new_administrative_state == AdministrativeState.UNLOCKED.value:
logger.info(f'Administrative State has changed from {local_admin_state} '
diff --git a/components/pm-subscription-handler/pom.xml b/components/pm-subscription-handler/pom.xml
index fbf44977..9f92d902 100644
--- a/components/pm-subscription-handler/pom.xml
+++ b/components/pm-subscription-handler/pom.xml
@@ -32,7 +32,7 @@
<groupId>org.onap.dcaegen2.services</groupId>
<artifactId>pmsh</artifactId>
<name>dcaegen2-services-pm-subscription-handler</name>
- <version>1.3.1-SNAPSHOT</version>
+ <version>1.4.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.sources>.</sonar.sources>
diff --git a/components/pm-subscription-handler/setup.py b/components/pm-subscription-handler/setup.py
index c11d1330..9270c5b3 100644
--- a/components/pm-subscription-handler/setup.py
+++ b/components/pm-subscription-handler/setup.py
@@ -21,7 +21,7 @@ from setuptools import setup, find_packages
setup(
name="pm_subscription_handler",
- version="1.3.1",
+ version="1.4.0",
packages=find_packages(),
author="lego@est.tech",
author_email="lego@est.tech",
diff --git a/components/pm-subscription-handler/tests/data/pm_subscription_event.json b/components/pm-subscription-handler/tests/data/pm_subscription_event.json
index cd547d9d..a3a6ce3d 100755
--- a/components/pm-subscription-handler/tests/data/pm_subscription_event.json
+++ b/components/pm-subscription-handler/tests/data/pm_subscription_event.json
@@ -5,7 +5,7 @@
"policyName":"pmsh-operational-policy",
"changeType":"CREATE",
"closedLoopControlName":"pmsh-control-loop",
- "ipv4Address": "1.2.3.4",
+ "ipAddress": "1.2.3.4",
"subscription":{
"subscriptionName":"ExtraPM-All-gNB-R2B",
"administrativeState":"UNLOCKED",
diff --git a/components/pm-subscription-handler/tests/test_policy_response_handler.py b/components/pm-subscription-handler/tests/test_policy_response_handler.py
index 26a06fce..e678d839 100644
--- a/components/pm-subscription-handler/tests/test_policy_response_handler.py
+++ b/components/pm-subscription-handler/tests/test_policy_response_handler.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2019-2020 Nordix Foundation.
+# Copyright (C) 2019-2021 Nordix Foundation.
# ============================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
from unittest.mock import patch
from mod.api.db_models import SubscriptionModel
-from mod.network_function import NetworkFunction
+from mod.network_function import NetworkFunction, NetworkFunctionFilter
from mod.policy_response_handler import PolicyResponseHandler, policy_response_handle_functions
from mod.subscription import AdministrativeState, SubNfState
from tests.base_setup import BaseClassSetup
@@ -39,6 +39,20 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.policy_response_handler = PolicyResponseHandler(self.mock_policy_mr_sub,
self.app_conf,
mock_app)
+ self.nfFilter = NetworkFunctionFilter(**{
+ "nfNames": [
+ "^pnf.*"
+ ],
+ "modelInvariantIDs": [
+
+ ],
+ "modelVersionIDs": [
+
+ ],
+ "modelNames": [
+
+ ]
+ })
def tearDown(self):
super().tearDown()
@@ -54,7 +68,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.policy_response_handler._handle_response(
self.app_conf.subscription.subscriptionName,
AdministrativeState.LOCKED.value,
- self.nf.nf_name, 'success')
+ self.nf.nf_name, 'success', 'DELETED')
mock_delete.assert_called()
@@ -65,7 +79,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.policy_response_handler._handle_response(
self.app_conf.subscription.subscriptionName,
AdministrativeState.LOCKED.value,
- self.nf.nf_name, 'failed')
+ self.nf.nf_name, 'failed','DELETE_FAILED')
mock_update_sub_nf.assert_called_with(
subscription_name=self.app_conf.subscription.subscriptionName,
status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name)
@@ -77,7 +91,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.policy_response_handler._handle_response(
self.app_conf.subscription.subscriptionName,
AdministrativeState.UNLOCKED.value,
- self.nf.nf_name, 'success')
+ self.nf.nf_name, 'success', 'CREATED')
mock_update_sub_nf.assert_called_with(
subscription_name=self.app_conf.subscription.subscriptionName,
status=SubNfState.CREATED.value, nf_name=self.nf.nf_name)
@@ -89,7 +103,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.policy_response_handler._handle_response(
self.app_conf.subscription.subscriptionName,
AdministrativeState.UNLOCKED.value,
- self.nf.nf_name, 'failed')
+ self.nf.nf_name, 'failed', 'CREATE_FAILED')
mock_update_sub_nf.assert_called_with(
subscription_name=self.app_conf.subscription.subscriptionName,
status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name)
@@ -102,15 +116,17 @@ class PolicyResponseHandlerTest(BaseClassSetup):
@patch('mod.subscription.Subscription.get')
def test_poll_policy_topic_calls_methods_correct_sub(self, mock_get_sub, mock_handle_response):
response_data = ['{"name": "ResponseEvent","status": { "subscriptionName": '
- '"ExtraPM-All-gNB-R2B", "nfName": "pnf300", "message": "success" } }']
+ '"ExtraPM-All-gNB-R2B", "nfName": "pnf300", "message": "success", "changeType": "CREATED" } }']
self.mock_policy_mr_sub.get_from_topic.return_value = response_data
- mock_get_sub.return_value = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
- status=AdministrativeState.UNLOCKED.value)
+ mock_get_sub.return_value = \
+ SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
+ nfFilter=self.nfFilter,
+ status=AdministrativeState.UNLOCKED.value)
self.policy_response_handler.poll_policy_topic()
self.mock_policy_mr_sub.get_from_topic.assert_called()
mock_handle_response.assert_called_with(self.app_conf.subscription.subscriptionName,
AdministrativeState.UNLOCKED.value, 'pnf300',
- 'success')
+ 'success', "CREATED")
@patch('mod.policy_response_handler.PolicyResponseHandler._handle_response')
@patch('mod.subscription.Subscription.get')
@@ -119,8 +135,10 @@ class PolicyResponseHandlerTest(BaseClassSetup):
response_data = ['{"name": "ResponseEvent","status": { "subscriptionName": '
'"Different_Subscription", "nfName": "pnf300", "message": "success" } }']
self.mock_policy_mr_sub.get_from_topic.return_value = response_data
- mock_get_sub.return_value = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
- status=AdministrativeState.UNLOCKED.value)
+ mock_get_sub.return_value = \
+ SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
+ nfFilter=self.nfFilter,
+ status=AdministrativeState.UNLOCKED.value)
self.policy_response_handler.poll_policy_topic()
self.mock_policy_mr_sub.get_from_topic.assert_called()
@@ -131,7 +149,9 @@ class PolicyResponseHandlerTest(BaseClassSetup):
@patch('mod.subscription.Subscription.get')
def test_poll_policy_topic_exception(self, mock_get_sub, mock_logger):
self.mock_policy_mr_sub.get_from_topic.return_value = 'wrong_return'
- mock_get_sub.return_value = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
- status=AdministrativeState.UNLOCKED.value)
+ mock_get_sub.return_value = \
+ SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
+ nfFilter=self.nfFilter,
+ status=AdministrativeState.UNLOCKED.value)
self.policy_response_handler.poll_policy_topic()
mock_logger.assert_called()
diff --git a/components/pm-subscription-handler/tests/test_subscription.py b/components/pm-subscription-handler/tests/test_subscription.py
index b18f41e8..16c9e509 100755
--- a/components/pm-subscription-handler/tests/test_subscription.py
+++ b/components/pm-subscription-handler/tests/test_subscription.py
@@ -19,6 +19,7 @@ import json
import os
from unittest.mock import patch, Mock
+from pmsh_service.mod.network_function import NetworkFunctionFilter
from requests import Session
import mod.aai_client as aai_client
@@ -43,6 +44,9 @@ class SubscriptionTest(BaseClassSetup):
mock_session_put.return_value.text = self.aai_response_data
with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data:
self.aai_model_data = data.read()
+ with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
+ self.cbs_data = json.load(data)
+ self.nfFilter = NetworkFunctionFilter(**self.cbs_data['config']['pmsh_policy']['subscription']['nfFilter'])
mock_session_get.return_value.status_code = 200
mock_session_get.return_value.text = self.aai_model_data
self.mock_mr_sub = Mock()
@@ -156,3 +160,23 @@ class SubscriptionTest(BaseClassSetup):
self.assertEqual(3, len(nfs))
self.assertIsInstance(nfs[0], NetworkFunction)
+
+ def test_filter_diff_with_difference(self):
+ print(self.nfFilter)
+ networkFunction = '{"nfNames":["^pnf.*","^vnf.*"],"modelInvariantIDs": ["Extra Data"],"modelVersionIDs": ["Extra Data"],"modelNames": ["Extra Data""]}'
+ self.assertTrue(self.app_conf.subscription._filter_diff(networkFunction));
+
+ def test_filter_diff_without_difference(self):
+ networkFunction = '{"nfNames":["^pnf.*","^vnf.*"],"modelInvariantIDs": [],"modelVersionIDs": [],"modelNames": []}'
+ self.assertTrue(self.app_conf.subscription._filter_diff(networkFunction));
+ self.assertIsNotNone(self.app_conf.subscription)
+
+ def test_update_subscription_filter(self):
+ original_filter = self.app_conf.subscription.nfFilter
+ self.app_conf.subscription.nfFilter = '{"nfNames":["^pnf.*","^vnf.*"],"modelInvariantIDs": ["Extra Data"],"modelVersionIDs": ["Extra Data"],"modelNames": ["Extra Data""]}'
+ self.app_conf.subscription.update_subscription_filter()
+ updated_subscription = (self.app_conf.subscription.get())
+ self.assertTrue(updated_subscription.nfFilter == self.app_conf.subscription.nfFilter)
+ self.assertFalse(updated_subscription == original_filter)
+ print(self.app_conf.subscription.get_network_functions())
+
diff --git a/components/pm-subscription-handler/version.properties b/components/pm-subscription-handler/version.properties
index fee49286..9e0d73d4 100644
--- a/components/pm-subscription-handler/version.properties
+++ b/components/pm-subscription-handler/version.properties
@@ -1,6 +1,6 @@
major=1
-minor=3
-patch=1
+minor=4
+patch=0
base_version=${major}.${minor}.${patch}
release_version=${base_version}
snapshot_version=${base_version}-SNAPSHOT