summaryrefslogtreecommitdiffstats
path: root/components/pm-subscription-handler
diff options
context:
space:
mode:
authorefiacor <fiachra.corcoran@est.tech>2020-09-08 16:26:50 +0100
committerefiacor <fiachra.corcoran@est.tech>2020-09-10 13:00:50 +0100
commit0080fa4309a40599b7d239b53bab9a74182ae500 (patch)
tree17af572ecb3e03a3be7115d41e3097985773ed5a /components/pm-subscription-handler
parent2e3c407d0fcf8c73c5fd6714d6013e37930c92cb (diff)
[PMSSH] Add sdnc model info to event publish1.1.1-pmsh
Signed-off-by: efiacor <fiachra.corcoran@est.tech> Change-Id: I89e25e99a2d541a29cf4a8dde986fab5b1812c9e Issue-ID: DCAEGEN2-2405
Diffstat (limited to 'components/pm-subscription-handler')
-rwxr-xr-xcomponents/pm-subscription-handler/Changelog.md1
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/aai_client.py114
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py36
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/api/db_models.py35
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/network_function.py68
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py10
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/subscription.py77
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py4
-rwxr-xr-xcomponents/pm-subscription-handler/tests/base_setup.py57
-rw-r--r--components/pm-subscription-handler/tests/data/aai_model_info.json36
-rw-r--r--components/pm-subscription-handler/tests/data/aai_model_info_no_sdnc.json34
-rw-r--r--components/pm-subscription-handler/tests/data/cbs_data_1.json2
-rw-r--r--components/pm-subscription-handler/tests/data/filter_test_data.json50
-rwxr-xr-xcomponents/pm-subscription-handler/tests/data/pm_subscription_event.json2
-rwxr-xr-xcomponents/pm-subscription-handler/tests/log_config.yaml9
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_aai_event_handler.py57
-rw-r--r--components/pm-subscription-handler/tests/test_aai_service.py88
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_controller.py65
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_exit_handler.py38
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_network_function.py77
-rw-r--r--components/pm-subscription-handler/tests/test_network_function_filter.py39
-rw-r--r--components/pm-subscription-handler/tests/test_pmsh_utils.py105
-rw-r--r--components/pm-subscription-handler/tests/test_policy_response_handler.py31
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_subscription.py86
-rw-r--r--components/pm-subscription-handler/tests/test_subscription_handler.py49
25 files changed, 636 insertions, 534 deletions
diff --git a/components/pm-subscription-handler/Changelog.md b/components/pm-subscription-handler/Changelog.md
index 8f4ce1b5..1d97b586 100755
--- a/components/pm-subscription-handler/Changelog.md
+++ b/components/pm-subscription-handler/Changelog.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Changed
* Moved to alpine base image (DCAEGEN2-2292)
* Added model-invariant-id and model-version-id to filter (DCAEGEN2-2151)
+* Added support for multiple CDS blueprints (DCAEGEN2-2405)
## [1.1.0]
### Changed
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 c8dea9f7..73bf8d4c 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/aai_client.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/aai_client.py
@@ -21,9 +21,9 @@ 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.network_function import NetworkFunction
-from mod.pmsh_utils import mdc_handler
def get_pmsh_nfs_from_aai(app_conf):
@@ -34,21 +34,20 @@ def get_pmsh_nfs_from_aai(app_conf):
app_conf (AppConfig): the AppConfig object.
Returns:
- set(NetworkFunctions): set of NetworkFunctions.
+ NetworkFunctions (list): list of NetworkFunctions.
Raises:
RuntimeError: if AAI Network Function data cannot be retrieved.
"""
aai_nf_data = _get_all_aai_nf_data(app_conf)
if aai_nf_data:
- nfs = _filter_nf_data(aai_nf_data, app_conf.nf_filter)
+ nfs = _filter_nf_data(aai_nf_data, app_conf)
else:
raise RuntimeError('Failed to get data from AAI')
return nfs
-@mdc_handler
-def _get_all_aai_nf_data(app_conf, **kwargs):
+def _get_all_aai_nf_data(app_conf):
"""
Return queried nf data from the AAI service.
@@ -61,24 +60,19 @@ def _get_all_aai_nf_data(app_conf, **kwargs):
nf_data = None
try:
session = requests.Session()
- aai_endpoint = f'{_get_aai_service_url()}{"/aai/v19/query"}'
+ aai_named_query_endpoint = f'{_get_aai_service_url()}{"/query"}'
logger.info('Fetching XNFs from AAI.')
- headers = {'accept': 'application/json',
- 'content-type': 'application/json',
- 'x-fromappid': 'dcae-pmsh',
- 'x-transactionid': kwargs['request_id'],
- 'InvocationID': kwargs['invocation_id'],
- 'RequestID': kwargs['request_id']}
- json_data = """
- {'start':
- ['network/pnfs',
- 'network/generic-vnfs']
- }"""
+ headers = _get_aai_request_headers()
+ data = """
+ {'start':
+ ['network/pnfs',
+ 'network/generic-vnfs']
+ }"""
params = {'format': 'simple', 'nodesOnly': 'true'}
- response = session.put(aai_endpoint, headers=headers,
+ 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')),
- data=json_data, params=params,
+ data=data, params=params,
verify=(app_conf.ca_cert_path if app_conf.enable_tls else False),
cert=(app_conf.cert_params if app_conf.enable_tls else None))
response.raise_for_status()
@@ -103,39 +97,89 @@ def _get_aai_service_url():
"""
try:
aai_ssl_port = environ['AAI_SERVICE_PORT']
- return f'https://aai:{aai_ssl_port}'
+ return f'https://aai:{aai_ssl_port}/aai/v20'
except KeyError as e:
logger.error(f'Failed to get AAI env var: {e}', exc_info=True)
raise
-def _filter_nf_data(nf_data, nf_filter):
+@mod.pmsh_utils.mdc_handler
+def _get_aai_request_headers(**kwargs):
+ return {'accept': 'application/json',
+ 'content-type': 'application/json',
+ 'x-fromappid': 'dcae-pmsh',
+ 'x-transactionid': kwargs['request_id'],
+ 'InvocationID': kwargs['invocation_id'],
+ 'RequestID': kwargs['request_id']}
+
+
+def _filter_nf_data(nf_data, app_conf):
"""
Returns a list of filtered NetworkFunctions using the nf_filter.
Args:
- nf_data(dict): the nf json data from AAI.
- nf_filter(NetworkFunctionFilter): the NetworkFunctionFilter to be applied.
+ nf_data (dict): the nf json data from AAI.
+ app_conf (AppConfig): the AppConfig object.
Returns:
- set(NetworkFunctions): a set of filtered NetworkFunctions.
+ NetworkFunction (list): a list of filtered NetworkFunction Objects.
Raises:
KeyError: if AAI data cannot be parsed.
"""
- nf_set = set()
+ nf_list = []
try:
for nf in nf_data['results']:
+ if nf['properties'].get('orchestration-status') != 'Active':
+ continue
name_identifier = 'pnf-name' if nf['node-type'] == 'pnf' else 'vnf-name'
- orchestration_status = nf['properties'].get('orchestration-status')
- model_invariant_id = nf['properties'].get('model-invariant-id')
- model_version_id = nf['properties'].get('model-version-id')
- if nf_filter.is_nf_in_filter(nf['properties'].get(name_identifier),
- model_invariant_id, model_version_id, orchestration_status):
- nf_set.add(NetworkFunction(
- nf_name=nf['properties'].get(name_identifier),
- orchestration_status=orchestration_status))
+ new_nf = mod.network_function.NetworkFunction(
+ nf_name=nf['properties'].get(name_identifier),
+ model_invariant_id=nf['properties'].get('model-invariant-id'),
+ model_version_id=nf['properties'].get('model-version-id'))
+ if not new_nf.set_sdnc_params(app_conf):
+ continue
+ if app_conf.nf_filter.is_nf_in_filter(new_nf):
+ nf_list.append(new_nf)
except KeyError as e:
logger.error(f'Failed to parse AAI data: {e}', exc_info=True)
raise
- return nf_set
+ return nf_list
+
+
+def get_aai_model_data(app_conf, model_invariant_id, model_version_id, nf_name):
+ """
+ Get the sdnc_model info for the xNF from AAI.
+
+ Args:
+ model_invariant_id (str): the AAI model-invariant-id
+ model_version_id (str): the AAI model-version-id
+ app_conf (AppConfig): the AppConfig object.
+ nf_name (str): The xNF 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_params 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
diff --git a/components/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py b/components/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py
index 92369322..61b42b52 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py
@@ -58,28 +58,26 @@ def process_aai_events(mr_sub, mr_pub, app, app_conf):
entity_type = entry['event-header']['entity-type']
xnf_name = aai_entity['pnf-name'] if entity_type == XNFType.PNF.value \
else aai_entity['vnf-name']
- new_status = aai_entity['orchestration-status']
- model_invariant_id = aai_entity['model-invariant-id']
- model_version_id = aai_entity['model-version-id']
-
- if app_conf.nf_filter.is_nf_in_filter(xnf_name, model_invariant_id, model_version_id, new_status):
- _process_event(action, new_status, xnf_name, mr_pub, app_conf)
+ if aai_entity['orchestration-status'] != 'Active':
+ logger.info(f'Skipping XNF {xnf_name} as its orchestration-status '
+ f'is not "Active"')
+ continue
+ nf = NetworkFunction(nf_name=xnf_name,
+ model_invariant_id=aai_entity['model-invariant-id'],
+ model_version_id=aai_entity['model-version-id'])
+ if not nf.set_sdnc_params(app_conf):
+ continue
+ if app_conf.nf_filter.is_nf_in_filter(nf):
+ _process_event(action, nf, mr_pub, app_conf)
except Exception as e:
logger.error(f'Failed to process AAI event: {e}', exc_info=True)
-def _process_event(action, new_status, xnf_name, mr_pub, app_conf):
+def _process_event(action, nf, mr_pub, app_conf):
if action == AAIEvent.UPDATE.value:
- logger.info(f'Update event found for network function {xnf_name}')
- local_xnf = NetworkFunction.get(xnf_name)
-
- if local_xnf is None:
- app_conf.subscription.activate_subscription([NetworkFunction(
- nf_name=xnf_name, orchestration_status=new_status)], mr_pub, app_conf)
- else:
- logger.debug(f"Update Event for network function {xnf_name} will not be processed "
- f" as it's state is set to {local_xnf.orchestration_status}.")
+ logger.info(f'Update event found for network function {nf.nf_name}')
+ app_conf.subscription.activate_subscription([nf], mr_pub, app_conf)
elif action == AAIEvent.DELETE.value:
- logger.info(f'Delete event found for network function {xnf_name}')
- NetworkFunction.delete(nf_name=xnf_name)
- logger.info(f'{xnf_name} successfully deleted.')
+ logger.info(f'Delete event found for network function {nf.nf_name}')
+ NetworkFunction.delete(nf_name=nf.nf_name)
+ logger.info(f'{nf.nf_name} successfully deleted.')
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py b/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py
index 1d6f72b3..ff172d1c 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py
@@ -56,19 +56,34 @@ class NetworkFunctionModel(db.Model):
__tablename__ = 'network_functions'
id = Column(Integer, primary_key=True, autoincrement=True)
nf_name = Column(String(100), unique=True)
- orchestration_status = Column(String(100))
+ model_invariant_id = Column(String(100))
+ model_version_id = Column(String(100))
+ sdnc_model_name = Column(String(100))
+ sdnc_model_version = Column(String(100))
subscriptions = relationship(
'NfSubRelationalModel',
cascade='all, delete-orphan',
backref='nf')
- def __init__(self, nf_name, orchestration_status):
+ def __init__(self, nf_name, model_invariant_id, model_version_id, sdnc_model_name=None,
+ sdnc_model_version=None):
self.nf_name = nf_name
- self.orchestration_status = orchestration_status
+ self.model_invariant_id = model_invariant_id
+ self.model_version_id = model_version_id
+ self.sdnc_model_name = sdnc_model_name
+ self.sdnc_model_version = sdnc_model_version
def __repr__(self):
- return f'nf_name: {self.nf_name}, orchestration_status: {self.orchestration_status}'
+ return str(self.to_nf())
+
+ def to_nf(self):
+ from mod.network_function import NetworkFunction
+ return NetworkFunction(**{'nf_name': self.nf_name,
+ 'model_invariant_id': self.model_invariant_id,
+ 'model_version_id': self.model_version_id,
+ 'sdnc_model_name': self.sdnc_model_name,
+ 'sdnc_model_version': self.sdnc_model_version})
class NfSubRelationalModel(db.Model):
@@ -101,7 +116,11 @@ class NfSubRelationalModel(db.Model):
'nf_sub_status': self.nf_sub_status}
def serialize_nf(self):
- nf_orch_status = NetworkFunctionModel.query.filter(
- NetworkFunctionModel.nf_name == self.nf_name).one_or_none().orchestration_status
- return {'nf_name': self.nf_name, 'orchestration_status': nf_orch_status,
- 'nf_sub_status': self.nf_sub_status}
+ nf = NetworkFunctionModel.query.filter(
+ NetworkFunctionModel.nf_name == self.nf_name).one_or_none()
+ return {'nf_name': self.nf_name,
+ 'nf_sub_status': self.nf_sub_status,
+ 'model_invariant_id': nf.model_invariant_id,
+ 'model_version_id': nf.model_version_id,
+ 'sdnc_model_name': nf.sdnc_model_name,
+ 'sdnc_model_version': nf.sdnc_model_version}
diff --git a/components/pm-subscription-handler/pmsh_service/mod/network_function.py b/components/pm-subscription-handler/pmsh_service/mod/network_function.py
index 62cd546f..fd940385 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/network_function.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/network_function.py
@@ -18,6 +18,7 @@
import re
+import mod.aai_client
from mod import logger, db
from mod.api.db_models import NetworkFunctionModel
@@ -26,21 +27,34 @@ class NetworkFunction:
def __init__(self, **kwargs):
""" Object representation of the NetworkFunction. """
self.nf_name = kwargs.get('nf_name')
- self.orchestration_status = kwargs.get('orchestration_status')
+ self.model_invariant_id = kwargs.get('model_invariant_id')
+ self.model_version_id = kwargs.get('model_version_id')
+ self.sdnc_model_name = None
+ self.sdnc_model_version = None
@classmethod
def nf_def(cls):
- return cls(nf_name=None, orchestration_status=None)
+ return cls(nf_name=None, model_invariant_id=None, model_version_id=None,
+ sdnc_model_name=None, sdnc_model_version=None)
def __str__(self):
- return f'nf-name: {self.nf_name}, orchestration-status: {self.orchestration_status}'
+ return f'nf-name: {self.nf_name}, ' \
+ f'model-invariant-id: {self.model_invariant_id}, ' \
+ f'model-version-id: {self.model_version_id}, ' \
+ f'sdnc-model-name: {self.sdnc_model_name}, ' \
+ f'sdnc-model-version: {self.sdnc_model_version}'
def __eq__(self, other):
- return self.nf_name == other.nf_name and \
- self.orchestration_status == other.orchestration_status
+ return \
+ self.nf_name == other.nf_name and \
+ self.model_invariant_id == other.model_invariant_id and \
+ self.model_version_id == other.model_version_id and \
+ self.sdnc_model_name == other.sdnc_model_name and \
+ self.sdnc_model_version == other.sdnc_model_version
def __hash__(self):
- return hash((self.nf_name, self.orchestration_status))
+ return hash((self.nf_name, self.model_invariant_id,
+ self.model_version_id, self.sdnc_model_name, self.sdnc_model_version))
def create(self):
""" Creates a NetworkFunction database entry """
@@ -49,7 +63,10 @@ class NetworkFunction:
if existing_nf is None:
new_nf = NetworkFunctionModel(nf_name=self.nf_name,
- orchestration_status=self.orchestration_status)
+ model_invariant_id=self.model_invariant_id,
+ model_version_id=self.model_version_id,
+ sdnc_model_name=self.sdnc_model_name,
+ sdnc_model_version=self.sdnc_model_version)
db.session.add(new_nf)
db.session.commit()
logger.info(f'Network Function {new_nf.nf_name} successfully created.')
@@ -59,6 +76,23 @@ class NetworkFunction:
f' returning this network function..')
return existing_nf
+ def set_sdnc_params(self, app_conf):
+ params_set = True
+ try:
+ sdnc_model_data = mod.aai_client.get_aai_model_data(app_conf, self.model_invariant_id,
+ self.model_version_id, self.nf_name)
+ try:
+ self.sdnc_model_name = sdnc_model_data['sdnc-model-name']
+ self.sdnc_model_version = sdnc_model_data['sdnc-model-version']
+ return params_set
+ except KeyError as e:
+ logger.info(f'Skipping NF {self.nf_name} as there is no '
+ f'sdnc-model data associated in AAI: {e}', exc_info=True)
+ return not params_set
+ except Exception as e:
+ logger.error(f'Failed to get sdnc-model info for XNFs from AAI: {e}', exc_info=True)
+ return not params_set
+
@staticmethod
def get(nf_name):
""" Retrieves a network function
@@ -90,33 +124,27 @@ class NetworkFunction:
db.session.commit()
-
class NetworkFunctionFilter:
def __init__(self, **kwargs):
self.nf_names = kwargs.get('nfNames')
- self.model_invariant_ids = kwargs.get('modelInvariantUUIDs')
+ self.model_invariant_ids = kwargs.get('modelInvariantIDs')
self.model_version_ids = kwargs.get('modelVersionIDs')
self.regex_matcher = re.compile('|'.join(raw_regex for raw_regex in self.nf_names))
- def is_nf_in_filter(self, nf_name, model_invariant_id, model_version_id, orchestration_status):
- """Match the nf name against regex values in Subscription.nfFilter.nfNames
+ def is_nf_in_filter(self, nf):
+ """Match the nf fields against values in Subscription.nfFilter
Args:
- nf_name (str): the AAI nf name.
- invariant_uuid (str): the AAI model-invariant-id
- uuid (str): the AAI model-version-id
- orchestration_status (str): orchestration status of the nf
+ nf (NetworkFunction): The NF to be filtered.
Returns:
bool: True if matched, else False.
"""
match = True
- if orchestration_status != 'Active':
- match = False
- if self.nf_names and self.regex_matcher.search(nf_name) is None:
+ if self.nf_names and self.regex_matcher.search(nf.nf_name) is None:
match = False
- if self.model_invariant_ids and not model_invariant_id in self.model_invariant_ids:
+ if self.model_invariant_ids and nf.model_invariant_id not in self.model_invariant_ids:
match = False
- if self.model_version_ids and not model_version_id in self.model_version_ids:
+ if self.model_version_ids and nf.model_version_id not in self.model_version_ids:
match = False
return match
diff --git a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py b/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
index fd24fca9..24eade98 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py
@@ -25,8 +25,8 @@ from onaplogging.mdcContext import MDC
from requests.auth import HTTPBasicAuth
from tenacity import wait_fixed, stop_after_attempt, retry, retry_if_exception_type
+import mod.network_function
from mod import logger
-from mod.network_function import NetworkFunctionFilter
from mod.subscription import Subscription
@@ -77,7 +77,7 @@ class AppConfig:
self.operational_policy_name = conf['config'].get('operational_policy_name')
self.control_loop_name = conf['config'].get('control_loop_name')
self.subscription = Subscription(**conf['policy']['subscription'])
- self.nf_filter = NetworkFunctionFilter(**self.subscription.nfFilter)
+ self.nf_filter = mod.network_function.NetworkFunctionFilter(**self.subscription.nfFilter)
def __new__(cls, *args, **kwargs):
if AppConfig.INSTANCE is None:
@@ -223,17 +223,17 @@ class _MrPub(_DmaapMrClient):
except Exception as e:
raise e
- def publish_subscription_event_data(self, subscription, xnf_name, app_conf):
+ def publish_subscription_event_data(self, subscription, nf, app_conf):
"""
Update the Subscription dict with xnf and policy name then publish to DMaaP MR topic.
Args:
subscription (Subscription): the `Subscription` <Subscription> object.
- xnf_name (str): the xnf to include in the event.
+ nf (NetworkFunction): the NetworkFunction to include in the event.
app_conf (AppConfig): the application configuration.
"""
try:
- subscription_event = subscription.prepare_subscription_event(xnf_name, app_conf)
+ subscription_event = subscription.prepare_subscription_event(nf, app_conf)
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)
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription.py b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
index 97bfc401..21e2399d 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/subscription.py
@@ -19,7 +19,6 @@ from enum import Enum
from mod import db, logger
from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, NetworkFunctionModel
-from mod.network_function import NetworkFunction
class SubNfState(Enum):
@@ -94,30 +93,11 @@ class Subscription:
logger.error(f'Failed to update status of subscription: {self.subscriptionName}: {e}',
exc_info=True)
- def delete_subscription(self):
- """ Deletes a subscription and all its association from the database. A network function
- that is only associated with the subscription being removed will also be deleted."""
- try:
- subscription = SubscriptionModel.query.filter(
- SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
- if subscription:
- for nf_relationship in subscription.nfs:
- other_nf_relationship = NfSubRelationalModel.query.filter(
- NfSubRelationalModel.subscription_name != self.subscriptionName,
- NfSubRelationalModel.nf_name == nf_relationship.nf_name).one_or_none()
- if not other_nf_relationship:
- db.session.delete(nf_relationship.nf)
- db.session.delete(subscription)
- db.session.commit()
- except Exception as e:
- logger.error(f'Failed to delete subscription: {self.subscriptionName} '
- f'and it\'s relations from the DB: {e}', exc_info=True)
-
- def prepare_subscription_event(self, xnf_name, app_conf):
+ def prepare_subscription_event(self, nf, app_conf):
"""Prepare the sub event for publishing
Args:
- xnf_name: the AAI xnf name.
+ nf (NetworkFunction): the AAI nf.
app_conf (AppConfig): the application configuration.
Returns:
@@ -125,14 +105,16 @@ class Subscription:
"""
try:
clean_sub = {k: v for k, v in self.__dict__.items() if k != 'nfFilter'}
- sub_event = {'nfName': xnf_name, 'policyName': app_conf.operational_policy_name,
+ sub_event = {'nfName': nf.nf_name, 'blueprintName': nf.sdnc_model_name,
+ 'blueprintVersion': nf.sdnc_model_version,
+ 'policyName': app_conf.operational_policy_name,
'changeType': 'DELETE'
if self.administrativeState == AdministrativeState.LOCKED.value
else 'CREATE', 'closedLoopControlName': app_conf.control_loop_name,
'subscription': clean_sub}
return sub_event
except Exception as e:
- logger.error(f'Failed to prep Sub event for xNF {xnf_name}: {e}', exc_info=True)
+ 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):
@@ -159,7 +141,7 @@ class Subscription:
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'{Subscription.get_nf_names_per_sub(self.subscriptionName)}')
+ f'{[nf.nf_name for nf.nf_name in self.get_network_functions()]}')
def get(self):
""" Retrieves a SubscriptionModel object
@@ -189,32 +171,15 @@ class Subscription:
"""
return SubscriptionModel.query.all()
- @staticmethod
- def get_nf_names_per_sub(subscription_name):
- """ Retrieves a list of network function names related to the subscription
-
- Args:
- subscription_name (str): The subscription name
-
- Returns:
- list(str): List of network function names
- """
- nf_sub_rel = NfSubRelationalModel.query.filter(
- NfSubRelationalModel.subscription_name == subscription_name).all()
- list_of_nfs = []
- for nf in nf_sub_rel:
- list_of_nfs.append(nf.nf_name)
-
- return list_of_nfs
-
def activate_subscription(self, nfs, mr_pub, app_conf):
logger.info(f'Activate subscription initiated for {self.subscriptionName}.')
try:
+ existing_nfs = self.get_network_functions()
sub_model = self.get()
- for nf in nfs:
- mr_pub.publish_subscription_event_data(self, nf.nf_name, app_conf)
+ for nf in set(nfs + existing_nfs):
logger.info(f'Publishing event to activate '
f'Sub: {self.subscriptionName} for the nf: {nf.nf_name}')
+ mr_pub.publish_subscription_event_data(self, nf, app_conf)
self.add_network_function_to_subscription(nf, sub_model)
self.update_sub_nf_status(self.subscriptionName, SubNfState.PENDING_CREATE.value,
nf.nf_name)
@@ -222,12 +187,12 @@ class Subscription:
raise Exception(f'Error publishing activation event to MR: {err}')
def deactivate_subscription(self, mr_pub, app_conf):
- nfs = self.get_network_functions()
try:
+ nfs = self.get_network_functions()
if nfs:
logger.info(f'Deactivate subscription initiated for {self.subscriptionName}.')
for nf in nfs:
- mr_pub.publish_subscription_event_data(self, nf.nf_name, app_conf)
+ mr_pub.publish_subscription_event_data(self, nf, app_conf)
logger.debug(f'Publishing Event to deactivate '
f'Sub: {self.subscriptionName} for the nf: {nf.nf_name}')
self.update_sub_nf_status(self.subscriptionName,
@@ -265,25 +230,13 @@ class Subscription:
logger.error(f'Failed to update status of nf: {nf_name} for subscription: '
f'{subscription_name}: {e}', exc_info=True)
- def _get_nf_models(self):
+ def get_network_functions(self):
nf_sub_relationships = NfSubRelationalModel.query.filter(
NfSubRelationalModel.subscription_name == self.subscriptionName)
- nf_models = []
+ 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()
- nf_models.append(nf_model_object)
-
- return nf_models
-
- def get_network_functions(self):
- nfs = []
- nf_models = self._get_nf_models()
- for nf_model in nf_models:
- nf = NetworkFunction(
- nf_name=nf_model.nf_name,
- orchestration_status=nf_model.orchestration_status
- )
- nfs.append(nf)
+ nfs.append(nf_model_object.to_nf())
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
index e74a1732..6de702f2 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
@@ -54,8 +54,8 @@ class SubscriptionHandler:
def _activate(self, local_admin_state, new_administrative_state):
logger.info(f'Administrative State has changed from {local_admin_state} '
f'to {new_administrative_state}.')
- existing_nfs_in_aai = aai.get_pmsh_nfs_from_aai(self.app_conf)
- self.app_conf.subscription.activate_subscription(existing_nfs_in_aai, self.mr_pub,
+ nfs_in_aai = aai.get_pmsh_nfs_from_aai(self.app_conf)
+ self.app_conf.subscription.activate_subscription(nfs_in_aai, self.mr_pub,
self.app_conf)
self.app_conf.subscription.update_subscription_status()
logger.info('Start listening for new NFs on AAI-EVENT topic in MR.')
diff --git a/components/pm-subscription-handler/tests/base_setup.py b/components/pm-subscription-handler/tests/base_setup.py
new file mode 100755
index 00000000..2e50dde9
--- /dev/null
+++ b/components/pm-subscription-handler/tests/base_setup.py
@@ -0,0 +1,57 @@
+# ============LICENSE_START===================================================
+# Copyright (C) 2020 Nordix Foundation.
+# ============================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=====================================================
+import json
+import os
+from unittest import TestCase
+from unittest.mock import patch, MagicMock
+
+from mod import create_app, db
+from mod.pmsh_utils import AppConfig
+
+
+def get_pmsh_config():
+ with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
+ return json.load(data)
+
+
+class BaseClassSetup(TestCase):
+ app = None
+ app_context = None
+
+ @classmethod
+ @patch('mod.get_db_connection_url', MagicMock(return_value='sqlite://'))
+ @patch('mod.update_logging_config', MagicMock())
+ def setUpClass(cls):
+ os.environ['LOGGER_CONFIG'] = os.path.join(os.path.dirname(__file__), 'log_config.yaml')
+ os.environ['LOGS_PATH'] = '.'
+ cls.app = create_app()
+ 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()))
+ def setUp(self):
+ os.environ['AAI_SERVICE_PORT'] = '8443'
+ db.create_all()
+ self.app_conf = AppConfig()
+
+ def tearDown(self):
+ db.drop_all()
+
+ @classmethod
+ def tearDownClass(cls):
+ db.session.remove()
diff --git a/components/pm-subscription-handler/tests/data/aai_model_info.json b/components/pm-subscription-handler/tests/data/aai_model_info.json
new file mode 100644
index 00000000..625de52a
--- /dev/null
+++ b/components/pm-subscription-handler/tests/data/aai_model_info.json
@@ -0,0 +1,36 @@
+{
+ "model-version-id": "6d25b637-8bca-47e2-af1a-61258424183d",
+ "model-name": "PNF102",
+ "model-version": "1.0",
+ "model-description": "sartgserg",
+ "sdnc-model-name": "pm_control",
+ "sdnc-model-version": "1.0.0",
+ "resource-version": "1598626661947",
+ "relationship-list": {
+ "relationship": [
+ {
+ "related-to": "model-element",
+ "relationship-label": "org.onap.relationships.inventory.IsA",
+ "related-link": "/aai/v20/service-design-and-creation/models/model/c1a44771-3aa8-4888-a4f4-be89d1caa0cb/model-vers/model-ver/7256a992-10a7-4ac8-8c2c-63c67e5c48c8/model-elements/model-element/fddc70fe-8343-48c1-af2e-b54f551a32ee/model-elements/model-element/7bff45b7-8254-44e5-b7ad-6e10dee6dfc3",
+ "relationship-data": [
+ {
+ "relationship-key": "model.model-invariant-id",
+ "relationship-value": "c1a44771-3aa8-4888-a4f4-be89d1caa0cb"
+ },
+ {
+ "relationship-key": "model-ver.model-version-id",
+ "relationship-value": "7256a992-10a7-4ac8-8c2c-63c67e5c48c8"
+ },
+ {
+ "relationship-key": "model-element.model-element-uuid",
+ "relationship-value": "fddc70fe-8343-48c1-af2e-b54f551a32ee"
+ },
+ {
+ "relationship-key": "model-element.model-element-uuid",
+ "relationship-value": "7bff45b7-8254-44e5-b7ad-6e10dee6dfc3"
+ }
+ ]
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/components/pm-subscription-handler/tests/data/aai_model_info_no_sdnc.json b/components/pm-subscription-handler/tests/data/aai_model_info_no_sdnc.json
new file mode 100644
index 00000000..fffdfa92
--- /dev/null
+++ b/components/pm-subscription-handler/tests/data/aai_model_info_no_sdnc.json
@@ -0,0 +1,34 @@
+{
+ "model-version-id": "b7469cc5-be51-41cc-b37f-361537656771",
+ "model-name": "PNF104",
+ "model-version": "1.0",
+ "model-description": "aervaer",
+ "resource-version": "1599053901976",
+ "relationship-list": {
+ "relationship": [
+ {
+ "related-to": "model-element",
+ "relationship-label": "org.onap.relationships.inventory.IsA",
+ "related-link": "/aai/v20/service-design-and-creation/models/model/9f751399-59f7-46e4-aaf4-f78b7bf8af84/model-vers/model-ver/135b8bab-b24c-4c6d-b042-dcd7fcd937ba/model-elements/model-element/3c323039-c6ab-47bb-b8e0-d1e57a78fbea/model-elements/model-element/8a424916-020f-4c83-b785-7c04ac06567a",
+ "relationship-data": [
+ {
+ "relationship-key": "model.model-invariant-id",
+ "relationship-value": "9f751399-59f7-46e4-aaf4-f78b7bf8af84"
+ },
+ {
+ "relationship-key": "model-ver.model-version-id",
+ "relationship-value": "135b8bab-b24c-4c6d-b042-dcd7fcd937ba"
+ },
+ {
+ "relationship-key": "model-element.model-element-uuid",
+ "relationship-value": "3c323039-c6ab-47bb-b8e0-d1e57a78fbea"
+ },
+ {
+ "relationship-key": "model-element.model-element-uuid",
+ "relationship-value": "8a424916-020f-4c83-b785-7c04ac06567a"
+ }
+ ]
+ }
+ ]
+ }
+} \ No newline at end of file
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 5c2e0296..86515343 100644
--- a/components/pm-subscription-handler/tests/data/cbs_data_1.json
+++ b/components/pm-subscription-handler/tests/data/cbs_data_1.json
@@ -10,7 +10,7 @@
"^pnf.*",
"^vnf.*"
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
],
"modelVersionIDs": [
diff --git a/components/pm-subscription-handler/tests/data/filter_test_data.json b/components/pm-subscription-handler/tests/data/filter_test_data.json
index 28dc61d1..0d8fc7c8 100644
--- a/components/pm-subscription-handler/tests/data/filter_test_data.json
+++ b/components/pm-subscription-handler/tests/data/filter_test_data.json
@@ -6,7 +6,7 @@
"^pnf.*",
"^vnf.*"
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
],
"modelVersionIDs": [
@@ -16,7 +16,6 @@
"nfName": "pnf1",
"modelInvariantUUID": "7129e420-d396-4efb-af02-6b83499b12f8",
"modelVersionID": "e80a6ae3-cafd-4d24-850d-e14c084a5ca9",
- "orchestration_status": "Active",
"expectedResult": true
},
{
@@ -26,7 +25,7 @@
"^pnf.*",
"^vnf.*"
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
],
"modelVersionIDs": [
@@ -36,15 +35,14 @@
"nfName": "PNF-33",
"modelInvariantUUID": "7129e420-d396-4efb-af02-6b83499b12f8",
"modelVersionID": "e80a6ae3-cafd-4d24-850d-e14c084a5ca9",
- "orchestration_status": "Active",
"expectedResult": false
},
{
- "testName": "test_filter_true_on_modelInvariantUUIDs",
+ "testName": "test_filter_true_on_modelInvariantIDs",
"nfFilter":{
"nfNames":[
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
"5845y423-g654-6fju-po78-8n53154532k6",
"7129e420-d396-4efb-af02-6b83499b12f8"
],
@@ -55,15 +53,14 @@
"nfName": "pnf1",
"modelInvariantUUID": "7129e420-d396-4efb-af02-6b83499b12f8",
"modelVersionID": "e80a6ae3-cafd-4d24-850d-e14c084a5ca9",
- "orchestration_status": "Active",
"expectedResult": true
},
{
- "testName": "test_filter_false_on_modelInvariantUUIDs",
+ "testName": "test_filter_false_on_modelInvariantIDs",
"nfFilter":{
"nfNames":[
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
"5845y423-g654-6fju-po78-8n53154532k6",
"7129e420-d396-4efb-af02-6b83499b12f8"
],
@@ -74,17 +71,16 @@
"nfName": "pnf1",
"modelInvariantUUID": "WrongModelInvariantUUID",
"modelVersionID": "e80a6ae3-cafd-4d24-850d-e14c084a5ca9",
- "orchestration_status": "Active",
"expectedResult": false
},
{
- "testName": "test_filter_false_on_modelInvariantUUIDs_being_false_and_pnfname_being_true",
+ "testName": "test_filter_false_on_modelInvariantIDs_being_false_and_pnfname_being_true",
"nfFilter":{
"nfNames":[
"^pnf.*",
"^vnf.*"
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
"7129e420-d396-4efb-af02-6b83499b12f8"
],
"modelVersionIDs": [
@@ -94,7 +90,6 @@
"nfName": "pnf1",
"modelInvariantUUID": "WrongModelInvariantUUID",
"modelVersionID": "e80a6ae3-cafd-4d24-850d-e14c084a5ca9",
- "orchestration_status": "Active",
"expectedResult": false
},
{
@@ -102,7 +97,7 @@
"nfFilter":{
"nfNames":[
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
],
"modelVersionIDs": [
"e80a6ae3-cafd-4d24-850d-e14c084a5ca9"
@@ -111,7 +106,6 @@
"nfName": "pnf1",
"modelInvariantUUID": "7129e420-d396-4efb-af02-6b83499b12f8",
"modelVersionID": "e80a6ae3-cafd-4d24-850d-e14c084a5ca9",
- "orchestration_status": "Active",
"expectedResult": true
},
{
@@ -119,7 +113,7 @@
"nfFilter":{
"nfNames":[
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
],
"modelVersionIDs": [
"e80a6ae3-cafd-4d24-850d-e14c084a5ca9"
@@ -128,7 +122,6 @@
"nfName": "pnf1",
"modelInvariantUUID": "7129e420-d396-4efb-af02-6b83499b12f8",
"modelVersionID": "WrongModelVersionID",
- "orchestration_status": "Active",
"expectedResult": false
},
{
@@ -138,7 +131,7 @@
"^pnf.*",
"^vnf.*"
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
],
"modelVersionIDs": [
"e80a6ae3-cafd-4d24-850d-e14c084a5ca9"
@@ -147,25 +140,6 @@
"nfName": "pnf1",
"modelInvariantUUID": "7129e420-d396-4efb-af02-6b83499b12f8",
"modelVersionID": "WrongModelVersionID",
- "orchestration_status": "Active",
- "expectedResult": false
- },
- {
- "testName": "test_filter_false_on_OrchestrationStatus",
- "nfFilter":{
- "nfNames":[
- "^pnf.*",
- "^vnf.*"
- ],
- "modelInvariantUUIDs": [
- ],
- "modelVersionIDs": [
- ]
- },
- "nfName": "pnf1",
- "modelInvariantUUID": "7129e420-d396-4efb-af02-6b83499b12f8",
- "modelVersionID": "e80a6ae3-cafd-4d24-850d-e14c084a5ca9",
- "orchestration_status": "Inventoried",
"expectedResult": false
}
- ] \ 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
index e190aa26..9416ec28 100755
--- a/components/pm-subscription-handler/tests/data/pm_subscription_event.json
+++ b/components/pm-subscription-handler/tests/data/pm_subscription_event.json
@@ -1,5 +1,7 @@
{
"nfName":"pnf_1",
+ "blueprintName": "some-name",
+ "blueprintVersion": "some-version",
"policyName":"pmsh-operational-policy",
"changeType":"CREATE",
"closedLoopControlName":"pmsh-control-loop",
diff --git a/components/pm-subscription-handler/tests/log_config.yaml b/components/pm-subscription-handler/tests/log_config.yaml
index 1c3abd8b..f3f39772 100755
--- a/components/pm-subscription-handler/tests/log_config.yaml
+++ b/components/pm-subscription-handler/tests/log_config.yaml
@@ -5,9 +5,16 @@ disable_existing_loggers: true
loggers:
onap_logger:
level: DEBUG
- handlers: [stdout_handler]
+ handlers: [onap_log_handler, stdout_handler]
propagate: false
handlers:
+ onap_log_handler:
+ class: logging.handlers.RotatingFileHandler
+ filename: ./application.log
+ mode: a
+ maxBytes: 10000000
+ backupCount: 10
+ formatter: mdcFormatter
stdout_handler:
class: logging.StreamHandler
formatter: mdcFormatter
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 9ac76477..dc5243d7 100755
--- a/components/pm-subscription-handler/tests/test_aai_event_handler.py
+++ b/components/pm-subscription-handler/tests/test_aai_event_handler.py
@@ -16,59 +16,40 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
import json
-import os
from os import path
-from test.support import EnvironmentVarGuard
-from unittest import TestCase
from unittest.mock import patch, Mock
-from mod import create_app, db
from mod.aai_event_handler import process_aai_events
-from mod.network_function import NetworkFunction
-from mod.pmsh_utils import AppConfig
+from tests.base_setup import BaseClassSetup
-class AAIEventHandlerTest(TestCase):
+class AAIEventHandlerTest(BaseClassSetup):
- @patch('mod.get_db_connection_url')
- @patch('mod.update_logging_config')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def setUp(self, mock_get_pmsh_config, mock_update_config, mock_get_db_url):
- mock_get_db_url.return_value = 'sqlite://'
- with open(path.join(path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ def setUp(self):
+ super().setUp()
with open(path.join(path.dirname(__file__), 'data/mr_aai_events.json'), 'r') as data:
self.mr_aai_events = json.load(data)["mr_response"]
- self.env = EnvironmentVarGuard()
- self.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
self.mock_mr_sub = Mock(get_from_topic=Mock(return_value=self.mr_aai_events))
self.mock_mr_pub = Mock()
self.mock_app = Mock()
- self.app = create_app()
- self.app_context = self.app.app_context()
- self.app_context.push()
- db.create_all()
def tearDown(self):
- db.session.remove()
- db.drop_all()
- self.app_context.pop()
+ super().tearDown()
+
+ @classmethod
+ def tearDownClass(cls):
+ super().tearDownClass()
+ @patch('mod.network_function.NetworkFunction.set_sdnc_params')
@patch('mod.subscription.Subscription.activate_subscription')
@patch('mod.aai_event_handler.NetworkFunction.delete')
- @patch('mod.aai_event_handler.NetworkFunction.get')
- def test_process_aai_update_and_delete_events(self, mock_nf_get, mock_nf_delete,
- mock_activate_sub):
- pnf_already_active = NetworkFunction(nf_name='pnf_already_active',
- orchestration_status='Active')
- mock_nf_get.side_effect = [None, pnf_already_active]
- expected_nf_for_processing = NetworkFunction(
- nf_name='pnf_newly_discovered', orchestration_status='Active')
-
+ def test_process_aai_update_and_delete_events(self, mock_nf_delete, mock_activate_sub,
+ mock_set_sdnc_params):
+ mock_set_sdnc_params.return_value = True
process_aai_events(self.mock_mr_sub, self.mock_mr_pub, self.mock_app, self.app_conf)
-
- mock_activate_sub.assert_called_once_with([expected_nf_for_processing],
- self.mock_mr_pub, self.app_conf)
- mock_nf_delete.assert_called_once_with(nf_name='pnf_to_be_deleted')
+ self.assertEqual(mock_activate_sub.call_count, 2)
+ mock_nf_delete.assert_called_once()
diff --git a/components/pm-subscription-handler/tests/test_aai_service.py b/components/pm-subscription-handler/tests/test_aai_service.py
index 4b7be153..7a3b846d 100644
--- a/components/pm-subscription-handler/tests/test_aai_service.py
+++ b/components/pm-subscription-handler/tests/test_aai_service.py
@@ -17,40 +17,46 @@
# ============LICENSE_END=====================================================
import json
import os
-from test.support import EnvironmentVarGuard
-from unittest import mock, TestCase
+from unittest import mock
from unittest.mock import patch
import responses
-from requests import Session
+from requests import Session, HTTPError
import mod.aai_client as aai_client
-from mod import create_app
-from mod.pmsh_utils import AppConfig
-
-
-class AaiClientTestCase(TestCase):
-
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- @patch('mod.update_logging_config')
- @patch('mod.get_db_connection_url')
- def setUp(self, mock_get_db_url, mock_update_config, mock_get_pmsh_config):
- mock_get_db_url.return_value = 'sqlite://'
- self.env = EnvironmentVarGuard()
- self.env.set('AAI_SERVICE_PORT', '8443')
- self.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+from tests.base_setup import BaseClassSetup
+
+
+class AaiClientTestCase(BaseClassSetup):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ def setUp(self):
+ super().setUp()
with open(os.path.join(os.path.dirname(__file__), 'data/aai_xnfs.json'), 'r') as data:
self.aai_response_data = data.read()
- self.app = create_app()
+ 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_sdnc_params')
+ @patch.object(Session, 'get')
@patch.object(Session, 'put')
- def test_aai_client_get_pm_sub_data_success(self, mock_session):
- mock_session.return_value.status_code = 200
- mock_session.return_value.text = self.aai_response_data
+ def test_aai_client_get_pm_sub_data_success(self, mock_put_session, mock_get_session,
+ mock_get_sdnc_params):
+ mock_put_session.return_value.status_code = 200
+ mock_put_session.return_value.text = self.aai_response_data
+ 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.assertEqual(self.app_conf.subscription.subscriptionName, 'ExtraPM-All-gNB-R2B')
self.assertEqual(self.app_conf.subscription.administrativeState, 'UNLOCKED')
@@ -61,26 +67,48 @@ class AaiClientTestCase(TestCase):
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.cbs_data)
+ aai_client.get_pmsh_nfs_from_aai(self.app_conf)
@responses.activate
def test_aai_client_get_all_aai_xnf_data_not_found(self):
responses.add(responses.PUT,
- 'https://1.2.3.4:8443/aai/v19/query?format=simple&nodesOnly=true',
+ 'https://1.2.3.4:8443/aai/v20/query?format=simple&nodesOnly=true',
json={'error': 'not found'}, status=404)
self.assertIsNone(aai_client._get_all_aai_nf_data(self.app_conf))
@responses.activate
def test_aai_client_get_all_aai_xnf_data_success(self):
responses.add(responses.PUT,
- 'https://aai:8443/aai/v19/query?format=simple&nodesOnly=true',
+ 'https://aai:8443/aai/v20/query?format=simple&nodesOnly=true',
json={'dummy_data': 'blah_blah'}, status=200)
self.assertIsNotNone(aai_client._get_all_aai_nf_data(self.app_conf))
+ @responses.activate
+ def test_aai_client_get_sdnc_params_success(self):
+ responses.add(responses.GET,
+ 'https://aai:8443/aai/v20/service-design-and-creation/models/model/'
+ '6fb9f466-7a79-4109-a2a3-72b340aca53d/model-vers/model-ver/'
+ '6d25b637-8bca-47e2-af1a-61258424183d',
+ json=json.loads(self.good_model_info), status=200)
+ self.assertIsNotNone(aai_client.get_aai_model_data(self.app_conf,
+ '6fb9f466-7a79-4109-a2a3-72b340aca53d',
+ '6d25b637-8bca-47e2-af1a-61258424183d',
+ 'pnf_1'))
+
+ @responses.activate
+ def test_aai_client_get_sdnc_params_fail(self):
+ responses.add(responses.GET,
+ 'https://aai:8443/aai/v20/service-design-and-creation/models/model/'
+ '9fb9f466-7a79-4109-a2a3-72b340aca53d/model-vers/model-ver/'
+ 'b7469cc5-be51-41cc-b37f-361537656771', status=404)
+ with self.assertRaises(HTTPError):
+ aai_client.get_aai_model_data(self.app_conf, '9fb9f466-7a79-4109-a2a3-72b340aca53d',
+ 'b7469cc5-be51-41cc-b37f-361537656771', 'pnf_2')
+
def test_aai_client_get_aai_service_url_fail(self):
- self.env.clear()
+ os.environ.clear()
with self.assertRaises(KeyError):
aai_client._get_aai_service_url()
def test_aai_client_get_aai_service_url_success(self):
- self.assertEqual('https://aai:8443', aai_client._get_aai_service_url())
+ self.assertEqual('https://aai:8443/aai/v20', aai_client._get_aai_service_url())
diff --git a/components/pm-subscription-handler/tests/test_controller.py b/components/pm-subscription-handler/tests/test_controller.py
index 4fcecc37..c38cd976 100755
--- a/components/pm-subscription-handler/tests/test_controller.py
+++ b/components/pm-subscription-handler/tests/test_controller.py
@@ -17,56 +17,55 @@
# ============LICENSE_END=====================================================
import json
import os
-import unittest
-from test.support import EnvironmentVarGuard
from unittest.mock import patch
+import responses
from requests import Session
-from mod import aai_client, create_app, db
+from mod import aai_client
from mod.api.controller import status, get_all_sub_to_nf_relations
-from mod.network_function import NetworkFunction
-from mod.pmsh_utils import AppConfig
+from tests.base_setup import BaseClassSetup
-class ControllerTestCase(unittest.TestCase):
+class ControllerTestCase(BaseClassSetup):
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- @patch('mod.update_logging_config')
- @patch('mod.get_db_connection_url')
- @patch.object(Session, 'put')
- def setUp(self, mock_session, mock_get_db_url, mock_update_config, mock_get_pmsh_config):
- mock_get_db_url.return_value = 'sqlite://'
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ def setUp(self):
+ 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.return_value.status_code = 200
- mock_session.return_value.text = self.aai_response_data
- self.env = EnvironmentVarGuard()
- self.env.set('AAI_SERVICE_PORT', '8443')
- self.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- mock_get_pmsh_config.return_value = self.cbs_data
- self.nf_1 = NetworkFunction(nf_name='pnf_1', orchestration_status='Inventoried')
- self.nf_2 = NetworkFunction(nf_name='pnf_2', orchestration_status='Active')
- self.app = create_app()
- self.app_context = self.app.app_context()
- self.app_context.push()
- db.create_all()
- self.app_conf = AppConfig()
- self.xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf)
+ 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):
- db.session.remove()
- db.drop_all()
+ super().tearDown()
+
+ @classmethod
+ def tearDownClass(cls):
+ super().tearDownClass()
def test_status_response_healthy(self):
self.assertEqual(status()['status'], 'healthy')
- def test_get_all_sub_to_nf_relations(self):
+ @patch.object(Session, 'get')
+ @patch.object(Session, 'put')
+ def test_get_all_sub_to_nf_relations(self, mock_put_session, mock_get_session):
+ mock_put_session.return_value.status_code = 200
+ mock_put_session.return_value.text = self.aai_response_data
+ mock_get_session.return_value.status_code = 200
+ mock_get_session.return_value.text = self.good_model_info
+ responses.add(responses.GET,
+ 'https://aai:8443/aai/v20/service-design-and-creation/models/model/'
+ '7129e420-d396-4efb-af02-6b83499b12f8/model-vers/model-ver/'
+ 'e80a6ae3-cafd-4d24-850d-e14c084a5ca9',
+ json=json.loads(self.good_model_info), status=200)
+ self.xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf)
sub_model = self.app_conf.subscription.get()
- for nf in [self.nf_1, self.nf_2]:
+ for nf in self.xnfs:
self.app_conf.subscription.add_network_function_to_subscription(nf, sub_model)
all_subs = get_all_sub_to_nf_relations()
- self.assertEqual(len(all_subs[0]['network_functions']), 2)
+ self.assertEqual(len(all_subs[0]['network_functions']), 3)
self.assertEqual(all_subs[0]['subscription_name'], 'ExtraPM-All-gNB-R2B')
diff --git a/components/pm-subscription-handler/tests/test_exit_handler.py b/components/pm-subscription-handler/tests/test_exit_handler.py
index d41bd03b..c3cc0241 100755
--- a/components/pm-subscription-handler/tests/test_exit_handler.py
+++ b/components/pm-subscription-handler/tests/test_exit_handler.py
@@ -15,40 +15,38 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-import json
import os
from signal import SIGTERM, signal
-from test.support import EnvironmentVarGuard
-from unittest import TestCase
from unittest.mock import patch, Mock
-from mod.api.db_models import NetworkFunctionModel
from mod.exit_handler import ExitHandler
-from mod.pmsh_utils import AppConfig
from mod.subscription import Subscription
+from tests.base_setup import BaseClassSetup
-class ExitHandlerTests(TestCase):
- @patch('mod.subscription.Subscription.create')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
+class ExitHandlerTests(BaseClassSetup):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
@patch('mod.pmsh_utils.PeriodicTask')
- def setUp(self, mock_periodic_task, mock_get_pmsh_config, mock_sub_create):
- self.env = EnvironmentVarGuard()
- self.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- mock_get_pmsh_config.return_value = self.cbs_data
+ def setUp(self, mock_periodic_task):
+ super().setUp()
self.mock_aai_event_thread = mock_periodic_task
- self.app_conf = AppConfig()
self.sub = self.app_conf.subscription
- @patch('mod.logger.debug')
+ def tearDown(self):
+ super().tearDown()
+
+ @classmethod
+ def tearDownClass(cls):
+ super().tearDownClass()
+
@patch.object(Subscription, 'update_sub_nf_status')
@patch.object(Subscription, 'update_subscription_status')
- @patch.object(Subscription, '_get_nf_models',
- return_value=[NetworkFunctionModel('pnf1', 'ACTIVE')])
- def test_terminate_signal_successful(self, mock_sub_get_nf_models, mock_upd_sub_status,
- mock_upd_subnf_status, mock_logger):
+ def test_terminate_signal_successful(self, mock_upd_sub_status,
+ mock_upd_subnf_status):
handler = ExitHandler(periodic_tasks=[self.mock_aai_event_thread],
app_conf=self.app_conf,
subscription_handler=Mock())
diff --git a/components/pm-subscription-handler/tests/test_network_function.py b/components/pm-subscription-handler/tests/test_network_function.py
index cdfb1eb5..f79ec93d 100755
--- a/components/pm-subscription-handler/tests/test_network_function.py
+++ b/components/pm-subscription-handler/tests/test_network_function.py
@@ -17,40 +17,38 @@
# ============LICENSE_END=====================================================
import json
import os
-from test.support import EnvironmentVarGuard
-from unittest import TestCase
from unittest.mock import patch
-from mod import db, create_app
from mod.network_function import NetworkFunction
-from mod.pmsh_utils import AppConfig
-from mod.subscription import Subscription
-
-
-class NetworkFunctionTests(TestCase):
-
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- @patch('mod.update_logging_config')
- @patch('mod.get_db_connection_url')
- def setUp(self, mock_get_db_url, mock_update_config, mock_get_pmsh_config):
- mock_get_db_url.return_value = 'sqlite://'
- self.nf_1 = NetworkFunction(nf_name='pnf_1', orchestration_status='Inventoried')
- self.nf_2 = NetworkFunction(nf_name='pnf_2', orchestration_status='Active')
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- mock_get_pmsh_config.return_value = self.cbs_data
- self.env = EnvironmentVarGuard()
- self.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
- self.app = create_app()
- self.app_context = self.app.app_context()
- self.app_context.push()
- db.create_all()
- self.app_conf = AppConfig()
+from tests.base_setup import BaseClassSetup
+
+
+class NetworkFunctionTests(BaseClassSetup):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ def setUp(self):
+ super().setUp()
+ self.nf_1 = NetworkFunction(nf_name='pnf_1',
+ model_invariant_id='some-id',
+ model_version_id='some-id')
+ self.nf_2 = NetworkFunction(nf_name='pnf_2',
+ model_invariant_id='some-id',
+ model_version_id='some-id')
+ with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data:
+ self.good_model_info = json.loads(data.read())
+ with open(os.path.join(os.path.dirname(__file__),
+ 'data/aai_model_info_no_sdnc.json'), 'r') as data:
+ self.bad_model_info = json.loads(data.read())
def tearDown(self):
- db.session.remove()
- db.drop_all()
- self.app_context.pop()
+ super().tearDown()
+
+ @classmethod
+ def tearDownClass(cls):
+ super().tearDownClass()
def test_get_network_function(self):
self.nf_1.create()
@@ -77,16 +75,21 @@ class NetworkFunctionTests(TestCase):
self.assertEqual(nf, same_nf)
def test_delete_network_function(self):
- self.nf_1.create()
- self.nf_2.create()
- sub = Subscription(**{"subscriptionName": "sub"})
+ sub = self.app_conf.subscription
for nf in [self.nf_1, self.nf_2]:
sub.add_network_function_to_subscription(nf, self.app_conf.subscription.get())
-
+ nfs = NetworkFunction.get_all()
+ self.assertEqual(2, len(nfs))
NetworkFunction.delete(nf_name=self.nf_1.nf_name)
-
nfs = NetworkFunction.get_all()
self.assertEqual(1, len(nfs))
- self.assertEqual(1, len(Subscription.get_all_nfs_subscription_relations()))
- pnf_1_deleted = [nf for nf in nfs if nf.nf_name != self.nf_1.nf_name]
- self.assertTrue(pnf_1_deleted)
+
+ @patch('mod.aai_client.get_aai_model_data')
+ def test_set_sdnc_params_true(self, mock_get_aai_model):
+ mock_get_aai_model.return_value = self.good_model_info
+ self.assertTrue(self.nf_1.set_sdnc_params(self.app_conf))
+
+ @patch('mod.aai_client.get_aai_model_data')
+ def test_set_sdnc_params_false(self, mock_get_aai_model):
+ mock_get_aai_model.return_value = self.bad_model_info
+ self.assertFalse(self.nf_1.set_sdnc_params(self.app_conf))
diff --git a/components/pm-subscription-handler/tests/test_network_function_filter.py b/components/pm-subscription-handler/tests/test_network_function_filter.py
index 95c9b7bc..2151925d 100644
--- a/components/pm-subscription-handler/tests/test_network_function_filter.py
+++ b/components/pm-subscription-handler/tests/test_network_function_filter.py
@@ -20,7 +20,7 @@ import json
import os
from unittest import TestCase
from parameterized import parameterized
-from mod.network_function import NetworkFunctionFilter
+from mod.network_function import NetworkFunctionFilter, NetworkFunction
def custom_name_func(testcase_func, param_num, param):
@@ -32,7 +32,8 @@ def custom_name_func(testcase_func, param_num, param):
def load_test_cases():
test_parameters = []
- with open(os.path.join(os.path.dirname(__file__), 'data/filter_test_data.json'), 'r') as test_data:
+ with open(os.path.join(os.path.dirname(__file__),
+ 'data/filter_test_data.json'), 'r') as test_data:
loaded_test_data = json.load(test_data)
for test in loaded_test_data:
params = [value for key, value in test.items()]
@@ -43,44 +44,44 @@ def load_test_cases():
class NetworkFunctionFilterTest(TestCase):
@parameterized.expand(load_test_cases, name_func=custom_name_func)
- def test(self, test_name, nf_filter, nf_name, model_invariant_uuid, model_version_id, orchestration_status,
+ def test(self, test_name, nf_filter, nf_name, model_invariant_uuid, model_version_id,
expected_result):
nf_filter = NetworkFunctionFilter(**nf_filter)
- self.assertEqual(nf_filter.is_nf_in_filter(nf_name,
- model_invariant_uuid,
- model_version_id,
- orchestration_status), expected_result)
+ self.assertEqual(nf_filter.is_nf_in_filter(NetworkFunction(nf_name=nf_name,
+ model_invariant_id=model_invariant_uuid,
+ model_version_id=model_version_id)),
+ expected_result)
- def test_filter_true_on_multiple_modelInvariantUUIDs(self):
+ def test_filter_true_on_multiple_modelInvariantIDs(self):
nf_filter = NetworkFunctionFilter(**{
"nfNames": [
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
'5845y423-g654-6fju-po78-8n53154532k6',
'7129e420-d396-4efb-af02-6b83499b12f8'
],
"modelVersionIDs": [
]
})
- self.assertTrue(nf_filter.is_nf_in_filter('pnf1',
- '7129e420-d396-4efb-af02-6b83499b12f8',
- 'e80a6ae3-cafd-4d24-850d-e14c084a5ca9',
- 'Active'))
+ self.assertTrue(nf_filter.is_nf_in_filter(
+ NetworkFunction(nf_name='pnf1',
+ model_invariant_id='7129e420-d396-4efb-af02-6b83499b12f8',
+ model_version_id='e80a6ae3-cafd-4d24-850d-e14c084a5ca9')))
- def test_filter_false_on_modelInvariantUUIDs_being_false_and_pnfname_being_true(self):
+ def test_filter_false_on_modelInvariantIDs_being_false_and_pnfname_being_true(self):
nf_filter = NetworkFunctionFilter(**{
"nfNames": [
"^pnf.*",
"^vnf.*"
],
- "modelInvariantUUIDs": [
+ "modelInvariantIDs": [
'5845y423-g654-6fju-po78-8n53154532k6',
'7129e420-d396-4efb-af02-6b83499b12f8'
],
"modelVersionIDs": [
]
})
- self.assertFalse(nf_filter.is_nf_in_filter('pnf1',
- 'WrongModelInvariantUUID',
- 'e80a6ae3-cafd-4d24-850d-e14c084a5ca9',
- 'Active')) \ No newline at end of file
+ self.assertFalse(nf_filter.is_nf_in_filter(
+ NetworkFunction(nf_name='pnf1',
+ model_invariant_id='WrongModelInvariantUUID',
+ model_version_id='e80a6ae3-cafd-4d24-850d-e14c084a5ca9')))
diff --git a/components/pm-subscription-handler/tests/test_pmsh_utils.py b/components/pm-subscription-handler/tests/test_pmsh_utils.py
index 6e5585f5..1bc039d2 100644
--- a/components/pm-subscription-handler/tests/test_pmsh_utils.py
+++ b/components/pm-subscription-handler/tests/test_pmsh_utils.py
@@ -15,88 +15,67 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-import json
-import os
from test.support import EnvironmentVarGuard
-from unittest import TestCase
-from unittest.mock import patch
+from unittest.mock import patch, Mock
import responses
from requests import Session
from tenacity import RetryError
-from mod import db, get_db_connection_url, create_app
+from mod import get_db_connection_url
+from mod.network_function import NetworkFunction
from mod.pmsh_utils import AppConfig
+from tests.base_setup import BaseClassSetup
+from tests.base_setup import get_pmsh_config
-class PmshUtilsTestCase(TestCase):
+class PmshUtilsTestCase(BaseClassSetup):
- @patch('mod.update_logging_config')
- @patch('mod.create_app')
- @patch('mod.get_db_connection_url')
- def setUp(self, mock_get_db_url, mock_app, mock_update_config):
- mock_get_db_url.return_value = 'sqlite://'
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- self.env = EnvironmentVarGuard()
- self.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
- self.mock_app = mock_app
- self.app = create_app()
- self.app_context = self.app.app_context()
- self.app_context.push()
- db.create_all()
-
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def test_utils_get_mr_sub(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ @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')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def test_utils_get_mr_sub_fails_with_invalid_name(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ def test_utils_get_mr_sub_fails_with_invalid_name(self):
with self.assertRaises(KeyError):
self.app_conf.get_mr_sub('invalid_sub')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def test_utils_get_mr_pub(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ 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!')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def test_utils_get_mr_pub_fails_with_invalid_name(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ def test_utils_get_mr_pub_fails_with_invalid_name(self):
with self.assertRaises(KeyError):
self.app_conf.get_mr_pub('invalid_pub')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def test_utils_get_cert_data(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ 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('mod.pmsh_utils.AppConfig._get_pmsh_config')
@patch.object(Session, 'post')
- def test_mr_pub_publish_to_topic_success(self, mock_session, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ 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()
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
@responses.activate
- def test_mr_pub_publish_to_topic_fail(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ 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)
@@ -104,21 +83,19 @@ class PmshUtilsTestCase(TestCase):
with self.assertRaises(Exception):
mr_policy_pub.publish_to_topic({"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"})
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def test_mr_pub_publish_sub_event_data_success(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ 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, 'pnf201',
- self.app_conf)
+ 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'),
+ self.app_conf)
pub_to_topic_call.assert_called_once()
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
@responses.activate
- def test_mr_sub_get_from_topic_success(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ 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/'
@@ -127,11 +104,8 @@ class PmshUtilsTestCase(TestCase):
mr_topic_data = policy_mr_sub.get_from_topic(1)
self.assertIsNotNone(mr_topic_data)
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
@responses.activate
- def test_mr_sub_get_from_topic_fail(self, mock_get_pmsh_config):
- mock_get_pmsh_config.return_value = self.cbs_data
- self.app_conf = AppConfig()
+ 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/'
@@ -158,15 +132,14 @@ class PmshUtilsTestCase(TestCase):
@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 = self.cbs_data
- self.app_conf = AppConfig()
+ 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.return_value = self.cbs_data
+ mock_cbs_client_get_all.return_value = get_pmsh_config()
self.app_conf = AppConfig()
mock_cbs_client_get_all.side_effect = Exception
with self.assertRaises(RetryError):
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 9dd73ee0..26a06fce 100644
--- a/components/pm-subscription-handler/tests/test_policy_response_handler.py
+++ b/components/pm-subscription-handler/tests/test_policy_response_handler.py
@@ -15,36 +15,37 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-import json
-import os
-from unittest import TestCase
from unittest.mock import patch
from mod.api.db_models import SubscriptionModel
from mod.network_function import NetworkFunction
-from mod.pmsh_utils import AppConfig
from mod.policy_response_handler import PolicyResponseHandler, policy_response_handle_functions
from mod.subscription import AdministrativeState, SubNfState
+from tests.base_setup import BaseClassSetup
-class PolicyResponseHandlerTest(TestCase):
+class PolicyResponseHandlerTest(BaseClassSetup):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
@patch('mod.create_app')
- @patch('mod.subscription.Subscription')
@patch('mod.pmsh_utils._MrSub')
- def setUp(self, mock_mr_sub, mock_sub, mock_app, mock_get_app_conf):
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
+ def setUp(self, mock_mr_sub, mock_app):
+ super().setUp()
self.mock_policy_mr_sub = mock_mr_sub
- mock_get_app_conf.return_value = self.cbs_data
- self.app_conf = AppConfig()
- self.sub = self.app_conf.subscription
- self.mock_app = mock_app
self.nf = NetworkFunction(nf_name='nf1')
self.policy_response_handler = PolicyResponseHandler(self.mock_policy_mr_sub,
self.app_conf,
- self.mock_app)
+ 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):
diff --git a/components/pm-subscription-handler/tests/test_subscription.py b/components/pm-subscription-handler/tests/test_subscription.py
index c7845e74..9bfe825f 100755
--- a/components/pm-subscription-handler/tests/test_subscription.py
+++ b/components/pm-subscription-handler/tests/test_subscription.py
@@ -17,54 +17,45 @@
# ============LICENSE_END=====================================================
import json
import os
-from test.support import EnvironmentVarGuard
-from unittest import TestCase
-from unittest.mock import patch
+from unittest.mock import patch, Mock
from requests import Session
import mod.aai_client as aai_client
-from mod import db, create_app
-from mod.api.db_models import NetworkFunctionModel
from mod.network_function import NetworkFunction
-from mod.pmsh_utils import AppConfig
from mod.subscription import Subscription
+from tests.base_setup import BaseClassSetup
-class SubscriptionTest(TestCase):
- @patch('mod.update_logging_config')
- @patch('mod.pmsh_utils._MrPub')
- @patch('mod.pmsh_utils._MrSub')
- @patch('mod.get_db_connection_url')
+class SubscriptionTest(BaseClassSetup):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ @patch.object(Session, 'get')
@patch.object(Session, 'put')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
- def setUp(self, mock_get_pmsh_config, mock_session, mock_get_db_url,
- mock_mr_sub, mock_mr_pub, mock_update_config):
- mock_get_db_url.return_value = 'sqlite://'
+ 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.return_value.status_code = 200
- mock_session.return_value.text = self.aai_response_data
- self.env = EnvironmentVarGuard()
- self.env.set('AAI_SERVICE_PORT', '8443')
- self.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- mock_get_pmsh_config.return_value = self.cbs_data
- self.mock_mr_sub = mock_mr_sub
- self.mock_mr_pub = mock_mr_pub
- self.app = create_app()
- self.app_context = self.app.app_context()
- self.app_context.push()
- db.create_all()
- self.app_conf = AppConfig()
+ 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.xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf)
self.sub_model = self.app_conf.subscription.get()
def tearDown(self):
- db.drop_all()
- db.session.remove()
- self.app_context.pop()
+ super().tearDown()
+
+ @classmethod
+ def tearDownClass(cls):
+ super().tearDownClass()
def test_sub_measurement_group(self):
self.assertEqual(len(self.app_conf.subscription.measurementGroups), 2)
@@ -84,8 +75,6 @@ class SubscriptionTest(TestCase):
self.sub_model)
self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[1],
self.sub_model)
- nfs = Subscription.get_nf_names_per_sub(self.app_conf.subscription.subscriptionName)
- self.assertEqual(2, len(nfs))
def test_create_existing_subscription(self):
sub1 = self.app_conf.subscription.create()
@@ -121,16 +110,6 @@ class SubscriptionTest(TestCase):
self.assertEqual('new_status', sub.status)
- def test_delete_subscription(self):
- for nf in self.xnfs:
- self.app_conf.subscription.add_network_function_to_subscription(nf, self.sub_model)
- self.app_conf.subscription.delete_subscription()
- self.assertEqual(0, len(Subscription.get_all()))
- self.assertEqual(None, self.app_conf.subscription.get())
- self.assertEqual(0, len(Subscription.get_all_nfs_subscription_relations()))
- self.assertEqual(0, len(NetworkFunction.get_all()))
- self.assertEqual(None, NetworkFunction.get(nf_name=list(self.xnfs)[0].nf_name))
-
def test_update_sub_nf_status(self):
sub_name = 'ExtraPM-All-gNB-R2B'
for nf in self.xnfs:
@@ -172,18 +151,15 @@ class SubscriptionTest(TestCase):
with open(os.path.join(os.path.dirname(__file__),
'data/pm_subscription_event.json'), 'r') as data:
expected_sub_event = json.load(data)
- actual_sub_event = self.app_conf.subscription.prepare_subscription_event('pnf_1',
- self.app_conf)
+ nf = NetworkFunction(nf_name='pnf_1',
+ 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, self.app_conf)
+ print(actual_sub_event)
self.assertEqual(expected_sub_event, actual_sub_event)
- def test_get_nf_models(self):
- for nf in self.xnfs:
- self.app_conf.subscription.add_network_function_to_subscription(nf, self.sub_model)
- nf_models = self.app_conf.subscription._get_nf_models()
-
- self.assertEqual(3, len(nf_models))
- self.assertIsInstance(nf_models[0], NetworkFunctionModel)
-
def test_get_network_functions(self):
for nf in self.xnfs:
self.app_conf.subscription.add_network_function_to_subscription(nf, self.sub_model)
diff --git a/components/pm-subscription-handler/tests/test_subscription_handler.py b/components/pm-subscription-handler/tests/test_subscription_handler.py
index a6611666..bf72382a 100644
--- a/components/pm-subscription-handler/tests/test_subscription_handler.py
+++ b/components/pm-subscription-handler/tests/test_subscription_handler.py
@@ -15,50 +15,39 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-import json
-import os
-from test.support import EnvironmentVarGuard
-from unittest import TestCase
-from unittest.mock import patch
+from unittest.mock import patch, Mock
-from mod import create_app, db
from mod.network_function import NetworkFunction
-from mod.pmsh_utils import AppConfig
from mod.subscription import AdministrativeState
from mod.subscription_handler import SubscriptionHandler
+from tests.base_setup import BaseClassSetup
-class SubscriptionHandlerTest(TestCase):
+class SubscriptionHandlerTest(BaseClassSetup):
@classmethod
def setUpClass(cls):
- cls.env = EnvironmentVarGuard()
- cls.env.set('AAI_SERVICE_PORT', '8443')
- cls.env.set('LOGGER_CONFIG', os.path.join(os.path.dirname(__file__), 'log_config.yaml'))
- cls.nfs = [NetworkFunction(nf_name='pnf_1'), NetworkFunction(nf_name='pnf_2')]
+ super().setUpClass()
- @patch('mod.get_db_connection_url')
- @patch('mod.update_logging_config')
- @patch('mod.pmsh_utils.AppConfig._get_pmsh_config')
@patch('mod.pmsh_utils._MrPub')
- @patch('mod.pmsh_utils.PeriodicTask')
- def setUp(self, mock_periodic_task, mock_mr_pub, mock_get_pmsh_config, mock_update_config,
- mock_get_db_url):
- mock_get_db_url.return_value = 'sqlite://'
- with open(os.path.join(os.path.dirname(__file__), 'data/cbs_data_1.json'), 'r') as data:
- self.cbs_data = json.load(data)
- mock_get_pmsh_config.return_value = self.cbs_data
+ def setUp(self, mock_mr_pub):
+ super().setUp()
+ self.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')]
self.mock_mr_pub = mock_mr_pub
- self.mock_aai_event_thread = mock_periodic_task
- self.mock_policy_event_thread = mock_periodic_task
- self.app = create_app()
- self.app.app_context().push()
- db.create_all()
- self.app_conf = AppConfig()
+ self.mock_aai_event_thread = Mock()
+ self.mock_policy_event_thread = Mock()
def tearDown(self):
- db.drop_all()
- db.session.remove()
+ super().tearDown()
+
+ @classmethod
+ def tearDownClass(cls):
+ super().tearDownClass()
@patch('mod.subscription.Subscription.get_local_sub_admin_state')
@patch('mod.logger.info')