summaryrefslogtreecommitdiffstats
path: root/components/pm-subscription-handler
diff options
context:
space:
mode:
authorraviteja.karumuri <raviteja.karumuri@est.tech>2022-03-02 17:59:27 +0000
committerraviteja.karumuri <raviteja.karumuri@est.tech>2022-03-03 16:54:04 +0000
commit5a2c43f2add2c6d4af8331a40b174684eac11b34 (patch)
tree4e76bac8e33d80b1e0e9af1fdf2b57fe6a9a7bf2 /components/pm-subscription-handler
parent5f69c24ad78121a2840b5299583791e557f8b535 (diff)
[PMSH] Cleaning up old App Config, subscription handler and it's subsequent calls
Issue-ID: DCAEGEN2-3085 Signed-off-by: Raviteja, Karumuri <raviteja.karumuri@est.tech> Change-Id: I7b862648eebf59844aaa9d09697b7f2a693c9d94
Diffstat (limited to 'components/pm-subscription-handler')
-rwxr-xr-xcomponents/pm-subscription-handler/Changelog.md1
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/__init__.py23
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/aai_client.py53
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/api/controller.py2
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py46
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py4
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/exit_handler.py2
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py34
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py313
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py10
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/subscription.py295
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py118
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/pmsh_service_main.py16
-rwxr-xr-xcomponents/pm-subscription-handler/tests/base_setup.py11
-rw-r--r--components/pm-subscription-handler/tests/data/cbs_data_1.json67
-rw-r--r--components/pm-subscription-handler/tests/data/cbs_invalid_data.json116
-rwxr-xr-xcomponents/pm-subscription-handler/tests/data/pm_subscription_event.json57
-rw-r--r--components/pm-subscription-handler/tests/services/test_measurement_group_service.py88
-rw-r--r--components/pm-subscription-handler/tests/services/test_nf_service.py12
-rw-r--r--components/pm-subscription-handler/tests/services/test_subscription_service.py33
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_aai_event_handler.py61
-rw-r--r--components/pm-subscription-handler/tests/test_aai_service.py28
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_controller.py27
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_exit_handler.py29
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_network_function.py17
-rw-r--r--components/pm-subscription-handler/tests/test_pmsh_config.py43
-rw-r--r--components/pm-subscription-handler/tests/test_pmsh_utils.py245
-rw-r--r--components/pm-subscription-handler/tests/test_policy_response_handler.py37
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_subscription.py168
-rw-r--r--components/pm-subscription-handler/tests/test_subscription_handler.py181
30 files changed, 256 insertions, 1881 deletions
diff --git a/components/pm-subscription-handler/Changelog.md b/components/pm-subscription-handler/Changelog.md
index 00e97783..010fb1e5 100755
--- a/components/pm-subscription-handler/Changelog.md
+++ b/components/pm-subscription-handler/Changelog.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [2.2.0]
### Changed
* Update Filter API (DCAEGEN2-2922)
+* Cleaning up old App Config, subscription handler and it's subsequent calls (DCAEGEN2-3085)
## [2.1.1]
### Changed
diff --git a/components/pm-subscription-handler/pmsh_service/mod/__init__.py b/components/pm-subscription-handler/pmsh_service/mod/__init__.py
index 1024417e..548670c3 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/__init__.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/__init__.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.
@@ -15,7 +15,7 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-import logging as logging
+import logging
import os
import pathlib
import ssl
@@ -26,6 +26,9 @@ from flask_sqlalchemy import SQLAlchemy
from onaplogging import monkey
from onaplogging.mdcContext import MDC
from ruamel.yaml import YAML
+import uuid
+from functools import wraps
+from os import getenv
db = SQLAlchemy()
basedir = os.path.abspath(os.path.dirname(__file__))
@@ -33,6 +36,22 @@ _connexion_app = None
logger = logging.getLogger('onap_logger')
+def mdc_handler(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ request_id = str(uuid.uuid1())
+ invocation_id = str(uuid.uuid1())
+ MDC.put('ServiceName', getenv('HOSTNAME'))
+ MDC.put('RequestID', request_id)
+ MDC.put('InvocationID', invocation_id)
+
+ kwargs['request_id'] = request_id
+ kwargs['invocation_id'] = invocation_id
+ return func(*args, **kwargs)
+
+ return wrapper
+
+
def _get_app():
global _connexion_app
if not _connexion_app:
diff --git a/components/pm-subscription-handler/pmsh_service/mod/aai_client.py b/components/pm-subscription-handler/pmsh_service/mod/aai_client.py
index d2aeb0f0..437a18f0 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/aai_client.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/aai_client.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.
@@ -20,8 +20,7 @@ from os import environ
import requests
from requests.auth import HTTPBasicAuth
import mod.network_function
-import mod.pmsh_utils
-from mod import logger
+from mod import logger, mdc_handler
def get_pmsh_nfs_from_aai(app_conf, nf_filter):
@@ -68,8 +67,8 @@ def _get_all_aai_nf_data(app_conf):
}"""
params = {'format': 'simple', 'nodesOnly': 'true'}
response = session.put(aai_named_query_endpoint, headers=headers,
- auth=HTTPBasicAuth(app_conf.aaf_creds.get('aaf_id'),
- app_conf.aaf_creds.get('aaf_pass')),
+ auth=HTTPBasicAuth(app_conf.aaf_id,
+ app_conf.aaf_pass),
data=data, params=params,
verify=(app_conf.ca_cert_path if app_conf.enable_tls else False),
cert=((app_conf.cert_path,
@@ -102,7 +101,7 @@ def _get_aai_service_url():
raise
-@mod.pmsh_utils.mdc_handler
+@mdc_handler
def _get_aai_request_headers(**kwargs):
return {'accept': 'application/json',
'content-type': 'application/json',
@@ -160,28 +159,22 @@ def get_aai_model_data(app_conf, model_invariant_id, model_version_id, nf_name):
Returns:
json (dict): the sdnc_model json object.
-
- Raises:
- Exception: if AAI model data cannot be retrieved.
"""
- try:
- session = requests.Session()
- aai_model_ver_endpoint = \
- f'{_get_aai_service_url()}/service-design-and-creation/models/model/' \
- f'{model_invariant_id}/model-vers/model-ver/{model_version_id}'
-
- logger.info(f'Fetching sdnc-model info for xNF: {nf_name} from AAI.')
- headers = _get_aai_request_headers()
- response = session.get(aai_model_ver_endpoint, headers=headers,
- auth=HTTPBasicAuth(app_conf.aaf_creds.get('aaf_id'),
- app_conf.aaf_creds.get('aaf_pass')),
- verify=(app_conf.ca_cert_path if app_conf.enable_tls else False),
- cert=((app_conf.cert_path,
- app_conf.key_path) if app_conf.enable_tls else None))
- response.raise_for_status()
- if response.ok:
- data = json.loads(response.text)
- logger.debug(f'Successfully fetched sdnc-model info from AAI: {data}')
- return data
- except Exception:
- raise
+ session = requests.Session()
+ aai_model_ver_endpoint = \
+ f'{_get_aai_service_url()}/service-design-and-creation/models/model/' \
+ f'{model_invariant_id}/model-vers/model-ver/{model_version_id}'
+
+ logger.info(f'Fetching sdnc-model info for xNF: {nf_name} from AAI.')
+ headers = _get_aai_request_headers()
+ response = session.get(aai_model_ver_endpoint, headers=headers,
+ auth=HTTPBasicAuth(app_conf.aaf_id,
+ app_conf.aaf_pass),
+ verify=(app_conf.ca_cert_path if app_conf.enable_tls else False),
+ cert=((app_conf.cert_path,
+ app_conf.key_path) if app_conf.enable_tls else None))
+ response.raise_for_status()
+ if response.ok:
+ data = json.loads(response.text)
+ logger.debug(f'Successfully fetched sdnc-model info from AAI: {data}')
+ return data
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 57d3e021..2e811c28 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/api/controller.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/controller.py
@@ -22,7 +22,7 @@ from mod.api.services import subscription_service, measurement_group_service
from connexion import NoContent
from mod.api.custom_exception import InvalidDataException, DuplicateDataException, \
DataConflictException
-from mod.subscription import AdministrativeState
+from mod.api.services.measurement_group_service import AdministrativeState
def status():
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 07d1b642..145a492c 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
@@ -23,8 +23,40 @@ from mod import db, logger
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_
+from enum import Enum
+
+
+class MgNfState(Enum):
+ PENDING_CREATE = 'PENDING_CREATE'
+ CREATE_FAILED = 'CREATE_FAILED'
+ CREATED = 'CREATED'
+ PENDING_DELETE = 'PENDING_DELETE'
+ DELETE_FAILED = 'DELETE_FAILED'
+ DELETED = 'DELETED'
+
+
+class AdministrativeState(Enum):
+ UNLOCKED = 'UNLOCKED'
+ LOCKING = 'LOCKING'
+ LOCKED = 'LOCKED'
+ FILTERING = 'FILTERING'
+
+
+mg_nf_states = {
+ AdministrativeState.LOCKED.value: {
+ 'success': MgNfState.DELETED,
+ 'failed': MgNfState.DELETE_FAILED
+ },
+ AdministrativeState.UNLOCKED.value: {
+ 'success': MgNfState.CREATED,
+ 'failed': MgNfState.CREATE_FAILED
+ },
+ AdministrativeState.LOCKING.value: {
+ 'success': MgNfState.DELETED,
+ 'failed': MgNfState.DELETE_FAILED
+ }
+}
def save_measurement_group(measurement_group, subscription_name):
@@ -229,7 +261,7 @@ def deactivate_nfs(sub_model, measurement_group, nf_meas_relations):
logger.info(f'Saving measurement group to nf name, measure_grp_name: {nf.nf_name},'
f'{measurement_group.measurement_group_name} with DELETE request')
update_measurement_group_nf_status(measurement_group.measurement_group_name,
- SubNfState.PENDING_DELETE.value, nf.nf_name)
+ MgNfState.PENDING_DELETE.value, nf.nf_name)
try:
network_function = NetworkFunction(**nf.serialize_meas_group_nfs())
logger.info(f'Publishing event for nf name, measure_grp_name: {nf.nf_name},'
@@ -267,7 +299,7 @@ def activate_nfs(sub_model, measurement_group):
apply_nf_status_to_measurement_group(nf.nf_name,
measurement_group.measurement_group_name,
- SubNfState.PENDING_CREATE.value)
+ MgNfState.PENDING_CREATE.value)
db.session.commit()
try:
network_function = NetworkFunction(**nf.serialize_nf())
@@ -331,12 +363,12 @@ def filter_nf_to_meas_grp(nf_name, measurement_group_name, status):
status (string): status of the network function for measurement group
"""
try:
- if status == SubNfState.DELETED.value:
+ if status == MgNfState.DELETED.value:
delete_nf_to_measurement_group(nf_name, measurement_group_name,
- SubNfState.DELETED.value)
- elif status == SubNfState.CREATED.value:
+ MgNfState.DELETED.value)
+ elif status == MgNfState.CREATED.value:
update_measurement_group_nf_status(measurement_group_name,
- SubNfState.CREATED.value, nf_name)
+ MgNfState.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_%'),
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 032fc4a0..99b72dfb 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
@@ -23,7 +23,7 @@ from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, \
from mod.api.services import measurement_group_service, nf_service
from mod.api.custom_exception import InvalidDataException, DuplicateDataException, \
DataConflictException
-from mod.subscription import AdministrativeState, SubNfState
+from mod.api.services.measurement_group_service import MgNfState, AdministrativeState
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import joinedload
@@ -155,7 +155,7 @@ def apply_measurement_grp_to_nfs(filtered_nfs, unlocked_mgs):
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)
+ MgNfState.PENDING_CREATE.value)
def check_missing_data(subscription):
diff --git a/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py b/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py
index 16223790..69f2408f 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py
@@ -18,7 +18,7 @@
from mod import logger, db
from mod.api.services import subscription_service, measurement_group_service
-from mod.subscription import AdministrativeState
+from mod.api.services.measurement_group_service import AdministrativeState
class ExitHandler:
diff --git a/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py b/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py
index 9c282ab7..295fc379 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2021 Nordix Foundation.
+# Copyright (C) 2021-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.
@@ -28,8 +28,7 @@ from onap_dcae_cbs_docker_client.client import get_all
from requests.auth import HTTPBasicAuth
from tenacity import wait_fixed, stop_after_attempt, retry, retry_if_exception_type
-from mod import logger
-from mod.pmsh_utils import mdc_handler
+from mod import logger, mdc_handler
@unique
@@ -67,8 +66,6 @@ class AppConfig(metaclass=MetaSingleton):
self.aaf_pass = app_config['config'].get('aaf_password')
self.streams_publishes = app_config['config'].get('streams_publishes')
self.streams_subscribes = app_config['config'].get('streams_subscribes')
- # TODO: aaf_creds variable should be removed on code cleanup
- self.aaf_creds = {'aaf_id': self.aaf_id, 'aaf_pass': self.aaf_pass}
@staticmethod
def get_instance():
@@ -94,7 +91,7 @@ class AppConfig(metaclass=MetaSingleton):
return config
except Exception as e:
logger.error(f'Failed to get config from CBS: {e}', exc_info=True)
- raise ValueError(e)
+ raise ValueError(e) from e
@mdc_handler
def publish_to_topic(self, mr_topic, event_json, **kwargs):
@@ -104,22 +101,16 @@ class AppConfig(metaclass=MetaSingleton):
Args:
mr_topic (enum) : Message Router topic to publish.
event_json (dict): the json data to be published.
-
- Raises:
- Exception: if post request fails.
"""
- try:
- session = requests.Session()
- topic_url = self.streams_publishes[mr_topic].get('dmaap_info').get('topic_url')
- headers = {'content-type': 'application/json', 'x-transactionid': kwargs['request_id'],
- 'InvocationID': kwargs['invocation_id'], 'RequestID': kwargs['request_id']}
- logger.info(f'Publishing event to MR topic: {topic_url}')
- response = session.post(topic_url, headers=headers,
- auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), json=event_json,
- verify=(self.ca_cert_path if self.enable_tls else False))
- response.raise_for_status()
- except Exception as e:
- raise e
+ session = requests.Session()
+ topic_url = self.streams_publishes[mr_topic].get('dmaap_info').get('topic_url')
+ headers = {'content-type': 'application/json', 'x-transactionid': kwargs['request_id'],
+ 'InvocationID': kwargs['invocation_id'], 'RequestID': kwargs['request_id']}
+ logger.info(f'Publishing event to MR topic: {topic_url}')
+ response = session.post(topic_url, headers=headers,
+ auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), json=event_json,
+ verify=(self.ca_cert_path if self.enable_tls else False))
+ response.raise_for_status()
@mdc_handler
def get_from_topic(self, mr_topic, consumer_id, consumer_group='dcae_pmsh_cg', timeout=5000,
@@ -149,7 +140,6 @@ class AppConfig(metaclass=MetaSingleton):
verify=(self.ca_cert_path if self.enable_tls else False))
if response.status_code == 503:
logger.error(f'MR Service is unavailable at present: {response.content}')
- pass
response.raise_for_status()
if response.ok:
return response.json()
diff --git a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py b/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
deleted file mode 100755
index d1790bbb..00000000
--- a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
+++ /dev/null
@@ -1,313 +0,0 @@
-# ============LICENSE_START===================================================
-# 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.
-# 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
-import os
-import uuid
-from functools import wraps
-from json import JSONDecodeError
-from os import getenv
-from threading import Timer
-
-import requests
-from jsonschema import validate, ValidationError
-from onap_dcae_cbs_docker_client.client import get_all
-from onaplogging.mdcContext import MDC
-from requests.auth import HTTPBasicAuth
-from tenacity import wait_fixed, stop_after_attempt, retry, retry_if_exception_type
-
-from mod import logger
-from mod.subscription import Subscription
-
-
-def mdc_handler(func):
- @wraps(func)
- def wrapper(*args, **kwargs):
- request_id = str(uuid.uuid1())
- invocation_id = str(uuid.uuid1())
- MDC.put('ServiceName', getenv('HOSTNAME'))
- MDC.put('RequestID', request_id)
- MDC.put('InvocationID', invocation_id)
-
- kwargs['request_id'] = request_id
- kwargs['invocation_id'] = invocation_id
- return func(*args, **kwargs)
-
- return wrapper
-
-
-def _load_sub_schema_from_file():
- try:
- with open(os.path.join(os.path.dirname(__file__), 'sub_schema.json')) as sub:
- return json.load(sub)
- except OSError as err:
- logger.error(f'Failed to read sub schema file: {err}', exc_info=True)
- except JSONDecodeError as json_err:
- logger.error(f'sub schema file is not a valid JSON file: {json_err}', exc_info=True)
-
-
-class AppConfig:
- INSTANCE = None
-
- def __init__(self):
- conf = self._get_pmsh_config()
- self.aaf_creds = {'aaf_id': conf['config'].get('aaf_identity'),
- 'aaf_pass': conf['config'].get('aaf_password')}
- self.enable_tls = conf['config'].get('enable_tls')
- self.ca_cert_path = conf['config'].get('ca_cert_path')
- self.cert_path = conf['config'].get('cert_path')
- self.key_path = conf['config'].get('key_path')
- self.streams_subscribes = conf['config'].get('streams_subscribes')
- self.streams_publishes = conf['config'].get('streams_publishes')
- self.operational_policy_name = conf['config'].get('operational_policy_name')
- self.control_loop_name = conf['config'].get('control_loop_name')
- self.sub_schema = _load_sub_schema_from_file()
- self.subscription = Subscription(self.control_loop_name,
- self.operational_policy_name,
- **conf['config']['pmsh_policy']['subscription'])
- self.nf_filter = None
-
- def __new__(cls, *args, **kwargs):
- if AppConfig.INSTANCE is None:
- AppConfig.INSTANCE = super().__new__(cls, *args, **kwargs)
- return AppConfig.INSTANCE
-
- @mdc_handler
- @retry(wait=wait_fixed(5), stop=stop_after_attempt(5),
- retry=retry_if_exception_type(ValueError))
- def _get_pmsh_config(self, **kwargs):
- """ Retrieves PMSH's configuration from Config binding service. If a non-2xx response
- is received, it retries after 2 seconds for 5 times before raising an exception.
-
- Returns:
- dict: Dictionary representation of the the service configuration
-
- Raises:
- Exception: If any error occurred pulling configuration from Config binding service.
- """
- try:
- logger.info('Attempting to fetch PMSH Configuration from CBS.')
- config = get_all()
- logger.info(f'Successfully fetched PMSH config from CBS: {config}')
- return config
- except Exception as e:
- logger.error(f'Failed to get config from CBS: {e}', exc_info=True)
- raise ValueError(e)
-
- def validate_sub_schema(self):
- """
- Validates schema of PMSH subscription
-
- Raises:
- ValidationError: If the PMSH subscription schema is invalid
- """
- sub_data = self.subscription.__dict__
- validate(instance=sub_data, schema=self.sub_schema)
- nf_filter = sub_data["nfFilter"]
- if not [filter_name for filter_name, val in nf_filter.items() if len(val) > 0]:
- raise ValidationError("At least one filter within nfFilter must not be empty")
- logger.debug("Subscription schema is valid.")
-
- def refresh_config(self):
- """
- Update the relevant attributes of the AppConfig object.
-
- Raises:
- Exception: if cbs request fails.
- """
- try:
- app_conf = self._get_pmsh_config()
- self.operational_policy_name = app_conf['config'].get('operational_policy_name')
- self.control_loop_name = app_conf['config'].get('control_loop_name')
- self.subscription = Subscription(self.control_loop_name,
- self.operational_policy_name,
- **app_conf['config']['pmsh_policy']['subscription'])
- logger.info("AppConfig data has been refreshed")
- except Exception:
- logger.error('Failed to refresh PMSH AppConfig')
- raise
-
- def get_mr_sub(self, sub_name):
- """
- Returns the MrSub object requested.
-
- Args:
- sub_name: the key of the subscriber object.
-
- Returns:
- MrSub: an Instance of an `MrSub` <MrSub> Object.
-
- Raises:
- KeyError: if the sub_name is not found.
- """
- try:
- return _MrSub(sub_name, self.aaf_creds, self.ca_cert_path,
- self.enable_tls, self.cert_params, **self.streams_subscribes[sub_name])
- except KeyError as e:
- logger.error(f'Failed to get MrSub {sub_name}: {e}', exc_info=True)
- raise
-
- def get_mr_pub(self, pub_name):
- """
- Returns the MrPub object requested.
-
- Args:
- pub_name: the key of the publisher object.
-
- Returns:
- MrPub: an Instance of an `MrPub` <MrPub> Object.
-
- Raises:
- KeyError: if the sub_name is not found.
- """
- try:
- return _MrPub(pub_name, self.aaf_creds, self.ca_cert_path,
- self.enable_tls, self.cert_params, **self.streams_publishes[pub_name])
- except KeyError as e:
- logger.error(f'Failed to get MrPub {pub_name}: {e}', exc_info=True)
- raise
-
- @property
- def cert_params(self):
- """
- Returns the tls artifact paths.
-
- Returns:
- cert_path, key_path (tuple): the path to tls cert and key.
- """
- return self.cert_path, self.key_path
-
-
-class _DmaapMrClient:
- def __init__(self, aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs):
- """
- A DMaaP Message Router utility class.
- Sub classes should be invoked via the AppConfig.get_mr_{pub|sub} only.
- Args:
- aaf_creds (dict): a dict of aaf secure credentials.
- ca_cert_path (str): path to the ca certificate.
- enable_tls (bool): TLS if True, else False
- cert_params (tuple): client side (cert, key) tuple.
- **kwargs: a dict of streams_{subscribes|publishes} data.
- """
- self.topic_url = kwargs.get('dmaap_info').get('topic_url')
- self.aaf_id = aaf_creds.get('aaf_id')
- self.aaf_pass = aaf_creds.get('aaf_pass')
- self.ca_cert_path = ca_cert_path
- self.enable_tls = enable_tls
- self.cert_params = cert_params
-
-
-class _MrPub(_DmaapMrClient):
- def __init__(self, pub_name, aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs):
- self.pub_name = pub_name
- super().__init__(aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs)
-
- @mdc_handler
- def publish_to_topic(self, event_json, **kwargs):
- """
- Publish the event to the DMaaP Message Router topic.
-
- Args:
- event_json (dict): the json data to be published.
-
- Raises:
- Exception: if post request fails.
- """
- try:
- session = requests.Session()
- headers = {'content-type': 'application/json', 'x-transactionid': kwargs['request_id'],
- 'InvocationID': kwargs['invocation_id'],
- 'RequestID': kwargs['request_id']
- }
- logger.info(f'Publishing event to {self.topic_url}')
- response = session.post(self.topic_url, headers=headers,
- auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), json=event_json,
- verify=(self.ca_cert_path if self.enable_tls else False))
- response.raise_for_status()
- except Exception as e:
- raise e
-
- def publish_subscription_event_data(self, subscription, nf):
- """
- Update the Subscription dict with xnf and policy name then publish to DMaaP MR topic.
-
- Args:
- subscription (Subscription): the `Subscription` <Subscription> object.
- nf (NetworkFunction): the NetworkFunction to include in the event.
- """
- try:
- subscription_event = subscription.prepare_subscription_event(nf)
- logger.debug(f'Subscription event: {subscription_event}')
- self.publish_to_topic(subscription_event)
- except Exception as e:
- logger.error(f'Failed to publish to topic {self.topic_url}: {e}', exc_info=True)
- raise e
-
-
-class _MrSub(_DmaapMrClient):
- def __init__(self, sub_name, aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs):
- self.sub_name = sub_name
- super().__init__(aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs)
-
- @mdc_handler
- def get_from_topic(self, consumer_id, consumer_group='dcae_pmsh_cg', timeout=1000, **kwargs):
- """
- Returns the json data from the MrTopic.
-
- Args:
- consumer_id (str): Within your subscribers group, a name that uniquely
- identifies your subscribers process.
- consumer_group (str): A name that uniquely identifies your subscribers.
- timeout (int): The request timeout value in mSec.
-
- Returns:
- list[str]: the json response from DMaaP Message Router topic.
- """
- try:
- session = requests.Session()
- headers = {'accept': 'application/json', 'content-type': 'application/json',
- 'InvocationID': kwargs['invocation_id'],
- 'RequestID': kwargs['request_id']}
- logger.info(f'Fetching messages from 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,
- verify=(self.ca_cert_path if self.enable_tls else False))
- if response.status_code == 503:
- logger.error(f'MR Service is unavailable at present: {response.content}')
- pass
- response.raise_for_status()
- if response.ok:
- return response.json()
- except Exception as e:
- logger.error(f'Failed to fetch message from MR: {e}', exc_info=True)
- raise
-
-
-class PeriodicTask(Timer):
- """
- See :class:`Timer`.
- """
-
- def run(self):
- self.function(*self.args, **self.kwargs)
- while not self.finished.wait(self.interval):
- try:
- self.function(*self.args, **self.kwargs)
- except Exception as e:
- logger.error(f'Exception in thread: {self.name}: {e}', exc_info=True)
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 5065ce8a..cfcda091 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
@@ -16,9 +16,11 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
import json
+
+from mod.api.services.measurement_group_service import mg_nf_states, \
+ AdministrativeState, MgNfState
from mod.pmsh_config import MRTopic, AppConfig
from mod import logger
-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
@@ -96,12 +98,12 @@ class PolicyResponseHandler:
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:
+ if nf_msg_rel.nf_measure_grp_status == MgNfState.PENDING_DELETE.value:
administrative_state = AdministrativeState.LOCKING.value
- elif nf_msg_rel.nf_measure_grp_status == SubNfState.PENDING_CREATE.value:
+ elif nf_msg_rel.nf_measure_grp_status == MgNfState.PENDING_CREATE.value:
administrative_state = AdministrativeState.UNLOCKED.value
- nf_measure_grp_status = (subscription_nf_states[administrative_state]
+ nf_measure_grp_status = (mg_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,
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription.py b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
deleted file mode 100755
index ddb6e1f5..00000000
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription.py
+++ /dev/null
@@ -1,295 +0,0 @@
-# ============LICENSE_START===================================================
-# 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.
-# 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=====================================================
-from enum import Enum
-
-from mod import db, logger
-from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, NetworkFunctionModel
-
-
-class SubNfState(Enum):
- PENDING_CREATE = 'PENDING_CREATE'
- CREATE_FAILED = 'CREATE_FAILED'
- CREATED = 'CREATED'
- PENDING_DELETE = 'PENDING_DELETE'
- DELETE_FAILED = 'DELETE_FAILED'
- DELETED = 'DELETED'
-
-
-class AdministrativeState(Enum):
- UNLOCKED = 'UNLOCKED'
- LOCKING = 'LOCKING'
- LOCKED = 'LOCKED'
- FILTERING = 'FILTERING'
-
-
-subscription_nf_states = {
- AdministrativeState.LOCKED.value: {
- 'success': SubNfState.DELETED,
- 'failed': SubNfState.DELETE_FAILED
- },
- AdministrativeState.UNLOCKED.value: {
- 'success': SubNfState.CREATED,
- 'failed': SubNfState.CREATE_FAILED
- },
- AdministrativeState.LOCKING.value: {
- 'success': SubNfState.DELETED,
- 'failed': SubNfState.DELETE_FAILED
- }
-}
-
-
-def _get_nf_objects(nf_sub_relationships):
- nfs = []
- for nf_sub_entry in nf_sub_relationships:
- nf_model_object = NetworkFunctionModel.query.filter(
- NetworkFunctionModel.nf_name == nf_sub_entry.nf_name).one_or_none()
- nfs.append(nf_model_object.to_nf())
- return nfs
-
-
-class Subscription:
- def __init__(self, control_loop_name, operational_policy_name, **kwargs):
- self.subscriptionName = kwargs.get('subscriptionName')
- self.administrativeState = kwargs.get('administrativeState')
- self.fileBasedGP = kwargs.get('fileBasedGP')
- self.fileLocation = kwargs.get('fileLocation')
- self.nfFilter = kwargs.get('nfFilter')
- self.measurementGroups = kwargs.get('measurementGroups')
- self.control_loop_name = control_loop_name
- self.operational_policy_name = operational_policy_name
- self.create()
-
- def update_sub_params(self, admin_state, file_based_gp, file_location, meas_groups):
- self.administrativeState = admin_state
- self.fileBasedGP = file_based_gp
- self.fileLocation = file_location
- self.measurementGroups = meas_groups
-
- def create(self):
- """ Creates a subscription database entry
-
- Returns:
- Subscription object
- """
- 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,
- operational_policy_name=self.operational_policy_name,
- control_loop_name=self.control_loop_name,
- 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
- 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 update_subscription_status(self):
- """ Updates the status of subscription in subscription table """
- try:
- SubscriptionModel.query.filter(
- SubscriptionModel.subscription_name == self.subscriptionName) \
- .update({SubscriptionModel.status: self.administrativeState},
- 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):
- """Prepare the sub event for publishing
-
- Args:
- nf (NetworkFunction): the AAI nf.
-
- Returns:
- dict: the Subscription event to be published.
- """
- try:
- clean_sub = \
- {k: v for k, v in self.__dict__.items() if
- (k != 'nfFilter' and k != 'control_loop_name' and k != 'operational_policy_name')}
- if self.administrativeState == AdministrativeState.LOCKING.value:
- change_type = 'DELETE'
- else:
- change_type = 'CREATE'
-
- sub_event = {
- 'nfName': nf.nf_name,
- 'ipAddress': nf.ipv4_address if nf.ipv6_address in (None, '') else nf.ipv6_address,
- 'blueprintName': nf.sdnc_model_name,
- 'blueprintVersion': nf.sdnc_model_version,
- 'operationalPolicyName': self.operational_policy_name,
- 'changeType': change_type,
- 'controlLoopName': self.control_loop_name,
- 'subscription': clean_sub}
- return sub_event
- except Exception as e:
- logger.error(f'Failed to prep Sub event for xNF {nf.nf_name}: {e}', exc_info=True)
- raise
-
- def add_network_function_to_subscription(self, nf, sub_model):
- """ Associates a network function to a Subscription
-
- Args:
- sub_model(SubscriptionModel): The SubscriptionModel from the DB.
- nf(NetworkFunction): A NetworkFunction object.
- """
- try:
- current_nf = nf.create()
- existing_entry = NfSubRelationalModel.query.filter(
- NfSubRelationalModel.subscription_name == self.subscriptionName,
- NfSubRelationalModel.nf_name == current_nf.nf_name).one_or_none()
- if existing_entry is None:
- new_nf_sub = NfSubRelationalModel(self.subscriptionName,
- nf.nf_name, SubNfState.PENDING_CREATE.value)
- sub_model.nfs.append(new_nf_sub)
- db.session.add(sub_model)
- db.session.commit()
- logger.info(f'Network function {current_nf.nf_name} added to Subscription '
- f'{self.subscriptionName}')
- except Exception as e:
- logger.error(f'Failed to add nf {nf.nf_name} to subscription '
- f'{self.subscriptionName}: {e}', exc_info=True)
- logger.debug(f'Subscription {self.subscriptionName} now contains these XNFs:'
- f'{[nf.nf_name for nf.nf_name in self.get_network_functions()]}')
-
- def get(self):
- """ Retrieves a SubscriptionModel object
-
- Returns:
- SubscriptionModel object else None
- """
- sub_model = SubscriptionModel.query.filter(
- SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
- return sub_model
-
- def get_local_sub_admin_state(self):
- """ Retrieves the subscription admin state
-
- Returns:
- str: The admin state of the SubscriptionModel
- """
- sub_model = SubscriptionModel.query.filter(
- SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
- db.session.remove()
- return sub_model.status
-
- def create_subscription_on_nfs(self, nfs, mr_pub):
- """ Publishes an event to create a Subscription on an nf
-
- Args:
- nfs(list[NetworkFunction]): A list of NetworkFunction Objects.
- mr_pub (_MrPub): MR publisher
- """
- try:
- existing_nfs = self.get_network_functions()
- sub_model = self.get()
- for nf in [new_nf for new_nf in nfs if new_nf not in existing_nfs]:
- logger.info(f'Publishing event to create '
- f'Sub: {self.subscriptionName} on nf: {nf.nf_name}')
- mr_pub.publish_subscription_event_data(self, nf)
- self.add_network_function_to_subscription(nf, sub_model)
- self.update_sub_nf_status(self.subscriptionName, SubNfState.PENDING_CREATE.value,
- nf.nf_name)
- except Exception as err:
- raise Exception(f'Error publishing create event to MR: {err}')
-
- def delete_subscription_from_nfs(self, nfs, mr_pub):
- """ Publishes an event to delete a Subscription from an nf
-
- Args:
- nfs(list[NetworkFunction]): A list of NetworkFunction Objects.
- mr_pub (_MrPub): MR publisher
- """
- try:
- for nf in nfs:
- logger.debug(f'Publishing Event to delete '
- f'Sub: {self.subscriptionName} from the nf: {nf.nf_name}')
- mr_pub.publish_subscription_event_data(self, nf)
- self.update_sub_nf_status(self.subscriptionName,
- SubNfState.PENDING_DELETE.value,
- nf.nf_name)
- except Exception as err:
- raise Exception(f'Error publishing delete event to MR: {err}')
-
- @staticmethod
- def get_all_nfs_subscription_relations():
- """ Retrieves all network function to subscription relations
-
- Returns:
- list(NfSubRelationalModel): NetworkFunctions per Subscription list else empty
- """
- nf_per_subscriptions = NfSubRelationalModel.query.all()
- db.session.remove()
- return nf_per_subscriptions
-
- @staticmethod
- def update_sub_nf_status(subscription_name, status, nf_name):
- """ Updates the status of the subscription for a particular nf
-
- Args:
- subscription_name (str): The subscription name
- nf_name (str): The network function name
- status (str): Status of the subscription
- """
- try:
- NfSubRelationalModel.query.filter(
- NfSubRelationalModel.subscription_name == subscription_name,
- NfSubRelationalModel.nf_name == nf_name). \
- update({NfSubRelationalModel.nf_sub_status: status}, synchronize_session='evaluate')
- db.session.commit()
- except Exception as e:
- logger.error(f'Failed to update status of nf: {nf_name} for subscription: '
- f'{subscription_name}: {e}', exc_info=True)
-
- def get_network_functions(self):
- nf_sub_relationships = NfSubRelationalModel.query.filter(
- NfSubRelationalModel.subscription_name == self.subscriptionName)
- nfs = _get_nf_objects(nf_sub_relationships)
- db.session.remove()
- return nfs
-
- def get_delete_failed_nfs(self):
- nf_sub_relationships = NfSubRelationalModel.query.filter(
- NfSubRelationalModel.subscription_name == self.subscriptionName,
- NfSubRelationalModel.nf_sub_status == SubNfState.DELETE_FAILED.value)
- nfs = _get_nf_objects(nf_sub_relationships)
- db.session.remove()
- return nfs
-
- def get_delete_pending_nfs(self):
- nf_sub_relationships = NfSubRelationalModel.query.filter(
- NfSubRelationalModel.subscription_name == self.subscriptionName,
- NfSubRelationalModel.nf_sub_status == SubNfState.PENDING_DELETE.value)
- nfs = _get_nf_objects(nf_sub_relationships)
- db.session.remove()
- return nfs
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py b/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
deleted file mode 100644
index 5fbb9a6c..00000000
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# ============LICENSE_START===================================================
-# 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.
-# 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=====================================================
-from jsonschema import ValidationError
-
-from mod import logger, aai_client
-from mod.network_function import NetworkFunctionFilter
-from mod.subscription import AdministrativeState
-
-
-class SubscriptionHandler:
- def __init__(self, mr_pub, aai_sub, app, app_conf):
- self.mr_pub = mr_pub
- self.aai_sub = aai_sub
- self.app = app
- self.app_conf = app_conf
- self.aai_event_thread = None
-
- def execute(self):
- """
- Checks for changes of administrative state in config and proceeds to process
- the Subscription if a change has occurred
- """
- self.app.app_context().push()
- try:
- local_admin_state = self.app_conf.subscription.get_local_sub_admin_state()
- if local_admin_state == AdministrativeState.LOCKING.value:
- self._check_for_failed_nfs()
- 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)
- except (ValidationError, TypeError) as err:
- logger.error(f'Error occurred during validation of subscription schema {err}',
- exc_info=True)
- except Exception as err:
- logger.error(f'Error occurred during the activation/deactivation process {err}',
- exc_info=True)
-
- 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} '
- f'to {new_administrative_state}.')
- self._activate(new_administrative_state)
- elif new_administrative_state == AdministrativeState.LOCKED.value:
- logger.info(f'Administrative State has changed from {local_admin_state} '
- f'to {new_administrative_state}.')
- self._deactivate()
- else:
- raise Exception(f'Invalid AdministrativeState: {new_administrative_state}')
-
- def _activate(self, new_administrative_state):
- if not self.app_conf.nf_filter:
- self.app_conf.nf_filter = NetworkFunctionFilter(**self.app_conf.subscription.nfFilter)
- self.app_conf.subscription.update_sub_params(new_administrative_state,
- self.app_conf.subscription.fileBasedGP,
- self.app_conf.subscription.fileLocation,
- self.app_conf.subscription.measurementGroups)
- nfs_in_aai = aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter)
- self.app_conf.subscription.create_subscription_on_nfs(nfs_in_aai, self.mr_pub)
- self.app_conf.subscription.update_subscription_status()
-
- def _deactivate(self):
- nfs = self.app_conf.subscription.get_network_functions()
- if nfs:
- self.stop_aai_event_thread()
- self.app_conf.subscription.administrativeState = AdministrativeState.LOCKING.value
- logger.info('Subscription is now LOCKING/DEACTIVATING.')
- self.app_conf.subscription.delete_subscription_from_nfs(nfs, self.mr_pub)
- self.app_conf.subscription.update_subscription_status()
-
- def stop_aai_event_thread(self):
- if self.aai_event_thread is not None:
- self.aai_event_thread.cancel()
- self.aai_event_thread = None
- logger.info('Stopping polling for NFs events on AAI-EVENT topic in MR.')
-
- def _check_for_failed_nfs(self):
- logger.info('Checking for DELETE_FAILED NFs before LOCKING Subscription.')
- del_failed_nfs = self.app_conf.subscription.get_delete_failed_nfs()
- if del_failed_nfs or self.app_conf.subscription.get_delete_pending_nfs():
- for nf in del_failed_nfs:
- nf_model = nf.get(nf.nf_name)
- if nf_model.retry_count < 3:
- logger.info(f'Retry deletion of subscription '
- f'{self.app_conf.subscription.subscriptionName} '
- f'from NF: {nf.nf_name}')
- self.app_conf.subscription.delete_subscription_from_nfs([nf], self.mr_pub)
- nf.increment_retry_count()
- else:
- logger.error(f'Failed to delete the subscription '
- f'{self.app_conf.subscription.subscriptionName} '
- f'from NF: {nf.nf_name} after {nf_model.retry_count} '
- f'attempts. Removing NF from DB')
- nf.delete(nf_name=nf.nf_name)
- else:
- logger.info('Proceeding to LOCKED adminState.')
- self.app_conf.subscription.administrativeState = AdministrativeState.LOCKED.value
- self.app_conf.subscription.update_subscription_status()
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 1d8b0b34..dbc58e51 100755
--- a/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py
+++ b/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py
@@ -21,8 +21,22 @@ from mod.aai_event_handler import AAIEventHandler
from mod import db, create_app, launch_api_server, logger
from mod.exit_handler import ExitHandler
from mod.pmsh_config import AppConfig
-from mod.pmsh_utils import PeriodicTask
from mod.policy_response_handler import PolicyResponseHandler
+from threading import Timer
+
+
+class PeriodicTask(Timer):
+ """
+ See :class:`Timer`.
+ """
+
+ def run(self):
+ self.function(*self.args, **self.kwargs)
+ while not self.finished.wait(self.interval):
+ try:
+ self.function(*self.args, **self.kwargs)
+ except Exception as e:
+ logger.error(f'Exception in thread: {self.name}: {e}', exc_info=True)
def main():
diff --git a/components/pm-subscription-handler/tests/base_setup.py b/components/pm-subscription-handler/tests/base_setup.py
index 14f813d4..90919ff1 100755
--- a/components/pm-subscription-handler/tests/base_setup.py
+++ b/components/pm-subscription-handler/tests/base_setup.py
@@ -24,9 +24,7 @@ from unittest.mock import patch, MagicMock
from mod import create_app, db
from mod.api.db_models import NetworkFunctionFilterModel, MeasurementGroupModel, \
SubscriptionModel, NetworkFunctionModel, NfSubRelationalModel
-from mod.network_function import NetworkFunctionFilter
-from mod.pmsh_utils import AppConfig
-from mod.pmsh_config import AppConfig as NewAppConfig
+from mod.pmsh_config import AppConfig
def get_pmsh_config(file_path='data/cbs_data_1.json'):
@@ -124,16 +122,11 @@ class BaseClassSetup(TestCase):
cls.app_context = cls.app.app_context()
cls.app_context.push()
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config', MagicMock(return_value=get_pmsh_config()))
+ @patch('mod.pmsh_config.AppConfig._get_config', MagicMock(return_value=get_pmsh_config()))
def setUp(self):
os.environ['AAI_SERVICE_PORT'] = '8443'
db.create_all()
self.app_conf = AppConfig()
- self.app_conf.nf_filter = NetworkFunctionFilter(**self.app_conf.subscription.nfFilter)
-
- @patch('mod.pmsh_config.AppConfig._get_config', MagicMock(return_value=get_pmsh_config()))
- def setUpAppConf(self):
- self.pmsh_app_conf = NewAppConfig()
def tearDown(self):
db.drop_all()
diff --git a/components/pm-subscription-handler/tests/data/cbs_data_1.json b/components/pm-subscription-handler/tests/data/cbs_data_1.json
index f872bb50..6efda4f8 100644
--- a/components/pm-subscription-handler/tests/data/cbs_data_1.json
+++ b/components/pm-subscription-handler/tests/data/cbs_data_1.json
@@ -8,71 +8,6 @@
"key_path":"/opt/app/pmsh/etc/certs/key.pem",
"ca_cert_path":"/opt/app/pmsh/etc/certs/cacert.pem",
"enable_tls":"true",
- "pmsh_policy":{
- "subscription":{
- "subscriptionName":"ExtraPM-All-gNB-R2B",
- "administrativeState":"UNLOCKED",
- "fileBasedGP":15,
- "fileLocation":"\/pm\/pm.xml",
- "nfFilter":{
- "nfNames":[
- "^pnf.*",
- "^vnf.*"
- ],
- "modelInvariantIDs":[
-
- ],
- "modelVersionIDs":[
-
- ],
- "modelNames":[
-
- ]
- },
- "measurementGroups":[
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"countera"
- },
- {
- "measurementType":"counterb"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dna"
- },
- {
- "DN":"dnb"
- }
- ]
- }
- },
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"counterc"
- },
- {
- "measurementType":"counterd"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dnc"
- },
- {
- "DN":"dnd"
- }
- ]
- }
- }
- ]
- }
- },
"streams_subscribes":{
"aai_subscriber":{
"type":"message_router",
@@ -114,4 +49,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/components/pm-subscription-handler/tests/data/cbs_invalid_data.json b/components/pm-subscription-handler/tests/data/cbs_invalid_data.json
deleted file mode 100644
index a6f63680..00000000
--- a/components/pm-subscription-handler/tests/data/cbs_invalid_data.json
+++ /dev/null
@@ -1,116 +0,0 @@
-{
- "config":{
- "control_loop_name":"pmsh-control-loop",
- "operational_policy_name":"pmsh-operational-policy",
- "aaf_password":"demo123456!",
- "aaf_identity":"dcae@dcae.onap.org",
- "cert_path":"/opt/app/pmsh/etc/certs/cert.pem",
- "key_path":"/opt/app/pmsh/etc/certs/key.pem",
- "ca_cert_path":"/opt/app/pmsh/etc/certs/cacert.pem",
- "enable_tls":"true",
- "pmsh_policy":{
- "subscription":{
- "subscriptionName":"ExtraPM-All-gNB-R2B",
- "administrativeState":"UNLOCKED",
- "fileBasedGP":15,
- "fileLocation":"\/pm\/pm.xml",
- "nfFilter":{
- "nfNames":[
-
- ],
- "modelInvariantIDs":[
-
- ],
- "modelVersionIDs":[
-
- ],
- "modelNames":[
-
- ]
- },
- "measurementGroups":[
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"countera"
- },
- {
- "measurementType":"counterb"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dna"
- },
- {
- "DN":"dnb"
- }
- ]
- }
- },
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"counterc"
- },
- {
- "measurementType":"counterd"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dnc"
- },
- {
- "DN":"dnd"
- }
- ]
- }
- }
- ]
- }
- },
- "streams_subscribes":{
- "aai_subscriber":{
- "type":"message_router",
- "dmaap_info":{
- "topic_url":"https://message-router:3905/events/AAI_EVENT",
- "client_role":"org.onap.dcae.aaiSub",
- "location":"san-francisco",
- "client_id":"1575976809466"
- }
- },
- "policy_pm_subscriber":{
- "type":"message_router",
- "dmaap_info":{
- "topic_url":"https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS",
- "client_role":"org.onap.dcae.pmSubscriber",
- "location":"san-francisco",
- "client_id":"1575876809456"
- }
- }
- },
- "streams_publishes":{
- "policy_pm_publisher":{
- "type":"message_router",
- "dmaap_info":{
- "topic_url":"https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS",
- "client_role":"org.onap.dcae.pmPublisher",
- "location":"san-francisco",
- "client_id":"1475976809466"
- }
- },
- "other_publisher":{
- "type":"message_router",
- "dmaap_info":{
- "topic_url":"https://message-router:3905/events/org.onap.dmaap.mr.SOME_OTHER_TOPIC",
- "client_role":"org.onap.dcae.pmControlPub",
- "location":"san-francisco",
- "client_id":"1875976809466"
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/components/pm-subscription-handler/tests/data/pm_subscription_event.json b/components/pm-subscription-handler/tests/data/pm_subscription_event.json
deleted file mode 100755
index 6a7fe340..00000000
--- a/components/pm-subscription-handler/tests/data/pm_subscription_event.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
- "nfName":"pnf_1",
- "blueprintName": "some-name",
- "blueprintVersion": "some-version",
- "operationalPolicyName":"pmsh-operational-policy",
- "changeType":"CREATE",
- "controlLoopName":"pmsh-control-loop",
- "ipAddress": "204.120.0.15",
- "subscription":{
- "subscriptionName":"ExtraPM-All-gNB-R2B",
- "administrativeState":"UNLOCKED",
- "fileBasedGP":15,
- "fileLocation":"/pm/pm.xml",
- "measurementGroups":[
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"countera"
- },
- {
- "measurementType":"counterb"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dna"
- },
- {
- "DN":"dnb"
- }
- ]
- }
- },
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"counterc"
- },
- {
- "measurementType":"counterd"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dnc"
- },
- {
- "DN":"dnd"
- }
- ]
- }
- }
- ]
- }
-}
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 1dbe84a9..25ab2581 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
@@ -21,6 +21,7 @@ import os
from unittest.mock import patch
from mod.api.custom_exception import InvalidDataException, DataConflictException
+from mod.api.services.measurement_group_service import MgNfState
from mod.network_function import NetworkFunction, NetworkFunctionFilter
from mod.pmsh_config import AppConfig
from mod import db, aai_client
@@ -29,13 +30,9 @@ from tests.base_setup import BaseClassSetup, create_subscription_data, \
from mod.api.services import measurement_group_service, nf_service
from mod.api.db_models import MeasurementGroupModel, NfMeasureGroupRelationalModel, \
SubscriptionModel, NetworkFunctionModel
-from mod.subscription import SubNfState
class MeasurementGroupServiceTestCase(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
def setUp(self):
super().setUp()
@@ -48,16 +45,9 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
'r') as data:
self.good_model_info = data.read()
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
@patch.object(AppConfig, 'publish_to_topic')
def test_publish_measurement_group(self, mock_mr):
- super().setUpAppConf()
+ super().setUp()
nf_1 = NetworkFunction(**{'nf_name': 'pnf_1',
'ipv4_address': '204.120.0.15',
'ipv6_address': '2001:db8:3333:4444:5555:6666:7777:8888',
@@ -104,38 +94,38 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
def test_apply_nf_to_measurement_group_status(self):
measurement_group_service.apply_nf_status_to_measurement_group(
- "pnf_test", "measure_grp_name", SubNfState.PENDING_CREATE.value)
+ "pnf_test", "measure_grp_name", MgNfState.PENDING_CREATE.value)
db.session.commit()
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test').one_or_none())
self.assertIsNotNone(measurement_grp_rel)
self.assertEqual(measurement_grp_rel.nf_measure_grp_status,
- SubNfState.PENDING_CREATE.value)
+ MgNfState.PENDING_CREATE.value)
def test_update_measurement_group_nf_status(self):
measurement_group_service.apply_nf_status_to_measurement_group(
- "pnf_test", "measure_grp_name", SubNfState.PENDING_CREATE.value)
+ "pnf_test", "measure_grp_name", MgNfState.PENDING_CREATE.value)
measurement_group_service.update_measurement_group_nf_status(
- "measure_grp_name", SubNfState.CREATED.value, "pnf_test")
+ "measure_grp_name", MgNfState.CREATED.value, "pnf_test")
db.session.commit()
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test').one_or_none())
self.assertIsNotNone(measurement_grp_rel)
self.assertEqual(measurement_grp_rel.nf_measure_grp_status,
- SubNfState.CREATED.value)
+ MgNfState.CREATED.value)
def test_delete_nf_to_measurement_group_without_nf_delete(self):
nf = NetworkFunction(nf_name='pnf_test1')
nf_service.save_nf(nf)
db.session.commit()
measurement_group_service.apply_nf_status_to_measurement_group(
- "pnf_test1", "measure_grp_name1", SubNfState.PENDING_CREATE.value)
+ "pnf_test1", "measure_grp_name1", MgNfState.PENDING_CREATE.value)
measurement_group_service.apply_nf_status_to_measurement_group(
- "pnf_test1", "measure_grp_name2", SubNfState.PENDING_CREATE.value)
+ "pnf_test1", "measure_grp_name2", MgNfState.PENDING_CREATE.value)
measurement_group_service.delete_nf_to_measurement_group(
- "pnf_test1", "measure_grp_name1", SubNfState.DELETED.value)
+ "pnf_test1", "measure_grp_name1", MgNfState.DELETED.value)
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name1',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test1').one_or_none())
@@ -149,9 +139,9 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
nf_service.save_nf(nf)
db.session.commit()
measurement_group_service.apply_nf_status_to_measurement_group(
- "pnf_test2", "measure_grp_name2", SubNfState.PENDING_CREATE.value)
+ "pnf_test2", "measure_grp_name2", MgNfState.PENDING_CREATE.value)
measurement_group_service.delete_nf_to_measurement_group(
- "pnf_test2", "measure_grp_name2", SubNfState.DELETED.value)
+ "pnf_test2", "measure_grp_name2", MgNfState.DELETED.value)
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name2',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
@@ -167,10 +157,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
nf_service.save_nf(nf)
db.session.commit()
measurement_group_service.apply_nf_status_to_measurement_group(
- "pnf_test2", "measure_grp_name2", SubNfState.PENDING_CREATE.value)
+ "pnf_test2", "measure_grp_name2", MgNfState.PENDING_CREATE.value)
nf_delete_func.side_effect = Exception('delete failed')
measurement_group_service.delete_nf_to_measurement_group(
- "pnf_test2", "measure_grp_name2", SubNfState.DELETED.value)
+ "pnf_test2", "measure_grp_name2", MgNfState.DELETED.value)
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name2',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
@@ -186,7 +176,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
def test_update_nf_to_measurement_group_failure(self, mock_logger, db_commit_call):
db_commit_call.side_effect = Exception('update failed')
measurement_group_service.update_measurement_group_nf_status(
- "measure_grp_name2", SubNfState.CREATE_FAILED.value, "pnf_test2")
+ "measure_grp_name2", MgNfState.CREATE_FAILED.value, "pnf_test2")
mock_logger.assert_called_with('Failed to update nf: pnf_test2 for '
'measurement group: measure_grp_name2 due to: update failed')
@@ -195,9 +185,8 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
subscription = subscription.replace('msrmt_grp_name', new_msrmt_grp_name)
return subscription
- @patch.object(AppConfig, 'publish_to_topic')
- def test_update_admin_status_to_locking(self, mock_mr):
- super().setUpAppConf()
+ def test_update_admin_status_to_locking(self):
+ super().setUp()
sub = create_subscription_data('sub')
nf_list = create_multiple_network_function_data(['pnf_101', 'pnf_102'])
db.session.add(sub)
@@ -206,7 +195,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
measurement_group_service. \
apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[0].
measurement_group_name,
- SubNfState.CREATED.value)
+ MgNfState.CREATED.value)
db.session.commit()
measurement_group_service.update_admin_status(sub.measurement_groups[0], 'LOCKED')
meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG1')
@@ -217,11 +206,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
NfMeasureGroupRelationalModel.measurement_grp_name == meas_grp.measurement_group_name)\
.all()
for nf in meas_group_nfs:
- self.assertEqual(nf.nf_measure_grp_status, SubNfState.PENDING_DELETE.value)
+ self.assertEqual(nf.nf_measure_grp_status, MgNfState.PENDING_DELETE.value)
- @patch.object(AppConfig, 'publish_to_topic')
- def test_update_admin_status_to_locked(self, mock_mr):
- super().setUpAppConf()
+ def test_update_admin_status_to_locked(self):
+ super().setUp()
sub = create_subscription_data('sub')
db.session.add(sub)
measurement_group_service.update_admin_status(sub.measurement_groups[0], 'LOCKED')
@@ -230,15 +218,14 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
self.assertEqual(meas_grp.measurement_group_name, 'MG1')
self.assertEqual(meas_grp.administrative_state, 'LOCKED')
- @patch.object(AppConfig, 'publish_to_topic')
@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_admin_status_to_unlocked_with_no_nfs(self, mock_filter_call,
- mock_model_aai, mock_aai, mock_mr):
+ mock_model_aai, mock_aai):
mock_aai.return_value = json.loads(self.aai_response_data)
mock_model_aai.return_value = json.loads(self.good_model_info)
- super().setUpAppConf()
+ super().setUp()
sub = create_subscription_data('sub')
sub.nfs = []
db.session.add(sub)
@@ -253,17 +240,16 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
NfMeasureGroupRelationalModel.measurement_grp_name == meas_grp.measurement_group_name)\
.all()
for nf in meas_group_nfs:
- self.assertEqual(nf.nf_measure_grp_status, SubNfState.PENDING_CREATE.value)
+ self.assertEqual(nf.nf_measure_grp_status, MgNfState.PENDING_CREATE.value)
- @patch.object(AppConfig, 'publish_to_topic')
@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_admin_status_to_unlocking(self, mock_filter_call,
- mock_model_aai, mock_aai, mock_mr):
+ mock_model_aai, mock_aai):
mock_aai.return_value = json.loads(self.aai_response_data)
mock_model_aai.return_value = json.loads(self.good_model_info)
- super().setUpAppConf()
+ super().setUp()
sub = create_subscription_data('sub')
db.session.add(sub)
db.session.commit()
@@ -277,7 +263,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
NfMeasureGroupRelationalModel.measurement_grp_name == meas_grp.measurement_group_name)\
.all()
for nf in meas_group_nfs:
- self.assertEqual(nf.nf_measure_grp_status, SubNfState.PENDING_CREATE.value)
+ self.assertEqual(nf.nf_measure_grp_status, MgNfState.PENDING_CREATE.value)
def test_update_admin_status_for_missing_measurement_group(self):
try:
@@ -287,7 +273,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
'for admin status update')
def test_update_admin_status_for_data_conflict(self):
- super().setUpAppConf()
+ super().setUp()
sub = create_subscription_data('sub1')
sub.measurement_groups[0].administrative_state = 'LOCKING'
try:
@@ -298,7 +284,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
'meas group name: MG1')
def test_update_admin_status_for_same_state(self):
- super().setUpAppConf()
+ super().setUp()
sub = create_subscription_data('sub1')
try:
measurement_group_service.update_admin_status(sub.measurement_groups[0], 'UNLOCKED')
@@ -317,10 +303,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
measurement_group_service. \
apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[1].
measurement_group_name,
- SubNfState.PENDING_DELETE.value)
+ MgNfState.PENDING_DELETE.value)
db.session.commit()
measurement_group_service.lock_nf_to_meas_grp(
- "pnf_101", "MG2", SubNfState.DELETED.value)
+ "pnf_101", "MG2", MgNfState.DELETED.value)
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2',
NfMeasureGroupRelationalModel.nf_name == 'pnf_101').one_or_none())
@@ -343,10 +329,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
measurement_group_service. \
apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[1].
measurement_group_name,
- SubNfState.PENDING_DELETE.value)
+ MgNfState.PENDING_DELETE.value)
db.session.commit()
measurement_group_service.lock_nf_to_meas_grp(
- "pnf_101", "MG2", SubNfState.DELETED.value)
+ "pnf_101", "MG2", MgNfState.DELETED.value)
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2',
NfMeasureGroupRelationalModel.nf_name == 'pnf_101').one_or_none())
@@ -365,10 +351,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
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)
+ "pnf_test2", "MG2", MgNfState.PENDING_DELETE.value)
db.session.commit()
measurement_group_service.filter_nf_to_meas_grp(
- "pnf_test2", "MG2", SubNfState.DELETED.value)
+ "pnf_test2", "MG2", MgNfState.DELETED.value)
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
@@ -387,10 +373,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
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)
+ "pnf_test2", "MG2", MgNfState.PENDING_CREATE.value)
db.session.commit()
measurement_group_service.filter_nf_to_meas_grp(
- "pnf_test2", "MG2", SubNfState.CREATED.value)
+ "pnf_test2", "MG2", MgNfState.CREATED.value)
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
diff --git a/components/pm-subscription-handler/tests/services/test_nf_service.py b/components/pm-subscription-handler/tests/services/test_nf_service.py
index d5824992..2297ff8d 100644
--- a/components/pm-subscription-handler/tests/services/test_nf_service.py
+++ b/components/pm-subscription-handler/tests/services/test_nf_service.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2021 Nordix Foundation.
+# Copyright (C) 2021-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.
@@ -28,9 +28,6 @@ from mod.network_function import NetworkFunctionFilter
class NetworkFunctionServiceTestCase(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
def setUp(self):
super().setUp()
@@ -44,13 +41,6 @@ class NetworkFunctionServiceTestCase(BaseClassSetup):
'r') as data:
self.good_model_info = data.read()
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
def create_test_subs(self, new_sub_name, new_msrmt_grp_name):
subscription = self.subscription_request.replace('ExtraPM-All-gNB-R2B', new_sub_name)
subscription = subscription.replace('msrmt_grp_name', new_msrmt_grp_name)
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 a0f3297c..4129bd81 100644
--- a/components/pm-subscription-handler/tests/services/test_subscription_service.py
+++ b/components/pm-subscription-handler/tests/services/test_subscription_service.py
@@ -22,8 +22,8 @@ from unittest.mock import patch, MagicMock
from mod.api.db_models import SubscriptionModel, MeasurementGroupModel, \
NfMeasureGroupRelationalModel, NetworkFunctionModel, NfSubRelationalModel, \
convert_db_string_to_list, NetworkFunctionFilterModel
+from mod.api.services.measurement_group_service import MgNfState
from mod.network_function import NetworkFunctionFilter
-from mod.subscription import SubNfState
from mod import aai_client, db
from mod.api.custom_exception import DuplicateDataException, InvalidDataException, \
DataConflictException
@@ -34,9 +34,6 @@ from tests.base_setup import create_multiple_subscription_data
class SubscriptionServiceTestCase(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
def setUp(self):
super().setUp()
@@ -49,13 +46,6 @@ class SubscriptionServiceTestCase(BaseClassSetup):
'r') as data:
self.good_model_info = data.read()
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
def create_test_subs(self, new_sub_name, new_msrmt_grp_name):
subscription = self.subscription_request.replace('ExtraPM-All-gNB-R2B', new_sub_name)
subscription = subscription.replace('msrmt_grp_name', new_msrmt_grp_name)
@@ -84,7 +74,7 @@ class SubscriptionServiceTestCase(BaseClassSetup):
NfMeasureGroupRelationalModel.measurement_grp_name == 'msrmt_grp_name-new')).all()
for pubslished_event in msr_grp_nf_rel:
self.assertEqual(pubslished_event.nf_measure_grp_status,
- SubNfState.PENDING_CREATE.value)
+ MgNfState.PENDING_CREATE.value)
@patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None))
@patch.object(AppConfig, 'publish_to_topic')
@@ -132,6 +122,9 @@ class SubscriptionServiceTestCase(BaseClassSetup):
def test_perform_validation_existing_sub(self):
try:
+ subscription = create_subscription_data('ExtraPM-All-gNB-R2B')
+ db.session.add(subscription)
+ db.session.commit()
subscription_service.create_subscription(json.loads(self.subscription_request)
['subscription'])
except DuplicateDataException as exception:
@@ -341,10 +334,10 @@ class SubscriptionServiceTestCase(BaseClassSetup):
"No value provided for measurement group name")
def test_validate_nf_filter_with_no_filter_values(self):
- nfFilter = '{"nfNames": [],"modelInvariantIDs": [], ' \
- '"modelVersionIDs": [],"modelNames": []}'
+ nf_filter = '{"nfNames": [],"modelInvariantIDs": [], ' \
+ '"modelVersionIDs": [],"modelNames": []}'
try:
- subscription_service.validate_nf_filter(json.loads(nfFilter))
+ subscription_service.validate_nf_filter(json.loads(nf_filter))
except InvalidDataException as invalidEx:
self.assertEqual(invalidEx.args[0],
"At least one filter within nfFilter must not be empty")
@@ -423,10 +416,10 @@ class SubscriptionServiceTestCase(BaseClassSetup):
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)
+ MgNfState.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)
+ MgNfState.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
@@ -442,13 +435,13 @@ class SubscriptionServiceTestCase(BaseClassSetup):
.all()
self.assertEqual(meas_group_nfs[0].nf_name, 'pnf201')
self.assertEqual(meas_group_nfs[0].nf_measure_grp_status,
- SubNfState.PENDING_DELETE.value)
+ MgNfState.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)
+ MgNfState.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)
+ MgNfState.PENDING_CREATE.value)
meas_grp = measurement_group_service.query_meas_group_by_name('sub_01', 'msg_01')
self.assertEqual(meas_grp.administrative_state, 'FILTERING')
diff --git a/components/pm-subscription-handler/tests/test_aai_event_handler.py b/components/pm-subscription-handler/tests/test_aai_event_handler.py
index 5fc38c52..ba0e5e9d 100755
--- a/components/pm-subscription-handler/tests/test_aai_event_handler.py
+++ b/components/pm-subscription-handler/tests/test_aai_event_handler.py
@@ -20,31 +20,26 @@ import json
from os import path
from unittest.mock import patch, MagicMock
from mod.aai_event_handler import AAIEventHandler
-from mod.api.db_models import NetworkFunctionModel, NetworkFunctionFilterModel, \
- MeasurementGroupModel, SubscriptionModel
-from mod.subscription import AdministrativeState
-from tests.base_setup import BaseClassSetup
+from mod.api.db_models import NetworkFunctionModel
+from tests.base_setup import BaseClassSetup, create_subscription_data
from mod import db
class AAIEventHandlerTest(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
def setUp(self):
super().setUp()
- super().setUpAppConf()
+ subscription = create_subscription_data('aai_event_handler')
+ subscription.measurement_groups[1].administravtive_sate = 'UNLOCKED'
+ db.session.add(subscription)
+ db.session.add(subscription.measurement_groups[0])
+ db.session.add(subscription.measurement_groups[1])
+ db.session.add(subscription.network_filter)
+ db.session.add(subscription.nfs[0])
+ db.session.commit()
with open(path.join(path.dirname(__file__), 'data/mr_aai_events.json'), 'r') as data:
self.mr_aai_events = json.load(data)["mr_response"]
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
@patch('mod.pmsh_config.AppConfig.get_from_topic')
@patch('mod.network_function.NetworkFunction.set_nf_model_params')
@patch('mod.network_function.NetworkFunction.delete')
@@ -87,16 +82,14 @@ class AAIEventHandlerTest(BaseClassSetup):
apply_nfs_to_measure_grp):
mock_set_sdnc_params.return_value = True
mr_aai_mock.return_value = self.mr_aai_events
- aai_handler = AAIEventHandler(self.app)
- subscription = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B2',
- operational_policy_name='operation_policy',
- control_loop_name="control-loop",
- status=AdministrativeState.UNLOCKED.value)
- db.session.add(subscription)
- db.session.commit()
- generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B', 'msr_grp_name')
- generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B2', 'msr_grp_name2')
+ nf_to_subscription = create_subscription_data('nf_to_subscription')
+ nf_to_subscription.measurement_groups[0].measurement_group_name = 'NF_MG_ONE'
+ nf_to_subscription.measurement_groups[1].measurement_group_name = 'NF_MG_TWO'
+ db.session.add(nf_to_subscription)
+ db.session.add(nf_to_subscription.measurement_groups[0])
+ db.session.add(nf_to_subscription.network_filter)
db.session.commit()
+ aai_handler = AAIEventHandler(self.app)
aai_handler.execute()
self.assertEqual(apply_nfs_to_measure_grp.call_count, 2)
@@ -111,11 +104,9 @@ class AAIEventHandlerTest(BaseClassSetup):
mr_aai_mock.return_value = self.mr_aai_events
apply_nfs_to_measure_grp.side_effect = Exception("publish failed")
aai_handler = AAIEventHandler(self.app)
- generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B', 'msr_grp_name3')
- db.session.commit()
aai_handler.execute()
mock_logger.assert_called_with('Failed to process AAI event for '
- 'subscription: ExtraPM-All-gNB-R2B '
+ 'subscription: aai_event_handler '
'due to: publish failed')
@patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
@@ -126,21 +117,5 @@ class AAIEventHandlerTest(BaseClassSetup):
mock_set_sdnc_params.return_value = True
mr_aai_mock.side_effect = Exception("AAI failure")
aai_handler = AAIEventHandler(self.app)
- generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B', 'msr_grp_name3')
- db.session.commit()
aai_handler.execute()
mock_logger.assert_called_with('Failed to process AAI event due to: AAI failure')
-
-
-def generate_nf_filter_measure_grp(sub_name, msg_name):
- nf_filter = NetworkFunctionFilterModel(
- subscription_name=sub_name, nf_names='{^pnf.*, ^vnf.*}',
- model_invariant_ids='{}',
- model_version_ids='{}',
- model_names='{}')
- measurement_group = MeasurementGroupModel(
- subscription_name=sub_name, measurement_group_name=msg_name,
- administrative_state='UNLOCKED', file_based_gp=15, file_location='pm.xml',
- measurement_type=[], managed_object_dns_basic=[])
- db.session.add(nf_filter)
- db.session.add(measurement_group)
diff --git a/components/pm-subscription-handler/tests/test_aai_service.py b/components/pm-subscription-handler/tests/test_aai_service.py
index 97f400c1..0d0bd962 100644
--- a/components/pm-subscription-handler/tests/test_aai_service.py
+++ b/components/pm-subscription-handler/tests/test_aai_service.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.
@@ -23,30 +23,21 @@ from unittest.mock import patch
import responses
from requests import Session, HTTPError
-import mod.aai_client as aai_client
-from tests.base_setup import BaseClassSetup
+from mod import aai_client
+from mod.network_function import NetworkFunctionFilter
+from tests.base_setup import BaseClassSetup, create_subscription_data
class AaiClientTestCase(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
def setUp(self):
super().setUp()
+ self.subscription = create_subscription_data('ExtraPM-All-gNB-R2B')
with open(os.path.join(os.path.dirname(__file__), 'data/aai_xnfs.json'), 'r') as data:
self.aai_response_data = data.read()
with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data:
self.good_model_info = data.read()
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
@patch('mod.network_function.NetworkFunction.set_nf_model_params')
@patch.object(Session, 'get')
@patch.object(Session, 'put')
@@ -57,9 +48,10 @@ class AaiClientTestCase(BaseClassSetup):
mock_get_session.return_value.status_code = 200
mock_get_session.return_value.text = self.good_model_info
mock_get_sdnc_params.return_value = True
- xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter)
- self.assertEqual(self.app_conf.subscription.subscriptionName, 'ExtraPM-All-gNB-R2B')
- self.assertEqual(self.app_conf.subscription.administrativeState, 'UNLOCKED')
+ nf_filter = NetworkFunctionFilter(**self.subscription.network_filter.serialize())
+ xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf, nf_filter)
+ self.assertEqual(self.subscription.subscription_name, 'ExtraPM-All-gNB-R2B')
+ self.assertEqual(self.subscription.measurement_groups[0].administrative_state, 'UNLOCKED')
self.assertEqual(len(xnfs), 3)
@patch.object(Session, 'put')
@@ -67,7 +59,7 @@ class AaiClientTestCase(BaseClassSetup):
mock_session.return_value.status_code = 404
with mock.patch('mod.aai_client._get_all_aai_nf_data', return_value=None):
with self.assertRaises(RuntimeError):
- aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter)
+ aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.subscription.network_filter)
@responses.activate
def test_aai_client_get_all_aai_xnf_data_not_found(self):
diff --git a/components/pm-subscription-handler/tests/test_controller.py b/components/pm-subscription-handler/tests/test_controller.py
index 7b0a8b19..797666d9 100755
--- a/components/pm-subscription-handler/tests/test_controller.py
+++ b/components/pm-subscription-handler/tests/test_controller.py
@@ -28,22 +28,17 @@ 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
from mod.api.db_models import SubscriptionModel, NfMeasureGroupRelationalModel
-from mod.subscription import SubNfState
from mod.network_function import NetworkFunctionFilter
from tests.base_setup import create_subscription_data, create_multiple_subscription_data, \
create_multiple_network_function_data
from mod.api.services import measurement_group_service, nf_service, subscription_service
+from mod.api.services.measurement_group_service import MgNfState
class ControllerTestCase(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
def setUp(self):
super().setUp()
- super().setUpAppConf()
with open(os.path.join(os.path.dirname(__file__), 'data/aai_xnfs.json'), 'r') as data:
self.aai_response_data = data.read()
with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data:
@@ -52,13 +47,6 @@ class ControllerTestCase(BaseClassSetup):
'data/create_subscription_request.json'), 'r') as data:
self.subscription_request = data.read()
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
def test_status_response_healthy(self):
self.assertEqual(status()['status'], 'healthy')
@@ -90,11 +78,14 @@ class ControllerTestCase(BaseClassSetup):
NfMeasureGroupRelationalModel.measurement_grp_name == mes_grp_name)).all()
for published_event in msr_grp_nf_rel:
self.assertEqual(published_event.nf_measure_grp_status,
- SubNfState.PENDING_CREATE.value)
+ MgNfState.PENDING_CREATE.value)
self.assertEqual(response[1], 201)
def test_post_subscription_duplicate_sub(self):
# Posting the same subscription request stored in previous test to get duplicate response
+ subscription = create_subscription_data('ExtraPM-All-gNB-R2B')
+ db.session.add(subscription)
+ db.session.commit()
response = post_subscription(json.loads(self.subscription_request))
self.assertEqual(response[1], 409)
self.assertEqual(response[0], 'subscription Name: ExtraPM-All-gNB-R2B already exists.')
@@ -185,7 +176,7 @@ class ControllerTestCase(BaseClassSetup):
measurement_group_service. \
apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[0].
measurement_group_name,
- SubNfState.PENDING_CREATE.value)
+ MgNfState.PENDING_CREATE.value)
db.session.commit()
mg_with_nfs, status_code = get_meas_group_with_nfs('sub1', 'MG1')
self.assertEqual(status_code, HTTPStatus.OK.value)
@@ -305,7 +296,7 @@ class ControllerTestCase(BaseClassSetup):
measurement_group_service. \
apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[0].
measurement_group_name,
- SubNfState.CREATED.value)
+ MgNfState.CREATED.value)
db.session.commit()
response = update_admin_state('sub1', 'MG1', {'administrativeState': 'LOCKED'})
self.assertEqual(response[1], HTTPStatus.OK.value)
@@ -315,7 +306,7 @@ class ControllerTestCase(BaseClassSetup):
self.assertEqual(mg_with_nfs['measurementGroupName'], 'MG1')
self.assertEqual(mg_with_nfs['administrativeState'], 'LOCKING')
for nf in mg_with_nfs['networkFunctions']:
- self.assertEqual(nf['nfMgStatus'], SubNfState.PENDING_DELETE.value)
+ self.assertEqual(nf['nfMgStatus'], MgNfState.PENDING_DELETE.value)
@patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
@patch.object(aai_client, '_get_all_aai_nf_data')
@@ -340,7 +331,7 @@ class ControllerTestCase(BaseClassSetup):
self.assertEqual(mg_with_nfs['measurementGroupName'], 'MG2')
self.assertEqual(mg_with_nfs['administrativeState'], 'UNLOCKED')
for nf in mg_with_nfs['networkFunctions']:
- self.assertEqual(nf['nfMgStatus'], SubNfState.PENDING_CREATE.value)
+ self.assertEqual(nf['nfMgStatus'], MgNfState.PENDING_CREATE.value)
@patch('mod.api.services.measurement_group_service.update_admin_status',
MagicMock(side_effect=InvalidDataException('Bad request')))
diff --git a/components/pm-subscription-handler/tests/test_exit_handler.py b/components/pm-subscription-handler/tests/test_exit_handler.py
index c98be634..d88b4752 100755
--- a/components/pm-subscription-handler/tests/test_exit_handler.py
+++ b/components/pm-subscription-handler/tests/test_exit_handler.py
@@ -17,32 +17,31 @@
# ============LICENSE_END=====================================================
import os
from signal import SIGTERM, signal
-from unittest.mock import patch
+from unittest.mock import patch, MagicMock
+from mod import db
from mod.exit_handler import ExitHandler
-from tests.base_setup import BaseClassSetup
+from tests.base_setup import BaseClassSetup, create_subscription_data
class ExitHandlerTests(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
- @patch('mod.pmsh_utils.PeriodicTask')
- @patch('mod.pmsh_utils.PeriodicTask')
+ @patch('pmsh_service_main.PeriodicTask')
+ @patch('pmsh_service_main.PeriodicTask')
def setUp(self, mock_periodic_task_aai, mock_periodic_task_policy):
super().setUp()
+ subscription = create_subscription_data('aai_event_handler')
+ subscription.measurement_groups[1].administravtive_sate = 'UNLOCKED'
+ db.session.add(subscription)
+ db.session.add(subscription.measurement_groups[0])
+ db.session.add(subscription.measurement_groups[1])
+ db.session.add(subscription.network_filter)
+ db.session.add(subscription.nfs[0])
+ db.session.commit()
self.mock_aai_event_thread = mock_periodic_task_aai
self.mock_policy_resp_handler_thread = mock_periodic_task_policy
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
+ @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
def test_terminate_signal_successful(self):
handler = ExitHandler(periodic_tasks=[self.mock_aai_event_thread,
self.mock_policy_resp_handler_thread])
diff --git a/components/pm-subscription-handler/tests/test_network_function.py b/components/pm-subscription-handler/tests/test_network_function.py
index 3e38b9c6..d80f2c40 100755
--- a/components/pm-subscription-handler/tests/test_network_function.py
+++ b/components/pm-subscription-handler/tests/test_network_function.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.
@@ -17,7 +17,7 @@
# ============LICENSE_END=====================================================
import json
import os
-from unittest.mock import patch, Mock
+from unittest.mock import patch
from mod.network_function import NetworkFunction
from tests.base_setup import BaseClassSetup
@@ -25,10 +25,6 @@ from tests.base_setup import BaseClassSetup
class NetworkFunctionTests(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
def setUp(self):
super().setUp()
self.nf_1 = NetworkFunction(sdnc_model_name='blah', sdnc_model_version=1.0,
@@ -49,13 +45,6 @@ class NetworkFunctionTests(BaseClassSetup):
'data/aai_model_info_no_sdnc.json'), 'r') as data:
self.bad_model_info = json.loads(data.read())
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
def test_get_network_function(self):
self.nf_1.create()
nf = NetworkFunction.get('pnf_1')
@@ -82,7 +71,7 @@ class NetworkFunctionTests(BaseClassSetup):
def test_delete_network_function(self):
for nf in [self.nf_1, self.nf_2]:
- self.app_conf.subscription.add_network_function_to_subscription(nf, Mock())
+ nf.create()
nfs = NetworkFunction.get_all()
self.assertEqual(2, len(nfs))
NetworkFunction.delete(nf_name=self.nf_1.nf_name)
diff --git a/components/pm-subscription-handler/tests/test_pmsh_config.py b/components/pm-subscription-handler/tests/test_pmsh_config.py
index deb867bf..84f86fb4 100644
--- a/components/pm-subscription-handler/tests/test_pmsh_config.py
+++ b/components/pm-subscription-handler/tests/test_pmsh_config.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2021 Nordix Foundation.
+# Copyright (C) 2021-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.
@@ -15,7 +15,7 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-from unittest.mock import Mock, patch
+from unittest.mock import patch
import responses
from requests import Session
@@ -26,30 +26,15 @@ from tests.base_setup import BaseClassSetup
class PmshConfigTestCase(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
- def setUp(self):
- super().setUpAppConf()
- self.mock_app = Mock()
-
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
def test_config_get_aaf_creds(self):
- self.assertEqual(self.pmsh_app_conf.enable_tls, 'true')
- self.assertEqual(self.pmsh_app_conf.aaf_id, 'dcae@dcae.onap.org')
- self.assertEqual(self.pmsh_app_conf.aaf_pass, 'demo123456!')
+ self.assertEqual(self.app_conf.enable_tls, 'true')
+ self.assertEqual(self.app_conf.aaf_id, 'dcae@dcae.onap.org')
+ self.assertEqual(self.app_conf.aaf_pass, 'demo123456!')
def test_config_get_cert_data(self):
- self.assertEqual(self.pmsh_app_conf.key_path, '/opt/app/pmsh/etc/certs/key.pem')
- self.assertEqual(self.pmsh_app_conf.cert_path, '/opt/app/pmsh/etc/certs/cert.pem')
- self.assertEqual(self.pmsh_app_conf.ca_cert_path, '/opt/app/pmsh/etc/certs/cacert.pem')
+ self.assertEqual(self.app_conf.key_path, '/opt/app/pmsh/etc/certs/key.pem')
+ self.assertEqual(self.app_conf.cert_path, '/opt/app/pmsh/etc/certs/cert.pem')
+ self.assertEqual(self.app_conf.ca_cert_path, '/opt/app/pmsh/etc/certs/cacert.pem')
def test_singleton_instance_is_accessible_using_class_method(self):
my_singleton_instance = AppConfig.get_instance()
@@ -60,8 +45,8 @@ class PmshConfigTestCase(BaseClassSetup):
def test_mr_pub_publish_to_topic_success(self, mock_session):
mock_session.return_value.status_code = 200
with patch('requests.Session.post') as session_post_call:
- self.pmsh_app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value,
- {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"})
+ self.app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value,
+ {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"})
session_post_call.assert_called_once()
@responses.activate
@@ -70,8 +55,8 @@ class PmshConfigTestCase(BaseClassSetup):
'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS',
json={"error": "Client Error"}, status=400)
with self.assertRaises(Exception):
- self.pmsh_app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value,
- {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"})
+ self.app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value,
+ {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"})
@responses.activate
def test_mr_sub_get_from_topic_success(self):
@@ -79,7 +64,7 @@ class PmshConfigTestCase(BaseClassSetup):
'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS/'
'dcae_pmsh_cg/1?timeout=5000',
json={"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=200)
- mr_topic_data = self.pmsh_app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1)
+ mr_topic_data = self.app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1)
self.assertIsNotNone(mr_topic_data)
@responses.activate
@@ -89,4 +74,4 @@ class PmshConfigTestCase(BaseClassSetup):
'dcae_pmsh_cg/1?timeout=5000',
json={"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=400)
with self.assertRaises(Exception):
- self.pmsh_app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1)
+ self.app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1)
diff --git a/components/pm-subscription-handler/tests/test_pmsh_utils.py b/components/pm-subscription-handler/tests/test_pmsh_utils.py
deleted file mode 100644
index 57f20ddf..00000000
--- a/components/pm-subscription-handler/tests/test_pmsh_utils.py
+++ /dev/null
@@ -1,245 +0,0 @@
-# ============LICENSE_START===================================================
-# 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.
-# 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=====================================================
-from test.support import EnvironmentVarGuard
-from unittest.mock import patch, Mock
-
-import responses
-from jsonschema import ValidationError
-from requests import Session
-from tenacity import RetryError
-
-from mod import get_db_connection_url
-from mod.network_function import NetworkFunction
-from tests.base_setup import BaseClassSetup
-from tests.base_setup import get_pmsh_config
-
-
-class PmshUtilsTestCase(BaseClassSetup):
-
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
- def setUp(self):
- super().setUp()
- self.mock_app = Mock()
-
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
- def test_utils_get_mr_sub(self):
- mr_policy_sub = self.app_conf.get_mr_sub('policy_pm_subscriber')
- self.assertTrue(mr_policy_sub.aaf_id, 'dcae@dcae.onap.org')
-
- def test_utils_get_mr_sub_fails_with_invalid_name(self):
- with self.assertRaises(KeyError):
- self.app_conf.get_mr_sub('invalid_sub')
-
- def test_utils_get_mr_pub(self):
- mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher')
- self.assertTrue(mr_policy_pub.aaf_pass, 'demo123456!')
-
- def test_utils_get_mr_pub_fails_with_invalid_name(self):
- with self.assertRaises(KeyError):
- self.app_conf.get_mr_pub('invalid_pub')
-
- def test_utils_get_cert_data(self):
- self.assertEqual(self.app_conf.cert_params, ('/opt/app/pmsh/etc/certs/cert.pem',
- '/opt/app/pmsh/etc/certs/key.pem'))
-
- @patch.object(Session, 'post')
- def test_mr_pub_publish_to_topic_success(self, mock_session):
- mock_session.return_value.status_code = 200
- mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher')
- with patch('requests.Session.post') as session_post_call:
- mr_policy_pub.publish_to_topic({"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"})
- session_post_call.assert_called_once()
-
- @responses.activate
- def test_mr_pub_publish_to_topic_fail(self):
- responses.add(responses.POST,
- 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS',
- json={'error': 'Client Error'}, status=400)
- mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher')
- with self.assertRaises(Exception):
- mr_policy_pub.publish_to_topic({"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"})
-
- def test_mr_pub_publish_sub_event_data_success(self):
- mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher')
- with patch('mod.pmsh_utils._MrPub.publish_to_topic') as pub_to_topic_call:
- mr_policy_pub.publish_subscription_event_data(
- self.app_conf.subscription,
- NetworkFunction(nf_name='pnf_1',
- model_invariant_id='some-id',
- model_version_id='some-id'))
- pub_to_topic_call.assert_called_once()
-
- @responses.activate
- def test_mr_sub_get_from_topic_success(self):
- policy_mr_sub = self.app_conf.get_mr_sub('policy_pm_subscriber')
- responses.add(responses.GET,
- 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS/'
- 'dcae_pmsh_cg/1?timeout=1000',
- json={"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=200)
- mr_topic_data = policy_mr_sub.get_from_topic(1)
- self.assertIsNotNone(mr_topic_data)
-
- @responses.activate
- def test_mr_sub_get_from_topic_fail(self):
- policy_mr_sub = self.app_conf.get_mr_sub('policy_pm_subscriber')
- responses.add(responses.GET,
- 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS/'
- 'dcae_pmsh_cg/1?timeout=1000',
- json={"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=400)
- with self.assertRaises(Exception):
- policy_mr_sub.get_from_topic(1)
-
- def test_get_db_connection_url_success(self):
- self.env = EnvironmentVarGuard()
- self.env.set('PMSH_PG_URL', '1.2.3.4')
- self.env.set('PMSH_PG_USERNAME', 'pmsh')
- self.env.set('PMSH_PG_PASSWORD', 'pass')
- db_url = get_db_connection_url()
- self.assertEqual(db_url, 'postgresql+psycopg2://pmsh:pass@1.2.3.4:5432/pmsh')
-
- def test_get_db_connection_url_fail(self):
- self.env = EnvironmentVarGuard()
- self.env.set('PMSH_PG_USERNAME', 'pmsh')
- self.env.set('PMSH_PG_PASSWORD', 'pass')
- with self.assertRaises(Exception):
- get_db_connection_url()
-
- @patch('mod.logger.info')
- @patch('mod.pmsh_utils.get_all')
- def test_refresh_config_success(self, mock_cbs_client_get_all, mock_logger):
- mock_cbs_client_get_all.return_value = get_pmsh_config()
- self.app_conf.refresh_config()
- mock_logger.assert_called_with('AppConfig data has been refreshed')
-
- @patch('mod.logger.error')
- @patch('mod.pmsh_utils.get_all')
- def test_refresh_config_fail(self, mock_cbs_client_get_all, mock_logger):
- mock_cbs_client_get_all.side_effect = ValueError
- with self.assertRaises(RetryError):
- self.app_conf.refresh_config()
- mock_logger.assert_called_with('Failed to refresh PMSH AppConfig')
-
- @patch('mod.logger.debug')
- def test_utils_validate_config_subscription(self, mock_logger):
- self.app_conf.validate_sub_schema()
- mock_logger.assert_called_with("Subscription schema is valid.")
-
- @patch('mod.logger.debug')
- def test_utils_validate_config_subscription_administrativeState_locked(self, mock_logger):
- self.app_conf.subscription.administrativeState = "LOCKED"
- self.app_conf.validate_sub_schema()
- mock_logger.assert_called_with("Subscription schema is valid.")
-
- def test_utils_validate_config_subscription_administrativeState_invalid_value(self):
- self.app_conf.subscription.administrativeState = "FAILED"
- with self.assertRaises(ValidationError):
- self.app_conf.validate_sub_schema()
-
- def test_utils_validate_config_subscription_nfFilter_failed(self):
- self.app_conf.subscription.nfFilter = {}
- with self.assertRaises(ValidationError):
- self.app_conf.validate_sub_schema()
-
- def test_utils_validate_config_subscription_nfFilter_not_empty(self):
- self.app_conf.subscription.nfFilter = {
- "nfNames": [
-
- ],
- "modelInvariantIDs": [
-
- ],
- "modelVersionIDs": [
-
- ],
- "modelNames": [
-
- ]
- }
- with self.assertRaises(ValidationError):
- self.app_conf.validate_sub_schema()
-
- @patch('mod.logger.debug')
- def test_utils_validate_config_subscription_nfFilter_with_empty_property(self, mock_logger):
- self.app_conf.subscription.nfFilter = {
- "nfNames": [
- "^pnf.*",
- "^vnf.*"
- ],
- "modelInvariantIDs": [
- "7129e420-d396-4efb-af02-6b83499b12f8"
- ],
- "modelVersionIDs": [
-
- ],
- "modelNames": [
- "pnf102"
- ]
- }
- self.app_conf.validate_sub_schema()
- mock_logger.assert_called_with("Subscription schema is valid.")
-
- def test_utils_validate_config_subscription_where_measurementTypes_is_empty(self):
- self.app_conf.subscription.measurementGroups = [{
- "measurementGroup": {
- "measurementTypes": [
- ],
- "managedObjectDNsBasic": [
- {
- "DN": "dna"
- },
- {
- "DN": "dnb"
- }
- ]
- }
- }]
- with self.assertRaises(ValidationError):
- self.app_conf.validate_sub_schema()
-
- def test_utils_validate_config_subscription_where_managedObjectDNsBasic_is_empty(self):
- self.app_conf.subscription.measurementGroups = [{
- "measurementGroup": {
- "measurementTypes": [
- {
- "measurementType": "countera"
- },
- {
- "measurementType": "counterb"
- }
- ],
- "managedObjectDNsBasic": [
-
- ]
- }
- }]
- with self.assertRaises(ValidationError):
- self.app_conf.validate_sub_schema()
-
- def test_utils_validate_config_subscription_where_measurementGroups_is_empty(self):
- self.app_conf.subscription.measurementGroups = []
- with self.assertRaises(ValidationError):
- self.app_conf.validate_sub_schema()
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 d5ae5ce1..735e9381 100644
--- a/components/pm-subscription-handler/tests/test_policy_response_handler.py
+++ b/components/pm-subscription-handler/tests/test_policy_response_handler.py
@@ -18,32 +18,21 @@
from unittest.mock import patch, MagicMock
from mod import db
+from mod.api.services.measurement_group_service import MgNfState, AdministrativeState
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
from tests.base_setup import BaseClassSetup, create_subscription_data
class PolicyResponseHandlerTest(BaseClassSetup):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
@patch('mod.create_app')
def setUp(self, mock_app):
super().setUp()
- super().setUpAppConf()
self.nf = NetworkFunction(nf_name='nf1')
self.policy_response_handler = PolicyResponseHandler(mock_app)
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
@patch('mod.network_function.NetworkFunction.delete')
def test_handle_response_locked_success(self, mock_delete):
with patch.dict(policy_response_handle_functions,
@@ -64,7 +53,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.nf.nf_name, 'failed')
mock_update_sub_nf.assert_called_with(
measurement_group_name='msr_grp_name',
- status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name)
+ status=MgNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name)
@patch('mod.network_function.NetworkFunction.delete')
def test_handle_response_locking_success(self, mock_delete):
@@ -86,7 +75,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.nf.nf_name, 'failed')
mock_update_sub_nf.assert_called_with(
measurement_group_name='msr_grp_name',
- status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name)
+ status=MgNfState.DELETE_FAILED.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(self, mock_update_sub_nf):
@@ -98,7 +87,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.nf.nf_name, 'success')
mock_update_sub_nf.assert_called_with(
measurement_group_name='msr_grp_name',
- status=SubNfState.CREATED.value, nf_name=self.nf.nf_name)
+ status=MgNfState.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):
@@ -107,7 +96,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ self.nf.nf_name, "MG2", MgNfState.PENDING_CREATE.value)
db.session.commit()
self.policy_response_handler._handle_response(
'MG2',
@@ -115,7 +104,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ status=MgNfState.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):
@@ -124,7 +113,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ self.nf.nf_name, "MG2", MgNfState.PENDING_DELETE.value)
db.session.commit()
self.policy_response_handler._handle_response(
'MG2',
@@ -132,7 +121,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ status=MgNfState.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):
@@ -144,7 +133,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
self.nf.nf_name, 'failed')
mock_update_sub_nf.assert_called_with(
measurement_group_name='msr_grp_name',
- status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name)
+ status=MgNfState.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):
@@ -153,7 +142,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ self.nf.nf_name, "MG2", MgNfState.PENDING_CREATE.value)
db.session.commit()
self.policy_response_handler._handle_response(
'MG2',
@@ -161,7 +150,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ status=MgNfState.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):
@@ -170,7 +159,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ self.nf.nf_name, "MG2", MgNfState.PENDING_DELETE.value)
db.session.commit()
self.policy_response_handler._handle_response(
'MG2',
@@ -178,7 +167,7 @@ class PolicyResponseHandlerTest(BaseClassSetup):
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)
+ status=MgNfState.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',
diff --git a/components/pm-subscription-handler/tests/test_subscription.py b/components/pm-subscription-handler/tests/test_subscription.py
deleted file mode 100755
index 5c40c4fd..00000000
--- a/components/pm-subscription-handler/tests/test_subscription.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# ============LICENSE_START===================================================
-# 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.
-# 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
-import os
-from unittest.mock import patch, Mock
-
-from requests import Session
-
-import mod.aai_client as aai_client
-from mod.network_function import NetworkFunction
-from mod.subscription import Subscription
-from tests.base_setup import BaseClassSetup
-
-
-class SubscriptionTest(BaseClassSetup):
-
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
- @patch.object(Session, 'get')
- @patch.object(Session, 'put')
- def setUp(self, mock_session_put, mock_session_get):
- super().setUp()
- with open(os.path.join(os.path.dirname(__file__), 'data/aai_xnfs.json'), 'r') as data:
- self.aai_response_data = data.read()
- mock_session_put.return_value.status_code = 200
- 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()
- mock_session_get.return_value.status_code = 200
- mock_session_get.return_value.text = self.aai_model_data
- self.mock_mr_sub = Mock()
- self.mock_mr_pub = Mock()
- self.app_conf.subscription.create()
- self.xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter)
- self.sub_model = self.app_conf.subscription.get()
-
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
- def test_sub_measurement_group(self):
- self.assertEqual(len(self.app_conf.subscription.measurementGroups), 2)
-
- def test_sub_file_location(self):
- self.assertEqual(self.app_conf.subscription.fileLocation, '/pm/pm.xml')
-
- def test_get_subscription(self):
- sub_name = 'ExtraPM-All-gNB-R2B'
- new_sub = self.app_conf.subscription.get()
- self.assertEqual(sub_name, new_sub.subscription_name)
-
- def test_get_nf_names_per_sub(self):
- self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[0],
- self.sub_model)
- self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[1],
- self.sub_model)
-
- def test_add_duplicate_network_functions_per_subscription(self):
- self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[0],
- self.sub_model)
- nf_subs = Subscription.get_all_nfs_subscription_relations()
- self.assertEqual(1, len(nf_subs))
- self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[0],
- self.sub_model)
- nf_subs = Subscription.get_all_nfs_subscription_relations()
- self.assertEqual(1, len(nf_subs))
-
- def test_update_subscription_status(self):
- self.app_conf.subscription.administrativeState = 'new_status'
- self.app_conf.subscription.update_subscription_status()
- sub = self.app_conf.subscription.get()
-
- self.assertEqual('new_status', sub.status)
-
- def test_update_sub_nf_status(self):
- sub_name = 'ExtraPM-All-gNB-R2B'
- for nf in self.xnfs:
- self.app_conf.subscription.add_network_function_to_subscription(nf, self.sub_model)
- sub_nfs = Subscription.get_all_nfs_subscription_relations()
- self.assertEqual('PENDING_CREATE', sub_nfs[0].nf_sub_status)
-
- Subscription.update_sub_nf_status(sub_name, 'Active', 'pnf_23')
- sub_nfs = Subscription.get_all_nfs_subscription_relations()
- self.assertEqual('PENDING_CREATE', sub_nfs[0].nf_sub_status)
- self.assertEqual('PENDING_CREATE', sub_nfs[1].nf_sub_status)
-
- @patch('mod.subscription.Subscription.add_network_function_to_subscription')
- @patch('mod.subscription.Subscription.update_sub_nf_status')
- def test_process_activate_subscription(self, mock_update_sub_nf, mock_add_nfs):
- self.app_conf.subscription.create_subscription_on_nfs([list(self.xnfs)[0]],
- self.mock_mr_pub)
-
- mock_add_nfs.assert_called()
- self.assertTrue(self.mock_mr_pub.publish_subscription_event_data.called)
- mock_update_sub_nf.assert_called_with(self.app_conf.subscription.subscriptionName,
- 'PENDING_CREATE', list(self.xnfs)[0].nf_name)
-
- @patch('mod.subscription.Subscription.get_network_functions')
- @patch('mod.subscription.Subscription.update_sub_nf_status')
- def test_process_deactivate_subscription(self, mock_update_sub_nf, mock_get_nfs):
- self.app_conf.subscription.administrativeState = 'LOCKED'
- mock_get_nfs.return_value = [list(self.xnfs)[0]]
- self.app_conf.subscription.delete_subscription_from_nfs(self.xnfs, self.mock_mr_pub)
- self.assertTrue(self.mock_mr_pub.publish_subscription_event_data.called)
- self.assertEqual(mock_update_sub_nf.call_count, 3)
-
- def test_activate_subscription_exception(self):
- self.assertRaises(Exception, self.app_conf.subscription.create_subscription_on_nfs,
- [list(self.xnfs)[0]], 'not_mr_pub', 'app_config')
-
- def test_prepare_subscription_event(self):
- with open(os.path.join(os.path.dirname(__file__),
- 'data/pm_subscription_event.json'), 'r') as data:
- expected_sub_event = json.load(data)
- nf = NetworkFunction(nf_name='pnf_1',
- ipv4_address='204.120.0.15',
- ipv6_address='',
- model_invariant_id='some-id',
- model_version_id='some-id')
- nf.sdnc_model_name = 'some-name'
- nf.sdnc_model_version = 'some-version'
- actual_sub_event = self.app_conf.subscription.prepare_subscription_event(nf)
- print(actual_sub_event)
- self.assertEqual(expected_sub_event, actual_sub_event)
-
- def test_prepare_subscription_event_with_ipv6(self):
- with open(os.path.join(os.path.dirname(__file__),
- 'data/pm_subscription_event.json'), 'r') as data:
- expected_sub_event = json.load(data)
- expected_sub_event['ipAddress'] = '2001:db8:3333:4444:5555:6666:7777:8888'
- nf = NetworkFunction(nf_name='pnf_1',
- ipv4_address='204.120.0.15',
- ipv6_address='2001:db8:3333:4444:5555:6666:7777:8888',
- model_invariant_id='some-id',
- model_version_id='some-id')
- nf.sdnc_model_name = 'some-name'
- nf.sdnc_model_version = 'some-version'
- actual_sub_event = self.app_conf.subscription.prepare_subscription_event(nf)
- print(actual_sub_event)
- self.assertEqual(expected_sub_event, actual_sub_event)
-
- def test_get_network_functions(self):
- for nf in self.xnfs:
- self.app_conf.subscription.add_network_function_to_subscription(nf, self.sub_model)
- nfs = self.app_conf.subscription.get_network_functions()
-
- self.assertEqual(3, len(nfs))
- self.assertIsInstance(nfs[0], NetworkFunction)
diff --git a/components/pm-subscription-handler/tests/test_subscription_handler.py b/components/pm-subscription-handler/tests/test_subscription_handler.py
deleted file mode 100644
index 1843eb44..00000000
--- a/components/pm-subscription-handler/tests/test_subscription_handler.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# ============LICENSE_START===================================================
-# 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.
-# 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=====================================================
-from unittest.mock import patch, Mock, MagicMock
-
-from mod.api.db_models import NetworkFunctionModel
-from mod.network_function import NetworkFunction
-from mod.subscription import AdministrativeState
-from mod.subscription_handler import SubscriptionHandler
-from tests.base_setup import BaseClassSetup, get_pmsh_config
-
-
-class SubscriptionHandlerTest(BaseClassSetup):
- nfs = [
- NetworkFunction(nf_name='pnf_1', model_invariant_id='some-id', model_version_id='some-id'),
- NetworkFunction(nf_name='pnf_2', model_invariant_id='some-id', model_version_id='some-id')]
-
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
-
- @patch('mod.pmsh_utils._MrSub')
- @patch('mod.pmsh_utils._MrPub')
- def setUp(self, mock_mr_pub, mock_mr_sub):
- super().setUp()
- self.mock_mr_pub = mock_mr_pub
- self.mock_mr_sub = mock_mr_sub
- self.mock_policy_event_thread = Mock()
-
- def tearDown(self):
- super().tearDown()
-
- @classmethod
- def tearDownClass(cls):
- super().tearDownClass()
-
- @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription.Subscription.get_local_sub_admin_state')
- @patch('mod.logger.info')
- @patch('mod.aai_client.get_pmsh_nfs_from_aai')
- def test_execute_no_change_of_state(self, mock_get_aai, mock_logger, mock_get_sub_status):
- mock_get_sub_status.return_value = AdministrativeState.UNLOCKED.value
- mock_get_aai.return_value = self.nfs
- sub_handler = SubscriptionHandler(self.mock_mr_pub,
- self.mock_mr_sub, self.app, self.app_conf)
- sub_handler.execute()
- mock_logger.assert_called_with('Administrative State did not change '
- 'in the app config: UNLOCKED')
-
- @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription.Subscription.get_local_sub_admin_state')
- @patch('mod.subscription.Subscription.create_subscription_on_nfs')
- @patch('mod.aai_client.get_pmsh_nfs_from_aai')
- def test_execute_change_of_state_to_unlocked(self, mock_get_aai, mock_activate_sub,
- mock_get_sub_status):
- mock_get_aai.return_value = self.nfs
- mock_get_sub_status.return_value = AdministrativeState.LOCKED.value
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- self.assertEqual(AdministrativeState.UNLOCKED.value,
- self.app_conf.subscription.administrativeState)
- mock_activate_sub.assert_called_with(self.nfs, self.mock_mr_pub)
-
- @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs))
- @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription.Subscription.get_local_sub_admin_state')
- @patch('mod.subscription.Subscription.delete_subscription_from_nfs')
- def test_execute_change_of_state_to_locked(self, mock_deactivate_sub, mock_get_sub_status):
- mock_get_sub_status.return_value = AdministrativeState.UNLOCKED.value
- self.app_conf.subscription.administrativeState = AdministrativeState.LOCKED.value
- self.app_conf.subscription.update_subscription_status()
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- mock_deactivate_sub.assert_called_with(self.nfs, self.mock_mr_pub)
-
- @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription.Subscription.create_subscription_on_nfs')
- @patch('mod.logger.error')
- @patch('mod.aai_client.get_pmsh_nfs_from_aai')
- def test_execute_exception(self, mock_get_aai, mock_logger, mock_activate_sub):
- mock_get_aai.return_value = self.nfs
- mock_activate_sub.side_effect = Exception
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- mock_logger.assert_called_with('Error occurred during the activation/deactivation process ',
- exc_info=True)
-
- @patch('mod.network_function.NetworkFunction.get',
- MagicMock(return_value=NetworkFunctionModel(nf_name='pnf_1',
- model_invariant_id='some-id',
- model_version_id='some-id',
- ipv4_address='ip_address4',
- ipv6_address='ip_address6',
- model_name='model_name',
- sdnc_model_name='sdnc_model_name',
- sdnc_model_version='sdnc_model_version')))
- @patch('mod.subscription.Subscription.get_delete_failed_nfs', MagicMock(return_value=nfs))
- @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs))
- @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription.Subscription.get_local_sub_admin_state')
- @patch('mod.subscription.Subscription.delete_subscription_from_nfs')
- @patch('mod.network_function.NetworkFunction.increment_retry_count')
- def test_execute_change_of_state_to_locking_retry_delete(self, mock_retry_inc, mock_delete_sub,
- mock_get_sub_status):
- mock_get_sub_status.return_value = AdministrativeState.LOCKING.value
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- self.assertEqual(mock_delete_sub.call_count, 2)
- self.assertEqual(mock_retry_inc.call_count, 2)
-
- @patch('mod.subscription.Subscription.get_delete_failed_nfs', MagicMock(return_value=[]))
- @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs))
- @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription.Subscription.get_local_sub_admin_state')
- @patch('mod.subscription.Subscription.update_subscription_status')
- def test_execute_change_of_state_to_locking_success(self, mock_update_sub,
- mock_get_sub_status):
- mock_get_sub_status.return_value = AdministrativeState.LOCKING.value
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- mock_update_sub.assert_called_once()
-
- @patch('mod.network_function.NetworkFunction.get',
- MagicMock(return_value=NetworkFunctionModel(nf_name='pnf_1',
- model_invariant_id='some-id',
- model_version_id='some-id',
- ipv4_address='ip_address4',
- ipv6_address='ip_address6',
- model_name='model_name',
- sdnc_model_name='sdnc_model_name',
- sdnc_model_version='sdnc_model_version',
- retry_count=3)))
- @patch('mod.subscription.Subscription.get_delete_failed_nfs', MagicMock(return_value=[nfs[0]]))
- @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs[0]))
- @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription.Subscription.get_local_sub_admin_state')
- @patch('mod.network_function.NetworkFunction.delete')
- def test_execute_change_of_state_to_locking_retry_failed(self, mock_nf_del,
- mock_get_sub_status):
- mock_get_sub_status.return_value = AdministrativeState.LOCKING.value
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- mock_nf_del.assert_called_once()
-
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config',
- MagicMock(return_value=get_pmsh_config('data/cbs_invalid_data.json')))
- @patch('mod.subscription_handler.SubscriptionHandler._check_state_change')
- def test_execute_invalid_schema(self, mock_change_state_check):
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- mock_change_state_check.assert_not_called()
-
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config',
- MagicMock(return_value=get_pmsh_config()))
- @patch('mod.subscription_handler.SubscriptionHandler._check_state_change')
- def test_execute_valid_schema(self, mock_change_state_check):
- sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app,
- self.app_conf)
- sub_handler.execute()
- mock_change_state_check.assert_called_once()