summaryrefslogtreecommitdiffstats
path: root/components/pm-subscription-handler
diff options
context:
space:
mode:
authorSagarS <sagar.shetty@est.tech>2022-02-24 17:07:01 +0000
committerSagarS <sagar.shetty@est.tech>2022-03-02 13:47:51 +0000
commit5f69c24ad78121a2840b5299583791e557f8b535 (patch)
tree22e84dc45427065d7bfa35e2ee0dcc80311a0753 /components/pm-subscription-handler
parent37762006756658532012d9b8e4286e80acb612c4 (diff)
[PMSH] Update Filter API
Issue-ID: DCAEGEN2-2922 Change-Id: Ibf0ef167642027429b3ba91daea60228cf5fa4c6 Signed-off-by: SagarS <sagar.shetty@est.tech>
Diffstat (limited to 'components/pm-subscription-handler')
-rwxr-xr-xcomponents/pm-subscription-handler/Changelog.md4
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/api/controller.py33
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml31
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py33
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/services/nf_service.py21
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py226
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py23
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/subscription.py3
-rw-r--r--components/pm-subscription-handler/pom.xml2
-rw-r--r--components/pm-subscription-handler/setup.py5
-rw-r--r--components/pm-subscription-handler/tests/data/create_subscription_request.json3
-rw-r--r--components/pm-subscription-handler/tests/services/test_measurement_group_service.py45
-rw-r--r--components/pm-subscription-handler/tests/services/test_subscription_service.py179
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_controller.py32
-rw-r--r--components/pm-subscription-handler/tests/test_policy_response_handler.py71
-rw-r--r--components/pm-subscription-handler/version.properties4
16 files changed, 650 insertions, 65 deletions
diff --git a/components/pm-subscription-handler/Changelog.md b/components/pm-subscription-handler/Changelog.md
index d002f229..00e97783 100755
--- a/components/pm-subscription-handler/Changelog.md
+++ b/components/pm-subscription-handler/Changelog.md
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
+## [2.2.0]
+### Changed
+* Update Filter API (DCAEGEN2-2922)
+
## [2.1.1]
### Changed
* Fixes for Flask, MarkupSafe versions + tox (DCAEGEN2-3086)
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/controller.py b/components/pm-subscription-handler/pmsh_service/mod/api/controller.py
index de3aa5f3..57d3e021 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/api/controller.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/controller.py
@@ -267,3 +267,36 @@ def update_admin_state(subscription_name, measurement_group_name, body):
f' due to Exception : {exception}', HTTPStatus.INTERNAL_SERVER_ERROR
return response
+
+
+def put_nf_filter(subscription_name, body):
+ """
+ Performs network function filter update for the respective subscription
+
+ Args:
+ subscription_name (String): Name of the subscription.
+ body (dict): Request body with nf filter data to update.
+ Returns:
+ string, HTTPStatus: Successfully updated network function Filter, 200
+ string, HTTPStatus: Invalid request details, 400
+ string, HTTPStatus: Cannot update as Locked/Filtering request is in progress, 409
+ string, HTTPStatus: Exception details of server failure, 500
+ """
+ logger.info('Performing network function filter update for subscription '
+ f'with sub name: {subscription_name} ')
+ response = 'Successfully updated network function Filter', HTTPStatus.OK.value
+ try:
+ subscription_service.update_filter(subscription_name, body)
+ except InvalidDataException as exception:
+ logger.error(exception.args[0])
+ response = exception.args[0], HTTPStatus.BAD_REQUEST.value
+ except DataConflictException as exception:
+ logger.error(exception.args[0])
+ response = exception.args[0], HTTPStatus.CONFLICT.value
+ except Exception as exception:
+ logger.error('Update nf filter request was not processed for sub name: '
+ f'{subscription_name} due to Exception : {exception}')
+ response = 'Update nf filter request was not processed for sub name: ' \
+ f'{subscription_name} due to Exception : {exception}', \
+ HTTPStatus.INTERNAL_SERVER_ERROR
+ return response
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml b/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml
index 274e0ebb..1f24f171 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml
@@ -131,6 +131,33 @@ paths:
500:
description: Exception occurred on the server
+ /subscription/{subscription_name}/nfFilter:
+ put:
+ tags:
+ - "Subscription"
+ description: >-
+ Update a Subscription nf filter
+ operationId: mod.api.controller.put_nf_filter
+ parameters:
+ - name: subscription_name
+ in: path
+ required: true
+ description: The name of the subscription to update nf filters
+ type: string
+ - in: "body"
+ name: "body"
+ required: true
+ schema:
+ $ref: "#/definitions/nfFilter"
+ responses:
+ 201:
+ description: Successfully updated nf filter
+ 409:
+ description: Conflicting data
+ 400:
+ description: Invalid input
+ 500:
+ description: Exception occurred while querying database
/subscription/{subscription_name}/measurementGroups/{measurement_group_name}:
get:
@@ -162,9 +189,9 @@ paths:
delete:
description: Delete a measurement group
- operationId: mod.api.controller.delete_meas_group
+ operationId: mod.api.controller.delete_meas_group_by_name
tags:
- - "measurement group"
+ - "Measurement Group"
parameters:
- name : subscription_name
in: path
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py b/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py
index b272e5b8..07d1b642 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py
@@ -24,6 +24,7 @@ from mod.api.services import nf_service, subscription_service
from mod.network_function import NetworkFunction
from mod.pmsh_config import MRTopic, AppConfig
from mod.subscription import AdministrativeState, SubNfState
+from sqlalchemy import or_
def save_measurement_group(measurement_group, subscription_name):
@@ -318,3 +319,35 @@ def update_admin_status(measurement_group, status):
deactivate_nfs(sub_model, measurement_group, nf_meas_relations)
elif status == AdministrativeState.UNLOCKED.value:
activate_nfs(sub_model, measurement_group)
+
+
+def filter_nf_to_meas_grp(nf_name, measurement_group_name, status):
+ """ Performs successful status update for a nf under filter update
+ request for a particular subscription and measurement group
+
+ Args:
+ nf_name (string): The network function name
+ measurement_group_name (string): Measurement group name
+ status (string): status of the network function for measurement group
+ """
+ try:
+ if status == SubNfState.DELETED.value:
+ delete_nf_to_measurement_group(nf_name, measurement_group_name,
+ SubNfState.DELETED.value)
+ elif status == SubNfState.CREATED.value:
+ update_measurement_group_nf_status(measurement_group_name,
+ SubNfState.CREATED.value, nf_name)
+ nf_measurement_group_rels = NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == measurement_group_name,
+ or_(NfMeasureGroupRelationalModel.nf_measure_grp_status.like('PENDING_%'),
+ NfMeasureGroupRelationalModel.nf_measure_grp_status.like('%_FAILED'))
+ ).all()
+ if not nf_measurement_group_rels:
+ MeasurementGroupModel.query.filter(
+ MeasurementGroupModel.measurement_group_name == measurement_group_name). \
+ update({MeasurementGroupModel.administrative_state: AdministrativeState.
+ UNLOCKED.value}, synchronize_session='evaluate')
+ db.session.commit()
+ except Exception as e:
+ logger.error('Failed update filter response for measurement group name: '
+ f'{measurement_group_name}, nf name: {nf_name} due to: {e}')
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/services/nf_service.py b/components/pm-subscription-handler/pmsh_service/mod/api/services/nf_service.py
index ce463ed0..a3c2a036 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/api/services/nf_service.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/services/nf_service.py
@@ -17,7 +17,7 @@
# ============LICENSE_END=====================================================
from mod import db, aai_client, logger
-from mod.api.db_models import NetworkFunctionModel
+from mod.api.db_models import NetworkFunctionModel, NetworkFunctionFilterModel
from mod.pmsh_config import AppConfig
from mod.network_function import NetworkFunctionFilter
@@ -74,3 +74,22 @@ def save_nf(nf):
sdnc_model_name=nf.sdnc_model_name,
sdnc_model_version=nf.sdnc_model_version)
db.session.add(network_function)
+
+
+def save_nf_filter_update(sub_name, nf_filter):
+ """
+ Updates the network function filter for the subscription in the db
+
+ Args:
+ sub_name (String): Name of the Subscription
+ nf_filter (dict): filter object to update in the subscription
+ """
+ NetworkFunctionFilterModel.query.filter(
+ NetworkFunctionFilterModel.subscription_name == sub_name). \
+ update({NetworkFunctionFilterModel.nf_names: nf_filter['nfNames'],
+ NetworkFunctionFilterModel.model_invariant_ids: nf_filter['modelInvariantIDs'],
+ NetworkFunctionFilterModel.model_version_ids: nf_filter['modelVersionIDs'],
+ NetworkFunctionFilterModel.model_names: nf_filter['modelNames']},
+ synchronize_session='evaluate')
+ db.session.commit()
+ logger.info(f'Successfully saved filter for subscription: {sub_name}')
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py b/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py
index 338ab89e..032fc4a0 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py
@@ -18,9 +18,11 @@
from mod import db, logger
from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, \
- NetworkFunctionFilterModel, NetworkFunctionModel, MeasurementGroupModel
+ NetworkFunctionFilterModel, NetworkFunctionModel, MeasurementGroupModel, \
+ NfMeasureGroupRelationalModel
from mod.api.services import measurement_group_service, nf_service
-from mod.api.custom_exception import InvalidDataException, DuplicateDataException
+from mod.api.custom_exception import InvalidDataException, DuplicateDataException, \
+ DataConflictException
from mod.subscription import AdministrativeState, SubNfState
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import joinedload
@@ -40,32 +42,16 @@ def create_subscription(subscription):
logger.info(f'Initiating create subscription for: {subscription["subscriptionName"]}')
perform_validation(subscription)
try:
- sub_model, measurement_groups = save_subscription_request(subscription)
+ sub_model = save_subscription_request(subscription)
db.session.commit()
logger.info(f'Successfully saved subscription request for: '
f'{subscription["subscriptionName"]}')
filtered_nfs = nf_service.capture_filtered_nfs(sub_model.subscription_name)
- if filtered_nfs:
- logger.info(f'Applying the filtered nfs for subscription: '
- f'{sub_model.subscription_name}')
- save_filtered_nfs(filtered_nfs)
- apply_subscription_to_nfs(filtered_nfs, sub_model.subscription_name)
- unlocked_msmt_groups = apply_measurement_grp_to_nfs(filtered_nfs, measurement_groups)
- db.session.commit()
- if unlocked_msmt_groups:
- publish_measurement_grp_to_nfs(sub_model, filtered_nfs,
- unlocked_msmt_groups)
- else:
- logger.error(f'All measurement groups are locked for subscription: '
- f'{sub_model.subscription_name}, '
- f'please verify/check measurement groups.')
- else:
- logger.error(f'No network functions found for subscription: '
- f'{sub_model.subscription_name}, '
- f'please verify/check NetworkFunctionFilter.')
+ unlocked_mgs = get_unlocked_measurement_grps(sub_model)
+ add_new_filtered_nfs(filtered_nfs, unlocked_mgs, sub_model)
except IntegrityError as e:
db.session.rollback()
- raise DuplicateDataException(f'DB Integrity issue encountered: {e.orig.args[0]}')
+ raise DuplicateDataException(f'DB Integrity issue encountered: {e.orig.args[0]}') from e
except Exception as e:
db.session.rollback()
raise e
@@ -73,6 +59,36 @@ def create_subscription(subscription):
db.session.remove()
+def add_new_filtered_nfs(filtered_nfs, unlocked_mgs, sub_model):
+ """
+ Inserts the filtered nfs in measurement groups of subscription
+
+ Args:
+ filtered_nfs (List[NetworkFunction]): nfs to be inserted
+ unlocked_mgs (List[MeasurementGroupModel]): mgs to be updated with new nfs
+ sub_model (SubscriptionModel): subscription model to update
+ """
+ if filtered_nfs:
+ logger.info(f'Applying the filtered nfs for subscription: '
+ f'{sub_model.subscription_name}')
+ save_filtered_nfs(filtered_nfs)
+ apply_subscription_to_nfs(filtered_nfs, sub_model.subscription_name)
+ db.session.commit()
+ if unlocked_mgs:
+ apply_measurement_grp_to_nfs(filtered_nfs, unlocked_mgs)
+ db.session.commit()
+ publish_measurement_grp_to_nfs(sub_model, filtered_nfs,
+ unlocked_mgs)
+ else:
+ logger.error(f'All measurement groups are locked for subscription: '
+ f'{sub_model.subscription_name}, '
+ f'please verify/check measurement groups.')
+ else:
+ logger.error(f'No network functions found for subscription: '
+ f'{sub_model.subscription_name}, '
+ f'please verify/check NetworkFunctionFilter.')
+
+
def publish_measurement_grp_to_nfs(sub_model, filtered_nfs,
measurement_groups):
"""
@@ -124,32 +140,22 @@ def apply_subscription_to_nfs(filtered_nfs, subscription_name):
db.session.add(new_nf_sub_rel)
-def apply_measurement_grp_to_nfs(filtered_nfs, measurement_groups):
+def apply_measurement_grp_to_nfs(filtered_nfs, unlocked_mgs):
"""
Saves measurement groups against nfs with status as PENDING_CREATE
Args:
filtered_nfs (list[NetworkFunction]): list of filtered network functions
- measurement_groups (list[MeasurementGroupModel]): list of measurement group
+ unlocked_mgs (list[MeasurementGroupModel]): list of measurement group
- Returns:
- list[MeasurementGroupModel]: list of Unlocked measurement groups
"""
- unlocked_msmt_groups = []
- for measurement_group in measurement_groups:
- if measurement_group.administrative_state \
- == AdministrativeState.UNLOCKED.value:
- unlocked_msmt_groups.append(measurement_group)
- for nf in filtered_nfs:
- logger.info(f'Saving measurement group to nf name, measure_grp_name: {nf.nf_name},'
- f'{measurement_group.measurement_group_name}')
- measurement_group_service.apply_nf_status_to_measurement_group(
- nf.nf_name, measurement_group.measurement_group_name,
- SubNfState.PENDING_CREATE.value)
- else:
- logger.info(f'No nfs added as measure_grp_name: '
- f'{measurement_group.measurement_group_name} is LOCKED')
- return unlocked_msmt_groups
+ for measurement_group in unlocked_mgs:
+ for nf in filtered_nfs:
+ logger.info(f'Saving measurement group to nf name, measure_grp_name: {nf.nf_name},'
+ f'{measurement_group.measurement_group_name}')
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ nf.nf_name, measurement_group.measurement_group_name,
+ SubNfState.PENDING_CREATE.value)
def check_missing_data(subscription):
@@ -217,7 +223,7 @@ def save_subscription_request(subscription):
measurement_group_service.save_measurement_group(
measurement_group['measurementGroup'],
subscription["subscriptionName"]))
- return sub_model, measurement_groups
+ return sub_model
def check_duplicate_fields(subscription_name):
@@ -380,3 +386,139 @@ def query_to_delete_subscription_by_name(subscription_name):
.filter_by(subscription_name=subscription_name).delete()
db.session.commit()
return effected_rows
+
+
+def is_duplicate_filter(nf_filter, db_network_filter):
+ """
+ Checks if the network function filter is unchanged for the subscription
+
+ Args:
+ nf_filter (dict): filter object to update in the subscription
+ db_network_filter (NetworkFunctionFilterModel): nf filter object from db
+
+ Returns:
+ (boolean) : True is nf filters are same else False
+ """
+ return nf_filter == db_network_filter.serialize()
+
+
+def update_filter(sub_name, nf_filter):
+ """
+ Updates the network function filter for the subscription
+
+ Args:
+ sub_name (String): Name of the Subscription
+ nf_filter (dict): filter object to update in the subscription
+
+ Returns:
+ InvalidDataException: contains details on invalid fields
+ DataConflictException: contains details on conflicting state of a field
+ Exception: contains runtime error details
+ """
+ sub_model = query_subscription_by_name(sub_name)
+ if sub_model is None:
+ raise InvalidDataException('Requested subscription is not available '
+ f'with sub name: {sub_name} for nf filter update')
+ if is_duplicate_filter(nf_filter, sub_model.network_filter):
+ raise InvalidDataException('Duplicate nf filter update requested for subscription '
+ f'with sub name: {sub_name}')
+ validate_sub_mgs_state(sub_model)
+ nf_service.save_nf_filter_update(sub_name, nf_filter)
+ del_nfs, new_nfs = extract_del_new_nfs(sub_model)
+ NfSubRelationalModel.query.filter(
+ NfSubRelationalModel.subscription_name == sub_name,
+ NfSubRelationalModel.nf_name.in_(del_nfs)).delete()
+ db.session.commit()
+ unlocked_mgs = get_unlocked_measurement_grps(sub_model)
+ if unlocked_mgs:
+ add_new_filtered_nfs(new_nfs, unlocked_mgs, sub_model)
+ delete_filtered_nfs(del_nfs, sub_model, unlocked_mgs)
+ db.session.remove()
+
+
+def get_unlocked_measurement_grps(sub_model):
+ """
+ Gets unlocked measurement groups and logs locked measurement groups
+
+ Args:
+ sub_model (SubscriptionModel): Subscription model to perform nfs delete
+
+ Returns:
+ unlocked_mgs (List[MeasurementGroupModel]): unlocked msgs in a subscription
+
+ """
+ unlocked_mgs = []
+ for measurement_group in sub_model.measurement_groups:
+ if measurement_group.administrative_state \
+ == AdministrativeState.UNLOCKED.value:
+ unlocked_mgs.append(measurement_group)
+ else:
+ logger.info(f'No nfs added as measure_grp_name: '
+ f'{measurement_group.measurement_group_name} is LOCKED')
+ return unlocked_mgs
+
+
+def delete_filtered_nfs(del_nfs, sub_model, unlocked_mgs):
+ """
+ Removes unfiltered nfs
+
+ Args:
+ del_nfs (List[String]): Names of nfs to be deleted
+ sub_model (SubscriptionModel): Subscription model to perform nfs delete
+ unlocked_mgs (List[MeasurementGroupModel]): unlocked msgs to perform nfs delete
+
+ """
+ if del_nfs:
+ logger.info(f'Removing nfs from subscription: '
+ f'{sub_model.subscription_name}')
+ for mg in unlocked_mgs:
+ MeasurementGroupModel.query.filter(
+ MeasurementGroupModel.measurement_group_name == mg.measurement_group_name) \
+ .update({MeasurementGroupModel.administrative_state: AdministrativeState.
+ FILTERING.value}, synchronize_session='evaluate')
+ db.session.commit()
+ nf_meas_relations = NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == mg.
+ measurement_group_name, NfMeasureGroupRelationalModel.
+ nf_name.in_(del_nfs)).all()
+ measurement_group_service.deactivate_nfs(sub_model, mg, nf_meas_relations)
+
+
+def extract_del_new_nfs(sub_model):
+ """
+ Captures nfs to be deleted and created for the subscription
+
+ Args:
+ sub_model (SubscriptionModel): Subscription model to perform nfs delete
+
+ Returns:
+ del_nfs (List[String]): Names of nfs to be deleted
+ new_nfs (List[NetworkFunction]): nfs to be inserted
+ """
+ filtered_nfs = nf_service.capture_filtered_nfs(sub_model.subscription_name)
+ filtered_nf_names = [nf.nf_name for nf in filtered_nfs]
+ existing_nf_names = [nf.nf_name for nf in sub_model.nfs]
+ new_nfs = list(filter(lambda x: x.nf_name not in existing_nf_names, filtered_nfs))
+ del_nfs = [nf.nf_name for nf in sub_model.nfs if nf.nf_name not in filtered_nf_names]
+ return del_nfs, new_nfs
+
+
+def validate_sub_mgs_state(sub_model):
+ """
+ Validates if any measurement group in subscription has
+ status Locking or Filtering
+
+ Args:
+ sub_model (SubscriptionModel): Subscription model to perform validation before nf filter
+
+ Returns:
+ DataConflictException: contains details on conflicting status in measurement group
+ """
+ mg_names_processing = [mg for mg in sub_model.measurement_groups
+ if mg.administrative_state in [AdministrativeState.FILTERING.value,
+ AdministrativeState.LOCKING.value]]
+ if mg_names_processing:
+ raise DataConflictException('Cannot update filter as subscription: '
+ f'{sub_model.subscription_name} is under '
+ 'transitioning state for the following measurement '
+ f'groups: {mg_names_processing}')
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 a0a7bd67..5065ce8a 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
@@ -18,8 +18,8 @@
import json
from mod.pmsh_config import MRTopic, AppConfig
from mod import logger
-from mod.subscription import AdministrativeState, subscription_nf_states
-from mod.api.db_models import MeasurementGroupModel
+from mod.subscription import AdministrativeState, subscription_nf_states, SubNfState
+from mod.api.db_models import MeasurementGroupModel, NfMeasureGroupRelationalModel
from mod.api.services import measurement_group_service
policy_response_handle_functions = {
@@ -34,6 +34,10 @@ policy_response_handle_functions = {
AdministrativeState.LOCKING.value: {
'success': measurement_group_service.lock_nf_to_meas_grp,
'failed': measurement_group_service.update_measurement_group_nf_status
+ },
+ AdministrativeState.FILTERING.value: {
+ 'success': measurement_group_service.filter_nf_to_meas_grp,
+ 'failed': measurement_group_service.update_measurement_group_nf_status
}
}
@@ -86,8 +90,19 @@ class PolicyResponseHandler:
logger.info(f'Response from MR: measurement group name: {measurement_group_name} for '
f'NF: {nf_name} received, updating the DB')
try:
- nf_measure_grp_status = subscription_nf_states[administrative_state][response_message]\
- .value
+
+ if administrative_state == AdministrativeState.FILTERING.value:
+ nf_msg_rel = NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == measurement_group_name,
+ NfMeasureGroupRelationalModel.nf_name == nf_name
+ ).one_or_none()
+ if nf_msg_rel.nf_measure_grp_status == SubNfState.PENDING_DELETE.value:
+ administrative_state = AdministrativeState.LOCKING.value
+ elif nf_msg_rel.nf_measure_grp_status == SubNfState.PENDING_CREATE.value:
+ administrative_state = AdministrativeState.UNLOCKED.value
+
+ nf_measure_grp_status = (subscription_nf_states[administrative_state]
+ [response_message]).value
policy_response_handle_functions[administrative_state][response_message](
measurement_group_name=measurement_group_name, status=nf_measure_grp_status,
nf_name=nf_name)
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription.py b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
index 603343f0..ddb6e1f5 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2019-2021 Nordix Foundation.
+# Copyright (C) 2019-2022 Nordix Foundation.
# ============================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ class AdministrativeState(Enum):
UNLOCKED = 'UNLOCKED'
LOCKING = 'LOCKING'
LOCKED = 'LOCKED'
+ FILTERING = 'FILTERING'
subscription_nf_states = {
diff --git a/components/pm-subscription-handler/pom.xml b/components/pm-subscription-handler/pom.xml
index 815b2f16..88ae50d5 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>2.1.1-SNAPSHOT</version>
+ <version>2.2.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 ba1b74b9..a4a80efb 100644
--- a/components/pm-subscription-handler/setup.py
+++ b/components/pm-subscription-handler/setup.py
@@ -22,7 +22,7 @@ from setuptools import setup, find_packages
setup(
name="pm_subscription_handler",
- version="2.1.1",
+ version="2.2.0",
packages=find_packages(),
author="lego@est.tech",
author_email="lego@est.tech",
@@ -43,5 +43,6 @@ setup(
"onap_dcae_cbs_docker_client==2.2.1",
"onappylog==1.0.9",
"ruamel.yaml==0.16.10",
- "jsonschema==3.2.0"]
+ "jsonschema==3.2.0",
+ "pyyaml==5.4.1"]
)
diff --git a/components/pm-subscription-handler/tests/data/create_subscription_request.json b/components/pm-subscription-handler/tests/data/create_subscription_request.json
index bc089a9a..74c09374 100644
--- a/components/pm-subscription-handler/tests/data/create_subscription_request.json
+++ b/components/pm-subscription-handler/tests/data/create_subscription_request.json
@@ -10,7 +10,8 @@
],
"modelInvariantIDs": [
"8lk4578-d396-4efb-af02-6b83499b12f8",
- "687kj45-d396-4efb-af02-6b83499b12f8"
+ "687kj45-d396-4efb-af02-6b83499b12f8",
+ "597b524-d396-4efb-af02-6b83499b12f8"
],
"modelVersionIDs": [
diff --git a/components/pm-subscription-handler/tests/services/test_measurement_group_service.py b/components/pm-subscription-handler/tests/services/test_measurement_group_service.py
index f656513e..1dbe84a9 100644
--- a/components/pm-subscription-handler/tests/services/test_measurement_group_service.py
+++ b/components/pm-subscription-handler/tests/services/test_measurement_group_service.py
@@ -358,3 +358,48 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
self.assertEqual(meas_grp.subscription_name, 'sub')
self.assertEqual(meas_grp.measurement_group_name, 'MG2')
self.assertEqual(meas_grp.administrative_state, 'LOCKING')
+
+ def test_filter_nf_to_meas_grp_for_delete(self):
+ sub = create_subscription_data('sub')
+ db.session.add(sub)
+ nf = NetworkFunction(nf_name='pnf_test2')
+ nf_service.save_nf(nf)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ "pnf_test2", "MG2", SubNfState.PENDING_DELETE.value)
+ db.session.commit()
+ measurement_group_service.filter_nf_to_meas_grp(
+ "pnf_test2", "MG2", SubNfState.DELETED.value)
+ measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2',
+ NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNone(measurement_grp_rel)
+ network_function = (NetworkFunctionModel.query.filter(
+ NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNone(network_function)
+ meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG2')
+ self.assertEqual(meas_grp.subscription_name, 'sub')
+ self.assertEqual(meas_grp.measurement_group_name, 'MG2')
+ self.assertEqual(meas_grp.administrative_state, 'UNLOCKED')
+
+ def test_filter_nf_to_meas_grp_for_create(self):
+ sub = create_subscription_data('sub')
+ db.session.add(sub)
+ nf = NetworkFunction(nf_name='pnf_test2')
+ nf_service.save_nf(nf)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ "pnf_test2", "MG2", SubNfState.PENDING_CREATE.value)
+ db.session.commit()
+ measurement_group_service.filter_nf_to_meas_grp(
+ "pnf_test2", "MG2", SubNfState.CREATED.value)
+ measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2',
+ NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNotNone(measurement_grp_rel)
+ self.assertEqual(measurement_grp_rel.nf_measure_grp_status, 'CREATED')
+ network_function = (NetworkFunctionModel.query.filter(
+ NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNotNone(network_function)
+ meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG2')
+ self.assertEqual(meas_grp.subscription_name, 'sub')
+ self.assertEqual(meas_grp.measurement_group_name, 'MG2')
+ self.assertEqual(meas_grp.administrative_state, 'UNLOCKED')
diff --git a/components/pm-subscription-handler/tests/services/test_subscription_service.py b/components/pm-subscription-handler/tests/services/test_subscription_service.py
index 807806f8..a0f3297c 100644
--- a/components/pm-subscription-handler/tests/services/test_subscription_service.py
+++ b/components/pm-subscription-handler/tests/services/test_subscription_service.py
@@ -21,13 +21,14 @@ import os
from unittest.mock import patch, MagicMock
from mod.api.db_models import SubscriptionModel, MeasurementGroupModel, \
NfMeasureGroupRelationalModel, NetworkFunctionModel, NfSubRelationalModel, \
- convert_db_string_to_list
+ convert_db_string_to_list, NetworkFunctionFilterModel
from mod.network_function import NetworkFunctionFilter
from mod.subscription import SubNfState
-from mod import aai_client
-from mod.api.custom_exception import DuplicateDataException, InvalidDataException
+from mod import aai_client, db
+from mod.api.custom_exception import DuplicateDataException, InvalidDataException, \
+ DataConflictException
from mod.pmsh_config import AppConfig
-from tests.base_setup import BaseClassSetup
+from tests.base_setup import BaseClassSetup, create_subscription_data
from mod.api.services import subscription_service, nf_service, measurement_group_service
from tests.base_setup import create_multiple_subscription_data
@@ -184,11 +185,10 @@ class SubscriptionServiceTestCase(BaseClassSetup):
'msrmt_grp_name', 'UNLOCKED',
15, 'pm.xml', [], [])
measurement2 = self.create_measurement_grp(measurement_grp, 'meas2', 'UNLOCKED')
- measurement3 = self.create_measurement_grp(measurement_grp, 'meas3', 'LOCKED')
- measurement_grps = [measurement_grp, measurement2, measurement3]
+ unlocked_msgs = [measurement_grp, measurement2]
mock_filter_call.return_value = NetworkFunctionFilter(**subscription["nfFilter"])
filtered_nfs = nf_service.capture_filtered_nfs(subscription["subscriptionName"])
- subscription_service.apply_measurement_grp_to_nfs(filtered_nfs, measurement_grps)
+ subscription_service.apply_measurement_grp_to_nfs(filtered_nfs, unlocked_msgs)
# 2 measurement group with 2 nfs each contribute 4 calls
self.assertEqual(mock_apply_nf.call_count, 4)
@@ -377,3 +377,168 @@ class SubscriptionServiceTestCase(BaseClassSetup):
def test_get_subscriptions_list_empty(self):
subs = subscription_service.get_subscriptions_list()
self.assertEqual(subs, [])
+
+ @patch('mod.api.services.nf_service.save_nf_filter_update')
+ @patch('mod.api.services.subscription_service.is_duplicate_filter',
+ MagicMock(return_value=False))
+ @patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None))
+ @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
+ @patch.object(aai_client, '_get_all_aai_nf_data')
+ @patch.object(aai_client, 'get_aai_model_data')
+ @patch.object(NetworkFunctionFilter, 'get_network_function_filter')
+ def test_update_filter(self, mock_filter_call, mock_model_aai, mock_aai, mock_update_filter):
+ mock_aai.return_value = json.loads(self.aai_response_data)
+ mock_model_aai.return_value = json.loads(self.good_model_info)
+ mock_update_filter.return_value = None
+ subscription = self.create_test_subs('sub_01', 'msg_01')
+ subscription = json.loads(subscription)['subscription']
+ nf_filter = subscription['nfFilter']
+ mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter)
+ subscription_service.create_subscription(subscription)
+ subscription_service.update_filter('sub_01', nf_filter)
+ self.assertTrue(mock_update_filter.called)
+
+ @patch('mod.api.services.nf_service.save_nf_filter_update')
+ @patch('mod.api.services.subscription_service.is_duplicate_filter',
+ MagicMock(return_value=False))
+ @patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None))
+ @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
+ @patch.object(aai_client, '_get_all_aai_nf_data')
+ @patch.object(aai_client, 'get_aai_model_data')
+ @patch.object(NetworkFunctionFilter, 'get_network_function_filter')
+ def test_update_filter_with_new_del_nfs(self, mock_filter_call, mock_model_aai, mock_aai,
+ mock_update_filter):
+ mock_aai.return_value = json.loads(self.aai_response_data)
+ mock_model_aai.return_value = json.loads(self.good_model_info)
+ mock_update_filter.return_value = None
+ subscription = self.create_test_subs('sub_01', 'msg_01')
+ subscription = json.loads(subscription)['subscription']
+ nf_filter = subscription['nfFilter']
+ mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter)
+ subscription_service.create_subscription(subscription)
+ # Check existing network functions
+ meas_group_nfs = db.session.query(NfMeasureGroupRelationalModel).filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == 'msg_01') \
+ .all()
+ self.assertEqual(len(meas_group_nfs), 2)
+ self.assertEqual(meas_group_nfs[0].nf_name, 'pnf201')
+ self.assertEqual(meas_group_nfs[0].nf_measure_grp_status,
+ SubNfState.PENDING_CREATE.value)
+ self.assertEqual(meas_group_nfs[1].nf_name, 'pnf_33_ericsson')
+ self.assertEqual(meas_group_nfs[1].nf_measure_grp_status,
+ SubNfState.PENDING_CREATE.value)
+ meas_grp = measurement_group_service.query_meas_group_by_name('sub_01', 'msg_01')
+ self.assertEqual(meas_grp.administrative_state, 'UNLOCKED')
+ # Creating test data for update filter function
+ aai_response = self.aai_response_data.replace('pnf201', 'xnf111')
+ mock_aai.return_value = json.loads(aai_response)
+ nf_filter['nfNames'] = ["^vnf.*", "^xnf.*"]
+ mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter)
+ subscription_service.update_filter('sub_01', nf_filter)
+ self.assertTrue(mock_update_filter.called)
+ # Check updated network functions after filter change
+ meas_group_nfs = db.session.query(NfMeasureGroupRelationalModel).filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == 'msg_01') \
+ .all()
+ self.assertEqual(meas_group_nfs[0].nf_name, 'pnf201')
+ self.assertEqual(meas_group_nfs[0].nf_measure_grp_status,
+ SubNfState.PENDING_DELETE.value)
+ self.assertEqual(meas_group_nfs[1].nf_name, 'pnf_33_ericsson')
+ self.assertEqual(meas_group_nfs[1].nf_measure_grp_status,
+ SubNfState.PENDING_DELETE.value)
+ self.assertEqual(meas_group_nfs[2].nf_name, 'xnf111')
+ self.assertEqual(meas_group_nfs[2].nf_measure_grp_status,
+ SubNfState.PENDING_CREATE.value)
+ meas_grp = measurement_group_service.query_meas_group_by_name('sub_01', 'msg_01')
+ self.assertEqual(meas_grp.administrative_state, 'FILTERING')
+
+ def test_update_filter_locking(self):
+ sub = create_subscription_data('sub')
+ sub.measurement_groups[1].administrative_state = 'LOCKING'
+ db.session.add(sub)
+ try:
+ subscription_service.update_filter('sub', json.loads('{"nfNames": "^pnf.*"}'))
+ except DataConflictException as conflictEx:
+ self.assertEqual(conflictEx.args[0],
+ 'Cannot update filter as subscription: sub is under transitioning'
+ ' state for the following measurement groups: [subscription_name:'
+ ' sub, measurement_group_name: MG2, administrative_state: LOCKING,'
+ ' file_based_gp: 15, file_location: /pm/pm.xml, measurement_type: '
+ '[{ "measurementType": "countera" }, { "measurementType": '
+ '"counterb" }], managed_object_dns_basic: [{ "DN":"dna"},'
+ '{"DN":"dnb"}]]')
+
+ def test_update_filter_filtering(self):
+ sub = create_subscription_data('sub')
+ sub.measurement_groups[1].administrative_state = 'FILTERING'
+ db.session.add(sub)
+ try:
+ subscription_service.update_filter('sub', json.loads('{"nfNames": "^pnf.*"}'))
+ except DataConflictException as conflictEx:
+ self.assertEqual(conflictEx.args[0],
+ 'Cannot update filter as subscription: sub is under transitioning'
+ ' state for the following measurement groups: [subscription_name:'
+ ' sub, measurement_group_name: MG2, administrative_state: FILTERING,'
+ ' file_based_gp: 15, file_location: /pm/pm.xml, measurement_type: ['
+ '{ "measurementType": "countera" }, { "measurementType": "counterb" '
+ '}], managed_object_dns_basic: [{ "DN":"dna"},{"DN":"dnb"}]]')
+
+ def test_update_filter_invalid_request(self):
+ try:
+ subscription_service.update_filter("sub3", json.loads('{"nfNames": "^pnf.*"}'))
+ except InvalidDataException as invalidEx:
+ self.assertEqual(invalidEx.args[0],
+ "Requested subscription is not available with sub name: sub3 "
+ "for nf filter update")
+
+ @patch('mod.api.services.nf_service.save_nf_filter_update')
+ @patch('mod.api.services.subscription_service.is_duplicate_filter',
+ MagicMock(return_value=True))
+ @patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None))
+ @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
+ @patch.object(aai_client, '_get_all_aai_nf_data')
+ @patch.object(aai_client, 'get_aai_model_data')
+ @patch.object(NetworkFunctionFilter, 'get_network_function_filter')
+ def test_update_filter_invalid_duplicate_request(self, mock_filter_call, mock_model_aai,
+ mock_aai, mock_update_filter):
+ try:
+ mock_aai.return_value = json.loads(self.aai_response_data)
+ mock_model_aai.return_value = json.loads(self.good_model_info)
+ mock_update_filter.return_value = None
+ subscription = self.create_test_subs('sub_01', 'msg_01')
+ subscription = json.loads(subscription)['subscription']
+ nf_filter = subscription['nfFilter']
+ mock_filter_call.return_value = NetworkFunctionFilter(**nf_filter)
+ subscription_service.create_subscription(subscription)
+ subscription_service.update_filter("sub_01", json.loads('{"nfNames": "^pnf.*"}'))
+ except InvalidDataException as invalidEx:
+ self.assertEqual(invalidEx.args[0],
+ "Duplicate nf filter update requested for subscription "
+ "with sub name: sub_01")
+
+ def test_is_duplicate_filter_true(self):
+ subscription = self.create_test_subs('sub_01', 'msg_01')
+ subscription = json.loads(subscription)['subscription']
+ nf_filter = subscription['nfFilter']
+ db_network_filter = NetworkFunctionFilterModel('sub_01',
+ '{^pnf.*,^vnf.*}',
+ '{8lk4578-d396-4efb-af02-6b83499b12f8,'
+ '687kj45-d396-4efb-af02-6b83499b12f8,'
+ '597b524-d396-4efb-af02-6b83499b12f8}',
+ '{e80a6ae3-cafd-4d24-850d-e14c084a5ca9}',
+ '{PNF102}')
+ similar = subscription_service.is_duplicate_filter(nf_filter, db_network_filter)
+ self.assertTrue(similar)
+
+ def test_is_duplicate_filter_false(self):
+ subscription = self.create_test_subs('sub_01', 'msg_01')
+ subscription = json.loads(subscription)['subscription']
+ nf_filter = subscription['nfFilter']
+ db_network_filter = NetworkFunctionFilterModel('sub_01',
+ '{^pnf.*,^vnf.*}',
+ '{8lk4578-d396-4efb-af02-6b83499b12f8,'
+ '687kj45-d396-4efb-af02-6b83499b12f8}',
+ '{e80a6ae3-cafd-4d24-850d-e14c084a5ca9}',
+ '{PNF102}')
+ similar = subscription_service.is_duplicate_filter(nf_filter, db_network_filter)
+ self.assertFalse(similar)
diff --git a/components/pm-subscription-handler/tests/test_controller.py b/components/pm-subscription-handler/tests/test_controller.py
index 42c52c09..7b0a8b19 100755
--- a/components/pm-subscription-handler/tests/test_controller.py
+++ b/components/pm-subscription-handler/tests/test_controller.py
@@ -23,7 +23,7 @@ from http import HTTPStatus
from mod import aai_client, db
from mod.api.controller import status, post_subscription, get_subscription_by_name, \
get_subscriptions, get_meas_group_with_nfs, delete_subscription_by_name, update_admin_state, \
- delete_meas_group_by_name
+ delete_meas_group_by_name, put_nf_filter
from mod.api.services.measurement_group_service import query_meas_group_by_name
from tests.base_setup import BaseClassSetup
from mod.api.custom_exception import InvalidDataException, DataConflictException
@@ -366,3 +366,33 @@ class ControllerTestCase(BaseClassSetup):
self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value)
self.assertEqual(error, 'Update admin status request was not processed for sub name: sub4 '
'and meas group name: MG2 due to Exception : Server Error')
+
+ @patch('mod.api.services.subscription_service.update_filter', MagicMock(return_value=None))
+ def test_put_nf_filter(self):
+ response = put_nf_filter('sub1', json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}'))
+ self.assertEqual(response[0], 'Successfully updated network function Filter')
+ self.assertEqual(response[1], HTTPStatus.OK.value)
+
+ @patch('mod.api.services.subscription_service.update_filter',
+ MagicMock(side_effect=InvalidDataException('Bad request')))
+ def test_put_nf_filter_api_invalid_data_exception(self):
+ error, status_code = put_nf_filter('sub1',
+ json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}'))
+ self.assertEqual(status_code, HTTPStatus.BAD_REQUEST.value)
+ self.assertEqual(error, 'Bad request')
+
+ @patch('mod.api.services.subscription_service.update_filter',
+ MagicMock(side_effect=DataConflictException('Data conflict')))
+ def test_put_nf_filter_api_data_conflict_exception(self):
+ error, status_code = put_nf_filter('sub1',
+ json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}'))
+ self.assertEqual(status_code, HTTPStatus.CONFLICT.value)
+ self.assertEqual(error, 'Data conflict')
+
+ @patch('mod.api.services.subscription_service.update_filter',
+ MagicMock(side_effect=Exception('Server Error')))
+ def test_put_nf_filter_api_exception(self):
+ error, status_code = put_nf_filter('sub1', json.loads('{"nfNames": ["^pnf.*", "^vnf.*"]}'))
+ self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value)
+ self.assertEqual(error, 'Update nf filter request was not processed for sub name: sub1 '
+ 'due to Exception : Server Error')
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 3e6abf94..d5ae5ce1 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-2021 Nordix Foundation.
+# Copyright (C) 2019-2022 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,6 +18,7 @@
from unittest.mock import patch, MagicMock
from mod import db
+from mod.api.services import measurement_group_service
from mod.network_function import NetworkFunction
from mod.policy_response_handler import PolicyResponseHandler, policy_response_handle_functions
from mod.subscription import AdministrativeState, SubNfState
@@ -100,6 +101,40 @@ class PolicyResponseHandlerTest(BaseClassSetup):
status=SubNfState.CREATED.value, nf_name=self.nf.nf_name)
@patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
+ def test_handle_response_unlocked_success_filtering(self, mock_update_sub_nf):
+ with patch.dict(policy_response_handle_functions,
+ {AdministrativeState.UNLOCKED.value: {'success': mock_update_sub_nf}}):
+ sub = create_subscription_data('sub')
+ db.session.add(sub)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ self.nf.nf_name, "MG2", SubNfState.PENDING_CREATE.value)
+ db.session.commit()
+ self.policy_response_handler._handle_response(
+ 'MG2',
+ AdministrativeState.FILTERING.value,
+ self.nf.nf_name, 'success')
+ mock_update_sub_nf.assert_called_with(
+ measurement_group_name='MG2',
+ status=SubNfState.CREATED.value, nf_name=self.nf.nf_name)
+
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
+ def test_handle_response_locking_success_filtering(self, mock_update_sub_nf):
+ with patch.dict(policy_response_handle_functions,
+ {AdministrativeState.LOCKING.value: {'success': mock_update_sub_nf}}):
+ sub = create_subscription_data('sub')
+ db.session.add(sub)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ self.nf.nf_name, "MG2", SubNfState.PENDING_DELETE.value)
+ db.session.commit()
+ self.policy_response_handler._handle_response(
+ 'MG2',
+ AdministrativeState.FILTERING.value,
+ self.nf.nf_name, 'success')
+ mock_update_sub_nf.assert_called_with(
+ measurement_group_name='MG2',
+ status=SubNfState.DELETED.value, nf_name=self.nf.nf_name)
+
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
def test_handle_response_unlocked_failed(self, mock_update_sub_nf):
with patch.dict(policy_response_handle_functions,
{AdministrativeState.UNLOCKED.value: {'failed': mock_update_sub_nf}}):
@@ -111,6 +146,40 @@ class PolicyResponseHandlerTest(BaseClassSetup):
measurement_group_name='msr_grp_name',
status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name)
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
+ def test_handle_response_create_failed_filtering(self, mock_update_sub_nf):
+ with patch.dict(policy_response_handle_functions,
+ {AdministrativeState.UNLOCKED.value: {'failed': mock_update_sub_nf}}):
+ sub = create_subscription_data('sub')
+ db.session.add(sub)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ self.nf.nf_name, "MG2", SubNfState.PENDING_CREATE.value)
+ db.session.commit()
+ self.policy_response_handler._handle_response(
+ 'MG2',
+ AdministrativeState.FILTERING.value,
+ self.nf.nf_name, 'failed')
+ mock_update_sub_nf.assert_called_with(
+ measurement_group_name='MG2',
+ status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name)
+
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
+ def test_handle_response_delete_failed_filtering(self, mock_update_sub_nf):
+ with patch.dict(policy_response_handle_functions,
+ {AdministrativeState.LOCKING.value: {'failed': mock_update_sub_nf}}):
+ sub = create_subscription_data('sub')
+ db.session.add(sub)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ self.nf.nf_name, "MG2", SubNfState.PENDING_DELETE.value)
+ db.session.commit()
+ self.policy_response_handler._handle_response(
+ 'MG2',
+ AdministrativeState.FILTERING.value,
+ self.nf.nf_name, 'failed')
+ mock_update_sub_nf.assert_called_with(
+ measurement_group_name='MG2',
+ status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name)
+
def test_handle_response_exception(self):
self.assertRaises(Exception, self.policy_response_handler._handle_response, 'sub1',
'wrong_state', 'nf1', 'wrong_message')
diff --git a/components/pm-subscription-handler/version.properties b/components/pm-subscription-handler/version.properties
index 3c5fba7f..3ad2137c 100644
--- a/components/pm-subscription-handler/version.properties
+++ b/components/pm-subscription-handler/version.properties
@@ -1,6 +1,6 @@
major=2
-minor=1
-patch=1
+minor=2
+patch=0
base_version=${major}.${minor}.${patch}
release_version=${base_version}
snapshot_version=${base_version}-SNAPSHOT