summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSE.txt36
-rw-r--r--components/datalake-handler/LICENSE.txt36
-rw-r--r--components/datalake-handler/admin/src/LICENSE202
-rw-r--r--components/kpi-computation-ms/LICENSE.txt36
-rwxr-xr-xcomponents/pm-subscription-handler/Changelog.md5
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/aai_event_handler.py143
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/api/controller.py79
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/mod/api/db_models.py79
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml104
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py72
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py49
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py71
-rw-r--r--components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py12
-rwxr-xr-xcomponents/pm-subscription-handler/pmsh_service/pmsh_service_main.py12
-rwxr-xr-xcomponents/pm-subscription-handler/tests/base_setup.py62
-rwxr-xr-xcomponents/pm-subscription-handler/tests/data/mr_aai_events.json3
-rw-r--r--components/pm-subscription-handler/tests/services/test_measurement_group_service.py89
-rw-r--r--components/pm-subscription-handler/tests/services/test_subscription_service.py22
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_aai_event_handler.py119
-rwxr-xr-xcomponents/pm-subscription-handler/tests/test_controller.py83
-rw-r--r--components/pm-subscription-handler/tests/test_policy_response_handler.py106
-rw-r--r--components/pm-subscription-handler/tests/test_subscription_handler.py3
-rw-r--r--components/pm-subscription-handler/tox.ini2
-rw-r--r--components/slice-analysis-ms/ChangeLog.md12
-rw-r--r--components/slice-analysis-ms/entry.sh4
-rw-r--r--components/slice-analysis-ms/pom.xml563
-rw-r--r--components/slice-analysis-ms/src/main/docker/dockerfile/Dockerfile29
-rw-r--r--components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java144
-rw-r--r--components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java12
-rw-r--r--components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java372
-rw-r--r--components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java179
-rw-r--r--components/slice-analysis-ms/version.properties2
32 files changed, 1692 insertions, 1050 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 00000000..9931ea93
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,36 @@
+/*
+* ============LICENSE_START==========================================
+* ===================================================================
+* Copyright (c) 2021 AT&T Intellectual Property. All rights reserved.
+* ===================================================================
+*
+* Unless otherwise specified, all software contained herein is licensed
+* under the Apache License, Version 2.0 (the "License");
+* you may not use this software 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.
+*
+*
+*
+* Unless otherwise specified, all documentation contained herein is licensed
+* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+* you may not use this documentation except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* https://creativecommons.org/licenses/by/4.0/
+*
+* Unless required by applicable law or agreed to in writing, documentation
+* 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.
+*
+* ============LICENSE_END============================================
+*/
diff --git a/components/datalake-handler/LICENSE.txt b/components/datalake-handler/LICENSE.txt
new file mode 100644
index 00000000..b12df03b
--- /dev/null
+++ b/components/datalake-handler/LICENSE.txt
@@ -0,0 +1,36 @@
+/*
+* ============LICENSE_START==========================================
+* ===================================================================
+* Copyright (c) 2019 ChinaMobile Intellectual Property. All rights reserved.
+* ===================================================================
+*
+* Unless otherwise specified, all software contained herein is licensed
+* under the Apache License, Version 2.0 (the "License");
+* you may not use this software 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.
+*
+*
+*
+* Unless otherwise specified, all documentation contained herein is licensed
+* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+* you may not use this documentation except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* https://creativecommons.org/licenses/by/4.0/
+*
+* Unless required by applicable law or agreed to in writing, documentation
+* 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.
+*
+* ============LICENSE_END============================================
+*/
diff --git a/components/datalake-handler/admin/src/LICENSE b/components/datalake-handler/admin/src/LICENSE
deleted file mode 100644
index d6456956..00000000
--- a/components/datalake-handler/admin/src/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
diff --git a/components/kpi-computation-ms/LICENSE.txt b/components/kpi-computation-ms/LICENSE.txt
new file mode 100644
index 00000000..be3117cb
--- /dev/null
+++ b/components/kpi-computation-ms/LICENSE.txt
@@ -0,0 +1,36 @@
+/*
+* ============LICENSE_START==========================================
+* ===================================================================
+* Copyright (c) 2021 ChinaMobile Intellectual Property. All rights reserved.
+* ===================================================================
+*
+* Unless otherwise specified, all software contained herein is licensed
+* under the Apache License, Version 2.0 (the "License");
+* you may not use this software 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.
+*
+*
+*
+* Unless otherwise specified, all documentation contained herein is licensed
+* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+* you may not use this documentation except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* https://creativecommons.org/licenses/by/4.0/
+*
+* Unless required by applicable law or agreed to in writing, documentation
+* 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.
+*
+* ============LICENSE_END============================================
+*/
diff --git a/components/pm-subscription-handler/Changelog.md b/components/pm-subscription-handler/Changelog.md
index f02fc5eb..db096b11 100755
--- a/components/pm-subscription-handler/Changelog.md
+++ b/components/pm-subscription-handler/Changelog.md
@@ -12,6 +12,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
* Implemented Create Subscription public API (DCAEGEN2-2819)
* Added 2 new attributes to the subscription model (DCAEGEN2-2913)
* Read subscription API by using subscription name (DCAEGEN2-2818)
+* Read All subscriptions API (DCAEGEN2-2847)
+* Response Event Handler Integration (DCAEGEN2-2915)
+* Updated to get NFs list when requesting a specific subscription (DCAEGEN2-2992)
+* AAI Event handler changes with new subscription format (DCAEGEN2-2912)
+* Read NFS associated with MG by using MGName and subName(DCAEGEN2-2993)
## [1.3.2]
### Changed
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 a00c164a..fe4166e7 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
@@ -15,12 +15,14 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-
import json
from enum import Enum
-
-from mod import logger
+from mod import logger, db
from mod.network_function import NetworkFunction
+from mod.pmsh_config import AppConfig, MRTopic
+from mod.api.db_models import SubscriptionModel
+from mod.network_function import NetworkFunctionFilter
+from mod.api.services import subscription_service
class XNFType(Enum):
@@ -33,53 +35,98 @@ class AAIEvent(Enum):
UPDATE = 'UPDATE'
-def process_aai_events(mr_sub, mr_pub, app, app_conf):
+def is_pnf_xnf(entity_type):
"""
- Processes AAI UPDATE events for each filtered xNFs where orchestration status is set to Active.
-
+ Applies measurement groups to network functions identified by AAI event
Args:
- mr_sub (_MrSub): MR subscriber
- mr_pub (_MrPub): MR publisher
- app (db): DB application
- app_conf (AppConfig): the application configuration.
+ entity_type (string): The type of network function
"""
- app.app_context().push()
- logger.info('Polling MR for XNF AAI events.')
- try:
- aai_events = mr_sub.get_from_topic('dcae_pmsh_aai_event')
- if aai_events is not None and len(aai_events) != 0:
- aai_events = [json.loads(e) for e in aai_events]
- xnf_events = [e for e in aai_events if e['event-header']['entity-type'] == (
- XNFType.PNF.value or XNFType.VNF.value)]
- for entry in xnf_events:
- logger.debug(f'AAI-EVENT entry: {entry}')
- aai_entity = entry['entity']
- action = entry['event-header']['action']
- entity_type = entry['event-header']['entity-type']
- xnf_name = aai_entity['pnf-name'] if entity_type == XNFType.PNF.value \
- else aai_entity['vnf-name']
- 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,
- ipv4_address=aai_entity['ipaddress-v4-oam'],
- ipv6_address=aai_entity['ipaddress-v6-oam'],
- model_invariant_id=aai_entity['model-invariant-id'],
- model_version_id=aai_entity['model-version-id'])
- if not nf.set_nf_model_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)
+ return entity_type == (XNFType.PNF.value or XNFType.VNF.value)
+
+
+class AAIEventHandler:
+ """ Responsible for handling AAI update events in PMSH """
+
+ def __init__(self, app):
+ self.app = app
+ def execute(self):
+ """
+ Processes AAI UPDATE events for each filtered xNFs where
+ orchestration status is set to Active.
+ """
+ self.app.app_context().push()
+ logger.info('Polling MR for XNF AAI events.')
+ try:
+ aai_events = AppConfig.get_instance().get_from_topic(MRTopic.AAI_SUBSCRIBER.value,
+ 'dcae_pmsh_aai_event')
+ if aai_events is not None and len(aai_events) != 0:
+ pmsh_nf_names = list(nf.nf_name for nf in NetworkFunction.get_all())
+ aai_events = [json.loads(e) for e in aai_events]
+ xnf_events = [e for e in aai_events if is_pnf_xnf(e['event-header']['entity-type'])]
+ new_nfs = []
+ for entry in xnf_events:
+ logger.debug(f'AAI-EVENT entry: {entry}')
+ aai_entity = entry['entity']
+ action = entry['event-header']['action']
+ entity_type = entry['event-header']['entity-type']
+ xnf_name = aai_entity['pnf-name'] if entity_type == XNFType.PNF.value \
+ else aai_entity['vnf-name']
+ 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,
+ ipv4_address=aai_entity['ipaddress-v4-oam'],
+ ipv6_address=aai_entity['ipaddress-v6-oam'],
+ model_invariant_id=aai_entity['model-invariant-id'],
+ model_version_id=aai_entity['model-version-id'])
+ if action == AAIEvent.DELETE.value and xnf_name in pmsh_nf_names:
+ 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.')
+ elif action == AAIEvent.UPDATE.value and \
+ xnf_name not in pmsh_nf_names and \
+ nf.set_nf_model_params(AppConfig.get_instance()):
+ new_nfs.append(nf)
+ if new_nfs:
+ self.apply_nfs_to_subscriptions(new_nfs)
+ except Exception as e:
+ logger.error(f'Failed to process AAI event due to: {e}')
-def _process_event(action, nf, mr_pub, app_conf):
- if action == AAIEvent.UPDATE.value:
- logger.info(f'Update event found for network function {nf.nf_name}')
- app_conf.subscription.create_subscription_on_nfs([nf], mr_pub)
- elif action == AAIEvent.DELETE.value:
- 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.')
+ @staticmethod
+ def apply_nfs_to_subscriptions(new_nfs):
+ """
+ Applies measurement groups to network functions identified by AAI event
+ Args:
+ new_nfs (list[NetworkFunction]): new network functions identified
+ """
+ subscriptions = db.session.query(SubscriptionModel).all()
+ if subscriptions:
+ for subscription in subscriptions:
+ try:
+ nf_filter = NetworkFunctionFilter(**subscription.network_filter.serialize())
+ filtered_nfs = []
+ for nf in new_nfs:
+ if nf_filter.is_nf_in_filter(nf):
+ filtered_nfs.append(nf)
+ if filtered_nfs:
+ subscription_service.save_filtered_nfs(filtered_nfs)
+ subscription_service. \
+ apply_subscription_to_nfs(filtered_nfs, subscription.subscription_name)
+ unlocked_meas_grp = subscription_service. \
+ apply_measurement_grp_to_nfs(filtered_nfs,
+ subscription.measurement_groups)
+ if unlocked_meas_grp:
+ subscription_service. \
+ publish_measurement_grp_to_nfs(subscription, filtered_nfs,
+ unlocked_meas_grp)
+ else:
+ logger.error(f'All measurement groups are locked for subscription: '
+ f'{subscription.subscription_name}, '
+ f'please verify/check measurement groups.')
+ db.session.commit()
+ except Exception as e:
+ logger.error(f'Failed to process AAI event for subscription: '
+ f'{subscription.subscription_name} due to: {e}')
+ db.session.remove()
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 80d86362..aee6df0e 100755
--- a/components/pm-subscription-handler/pmsh_service/mod/api/controller.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/controller.py
@@ -18,7 +18,7 @@
from http import HTTPStatus
from mod import logger
-from mod.api.services import subscription_service
+from mod.api.services import subscription_service, measurement_group_service
from connexion import NoContent
from mod.api.custom_exception import InvalidDataException, DuplicateDataException
@@ -75,24 +75,75 @@ def get_subscription_by_name(subscription_name):
subscription_name (String): Name of the subscription.
Returns:
- success: dict of single Subscription, 200
- None: subscription not defined, 404
- Exception: Details about exception, 500
+ dict, HTTPStatus: single Sub in PMSH, 200
+ dict, HTTPStatus: subscription not defined, 404
+ dict, HTTPStatus: Exception details of failure, 500
"""
logger.info('API call received to fetch subscription by name')
try:
- subscription = subscription_service.get_subscription_by_name(subscription_name)
+ subscription = subscription_service.query_subscription_by_name(subscription_name)
if subscription is not None:
- logger.info(f'subscription object with the name "{subscription_name}" '
- 'was fetched successfully from database')
- return subscription.serialize(), HTTPStatus.OK
+ logger.info(f'queried subscription was successful with the name: {subscription_name}')
+ return subscription.serialize(), HTTPStatus.OK.value
else:
- logger.error(f'subscription object with the name "{subscription_name}" '
- 'was un successful to fetch from database')
+ logger.error('queried subscription was un successful with the name: '
+ f'{subscription_name}')
return {'error': 'Subscription was not defined with the name : '
- f'{subscription_name}'}, HTTPStatus.NOT_FOUND
+ f'{subscription_name}'}, HTTPStatus.NOT_FOUND.value
except Exception as exception:
- logger.error(f'The following exception occurred "{exception}" while fetching subscription '
- f'with the name "{subscription_name}"')
+ logger.error(f'While querying the subscription with name: {subscription_name}, '
+ f'it occurred the following exception "{exception}"')
return {'error': 'Request was not processed due to Exception : '
- f'{exception}'}, HTTPStatus.INTERNAL_SERVER_ERROR
+ f'{exception}'}, HTTPStatus.INTERNAL_SERVER_ERROR.value
+
+
+def get_subscriptions():
+ """ Retrieves all the subscriptions that are defined in PMSH.
+
+ Returns:
+ list (dict), HTTPStatus: All subs in PMSH, 200
+ dict, HTTPStatus: Exception details of failure, 500
+ """
+ logger.info('API call received to fetch all subscriptions')
+ try:
+ subscriptions = subscription_service.get_subscriptions_list()
+ return subscriptions, HTTPStatus.OK.value
+ except Exception as exception:
+ logger.error(f'The following exception occurred while fetching subscriptions: {exception}')
+ return {'error': 'Request was not processed due to Exception : '
+ f'{exception}'}, HTTPStatus.INTERNAL_SERVER_ERROR.value
+
+
+def get_meas_group_with_nfs(subscription_name, measurement_group_name):
+ """
+ Retrieves the measurement group and it's associated network functions
+
+ Args:
+ subscription_name (String): Name of the subscription.
+ measurement_group_name (String): Name of the measurement group
+
+ Returns:
+ dict, HTTPStatus: measurement group info with associated nfs, 200
+ dict, HTTPStatus: measurement group was not defined, 404
+ dict, HTTPStatus: Exception details of failure, 500
+ """
+ logger.info('API call received to query measurement group and associated network'
+ f' functions by using sub name: {subscription_name} and measurement '
+ f'group name: {measurement_group_name}')
+ try:
+ meas_group = measurement_group_service.query_meas_group_by_name(subscription_name,
+ measurement_group_name)
+ if meas_group is not None:
+ return meas_group.meas_group_with_nfs(), HTTPStatus.OK.value
+ else:
+ logger.error('measurement group was not defined with the sub name: '
+ f'{subscription_name} and meas group name: '
+ f'{measurement_group_name}')
+ return {'error': 'measurement group was not defined with the sub name: '
+ f'{subscription_name} and meas group name: '
+ f'{measurement_group_name}'}, HTTPStatus.NOT_FOUND.value
+ except Exception as exception:
+ logger.error('The following exception occurred while fetching measurement group: '
+ f'{exception}')
+ return {'error': 'Request was not processed due to Exception : '
+ f'{exception}'}, HTTPStatus.INTERNAL_SERVER_ERROR.value
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 96a803ba..548e4f28 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
@@ -52,10 +52,10 @@ class SubscriptionModel(db.Model):
self.status = status
def __repr__(self):
- return f'subscription_name: {self.subscription_name},' \
- f'operational_policy_name: {self.operational_policy_name},' \
- f'control_loop_name: {self.control_loop_name},' \
- f'status: {self.status}'
+ return (f'subscription_name: {self.subscription_name}, '
+ f'operational_policy_name: {self.operational_policy_name}, '
+ f'control_loop_name: {self.control_loop_name}, '
+ f'status: {self.status}')
def __eq__(self, other):
if isinstance(self, other.__class__):
@@ -67,6 +67,7 @@ class SubscriptionModel(db.Model):
'operationalPolicyName': self.operational_policy_name,
'controlLoopName': self.control_loop_name,
'nfFilter': self.network_filter.serialize(),
+ 'nfs': [nf.nf_name for nf in self.nfs],
'measurementGroups':
[mg.serialize() for mg in self.measurement_groups]}}
@@ -138,8 +139,8 @@ class NfSubRelationalModel(db.Model):
self.nf_sub_status = nf_sub_status
def __repr__(self):
- return f'subscription_name: {self.subscription_name}, ' \
- f'nf_name: {self.nf_name}, nf_sub_status: {self.nf_sub_status}'
+ return (f'subscription_name: {self.subscription_name}, '
+ f'nf_name: {self.nf_name}, nf_sub_status: {self.nf_sub_status}')
def serialize(self):
return {'subscription_name': self.subscription_name, 'nf_name': self.nf_name,
@@ -182,9 +183,9 @@ class NetworkFunctionFilterModel(db.Model):
self.model_names = model_names
def __repr__(self):
- return f'subscription_name: {self.subscription_name}, ' \
- f'nf_names: {self.nf_names}, model_invariant_ids: {self.model_invariant_ids}' \
- f'model_version_ids: {self.model_version_ids}, model_names: {self.model_names}'
+ return (f'subscription_name: {self.subscription_name}, '
+ f'nf_names: {self.nf_names}, model_invariant_ids: {self.model_invariant_ids}, '
+ f'model_version_ids: {self.model_version_ids}, model_names: {self.model_names}')
def serialize(self):
return {'nfNames': convert_db_string_to_list(self.nf_names),
@@ -219,13 +220,13 @@ class MeasurementGroupModel(db.Model):
self.managed_object_dns_basic = managed_object_dns_basic
def __repr__(self):
- return f'subscription_name: {self.subscription_name}, ' \
- f'measurement_group_name: {self.measurement_group_name},' \
- f'administrative_state: {self.administrative_state},' \
- f'file_based_gp: {self.file_based_gp},' \
- f'file_location: {self.file_location},' \
- f'measurement_type: {self.measurement_type}' \
- f'managed_object_dns_basic: {self.managed_object_dns_basic}'
+ return (f'subscription_name: {self.subscription_name}, '
+ f'measurement_group_name: {self.measurement_group_name}, '
+ f'administrative_state: {self.administrative_state}, '
+ f'file_based_gp: {self.file_based_gp}, '
+ f'file_location: {self.file_location}, '
+ f'measurement_type: {self.measurement_type}, '
+ f'managed_object_dns_basic: {self.managed_object_dns_basic}')
def serialize(self):
return {'measurementGroup': {'measurementGroupName': self.measurement_group_name,
@@ -235,6 +236,28 @@ class MeasurementGroupModel(db.Model):
'measurementTypes': self.measurement_type,
'managedObjectDNsBasic': self.managed_object_dns_basic}}
+ def meas_group_with_nfs(self):
+ """
+ Generates the dictionary of subscription name, measurement group name, administrative state
+ and network functions
+
+ Returns:
+ dict: of subscription name, measurement group name, administrative state
+ and network functions
+ """
+ meas_group_nfs = db.session.query(NfMeasureGroupRelationalModel).filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == self.measurement_group_name).all()
+ db.session.remove()
+ return {'subscriptionName': self.subscription_name,
+ 'measurementGroupName': self.measurement_group_name,
+ 'administrativeState': self.administrative_state,
+ 'fileBasedGP': self.file_based_gp,
+ 'fileLocation': self.file_location,
+ 'measurementTypes': self.measurement_type,
+ 'managedObjectDNsBasic': self.managed_object_dns_basic,
+ 'networkFunctions':
+ [meas_group_nf.serialize_meas_group_nfs() for meas_group_nf in meas_group_nfs]}
+
class NfMeasureGroupRelationalModel(db.Model):
__tablename__ = 'nf_to_measure_grp_rel'
@@ -262,8 +285,28 @@ class NfMeasureGroupRelationalModel(db.Model):
self.retry_count = retry_count
def __repr__(self):
- return f'measurement_grp_name: {self.measurement_grp_name}, ' \
- f'nf_name: {self.nf_name}, nf_measure_grp_status: {self.nf_measure_grp_status}'
+ return (f'measurement_grp_name: {self.measurement_grp_name}, '
+ f'nf_name: {self.nf_name}, nf_measure_grp_status: {self.nf_measure_grp_status}')
+
+ def serialize_meas_group_nfs(self):
+ """
+ Generates the dictionary of all the network function properties
+
+ Returns:
+ dict: of network function properties
+ """
+ nf = db.session.query(NetworkFunctionModel).filter(
+ NetworkFunctionModel.nf_name == self.nf_name).one_or_none()
+ db.session.remove()
+ return {'nfName': self.nf_name,
+ 'ipv4Address': nf.ipv4_address,
+ 'ipv6Address': nf.ipv6_address,
+ 'nfMgStatus': self.nf_measure_grp_status,
+ 'modelInvariantId': nf.model_invariant_id,
+ 'modelVersionId': nf.model_version_id,
+ 'modelName': nf.model_name,
+ 'sdncModelName': nf.sdnc_model_name,
+ 'sdncModelVersion': nf.sdnc_model_version}
def convert_db_string_to_list(db_string):
diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml b/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml
index f27fb7ab..4dd1cc70 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml
+++ b/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml
@@ -72,9 +72,24 @@ paths:
400:
description: Invalid input
+ get:
+ description: Get all the subscriptions from PMSH.
+ operationId: mod.api.controller.get_subscriptions
+ tags:
+ - "Subscription"
+ responses:
+ 200:
+ description: OK; Array of subscriptions are returned else empty if not found
+ schema:
+ type: array
+ items:
+ $ref: "#/definitions/subscription"
+ 500:
+ description: Exception occurred while querying database
+
/subscription/{subscription_name}:
get:
- description: Get the Subscription from ONAP specified by Name
+ description: Get the Subscription from PMSH specified by Name
operationId: mod.api.controller.get_subscription_by_name
tags:
- "Subscription"
@@ -92,7 +107,35 @@ paths:
404:
description: Subscription with specified name not found
500:
- description: Exception occurs while querying database
+ description: Exception occurred while querying database
+
+ /subscription/{subscription_name}/measurementGroups/{measurement_group_name}:
+ get:
+ description: Get the measurement group and associated network functions
+ from PMSH by using sub name and meas group name
+ operationId: mod.api.controller.get_meas_group_with_nfs
+ tags:
+ - "measurement group"
+ parameters:
+ - name : subscription_name
+ in: path
+ required: true
+ description: Name of the subscription
+ type: string
+ - name: measurement_group_name
+ in: path
+ required: true
+ description: Name of the measurement group name
+ type: string
+ responses:
+ 200:
+ description: OK; Received requested measurement group with associated NF's
+ schema:
+ $ref : "#/definitions/measGroupWithNFs"
+ 404:
+ description: Measurement group with specified name not found
+ 500:
+ description: Exception occurred while querying database
definitions:
subscription:
@@ -200,3 +243,60 @@ definitions:
type: string
required:
- DN
+
+ measGroupWithNFs:
+ type: object
+ properties:
+ subscriptionName:
+ type: string
+ measurementGroupName:
+ type: string
+ administrativeState:
+ type: string
+ enum: [ LOCKED, UNLOCKED ]
+ fileBasedGP:
+ type: integer
+ fileLocation:
+ type: string
+ measurementTypes:
+ type: array
+ minItems: 1
+ items:
+ $ref: "#/definitions/measurementType"
+ managedObjectDNsBasic:
+ type: array
+ minItems: 1
+ items:
+ $ref: "#/definitions/managedObjectDNs"
+ network_functions:
+ type: array
+ items:
+ type: object
+ properties:
+ nfName:
+ type: string
+ description: Name of the Network Function
+ ipv4Address:
+ type: string
+ description: Address of the IPV4
+ ipv6Address:
+ type: string
+ description: Address of the IPV6
+ nfMgStatus:
+ type: string
+ description: status of network function for one meas group
+ modelInvariantId:
+ type: string
+ description: ID of the model invariant
+ modelVersionId:
+ type: string
+ description: ID of the model version
+ modelName:
+ type: string
+ description: Name of the model
+ sdncModelName:
+ type: string
+ description: Name of the sdnc model
+ sdncModelVersion:
+ type: string
+ description: Version of the sdnc model
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 733d803e..692efe27 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
@@ -18,8 +18,8 @@
from mod.api.db_models import MeasurementGroupModel, NfMeasureGroupRelationalModel
from mod import db, logger
-from mod.subscription import SubNfState
from mod.api.services import nf_service
+from mod.network_function import NetworkFunction
from mod.pmsh_config import MRTopic, AppConfig
@@ -47,18 +47,19 @@ def save_measurement_group(measurement_group, subscription_name):
return new_measurement_group
-def apply_nf_to_measgroup(nf_name, measurement_group_name):
+def apply_nf_status_to_measurement_group(nf_name, measurement_group_name, status):
"""
Associate and saves the measurement group with Network function
Args:
nf_name (string): Network function name.
measurement_group_name (string): Measurement group name
+ status (string): nf status to apply on measurement group
"""
new_nf_measure_grp_rel = NfMeasureGroupRelationalModel(
measurement_grp_name=measurement_group_name,
nf_name=nf_name,
- nf_measure_grp_status=SubNfState.PENDING_CREATE.value
+ nf_measure_grp_status=status
)
db.session.add(new_nf_measure_grp_rel)
@@ -86,3 +87,68 @@ def publish_measurement_group(sub_model, measurement_group, nf):
}
logger.debug(f'Event Body: {event_body}')
AppConfig.get_instance().publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value, event_body)
+
+
+def update_measurement_group_nf_status(measurement_group_name, status, nf_name):
+ """ Updates the status of a measurement grp for a particular nf
+
+ Args:
+ measurement_group_name (string): Measurement group name
+ nf_name (string): The network function name
+ status (string): status of the network function for measurement group
+ """
+ try:
+ logger.info(f'Performing update for measurement group name: {measurement_group_name},'
+ f' network function name: {nf_name} on status: {status}')
+ NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == measurement_group_name,
+ NfMeasureGroupRelationalModel.nf_name == nf_name). \
+ update({NfMeasureGroupRelationalModel.nf_measure_grp_status: status},
+ synchronize_session='evaluate')
+ db.session.commit()
+ except Exception as e:
+ logger.error(f'Failed to update nf: {nf_name} for measurement group: '
+ f'{measurement_group_name} due to: {e}')
+
+
+def delete_nf_to_measurement_group(nf_name, measurement_group_name, status):
+ """ Deletes a particular nf related to a measurement group name and
+ if no more relations of nf exist to measurement group then delete nf from PMSH
+
+ Args:
+ nf_name (string): The network function name
+ measurement_group_name (string): Measurement group name
+ status (string): status of the network function for measurement group
+ """
+ try:
+ logger.info(f'Performing delete for measurement group name: {measurement_group_name},'
+ f' network function name: {nf_name} on status: {status}')
+ nf_measurement_group_rel = NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == measurement_group_name,
+ NfMeasureGroupRelationalModel.nf_name == nf_name).one_or_none()
+ db.session.delete(nf_measurement_group_rel)
+ db.session.commit()
+ nf_relations = NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.nf_name == nf_name).all()
+ if not nf_relations:
+ NetworkFunction.delete(nf_name=nf_name)
+ except Exception as e:
+ logger.error(f'Failed to delete nf: {nf_name} for measurement group: '
+ f'{measurement_group_name} due to: {e}')
+
+
+def query_meas_group_by_name(subscription_name, measurement_group_name):
+ """
+ Retrieves the measurement group by using sub name and measurement group name
+
+ Args:
+ subscription_name (String): Name of the subscription.
+ measurement_group_name (String): Name of the measurement group
+
+ Returns:
+ MeasurementGroupModel: queried measurement group (or) None
+ """
+ meas_group = db.session.query(MeasurementGroupModel).filter(
+ MeasurementGroupModel.subscription_name == subscription_name,
+ MeasurementGroupModel.measurement_group_name == measurement_group_name).one_or_none()
+ return meas_group
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 c41bb18b..fc27f992 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
@@ -21,7 +21,7 @@ from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, \
NetworkFunctionFilterModel, NetworkFunctionModel
from mod.api.services import measurement_group_service, nf_service
from mod.api.custom_exception import InvalidDataException, DuplicateDataException
-from mod.subscription import AdministrativeState
+from mod.subscription import AdministrativeState, SubNfState
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import joinedload
@@ -129,7 +129,7 @@ def apply_measurement_grp_to_nfs(filtered_nfs, measurement_groups):
Saves measurement groups against nfs with status as PENDING_CREATE
Args:
- filtered_nfs (list[NetworkFunction])): list of filtered network functions
+ filtered_nfs (list[NetworkFunction]): list of filtered network functions
measurement_groups (list[MeasurementGroupModel]): list of measurement group
Returns:
@@ -143,8 +143,9 @@ def apply_measurement_grp_to_nfs(filtered_nfs, measurement_groups):
for nf in filtered_nfs:
logger.info(f'Saving measurement group to nf name, measure_grp_name: {nf.nf_name},'
f'{measurement_group.measurement_group_name}')
- measurement_group_service.apply_nf_to_measgroup(
- nf.nf_name, measurement_group.measurement_group_name)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ nf.nf_name, measurement_group.measurement_group_name,
+ SubNfState.PENDING_CREATE.value)
else:
logger.info(f'No nfs added as measure_grp_name: '
f'{measurement_group.measurement_group_name} is LOCKED')
@@ -292,9 +293,9 @@ def save_nf_filter(nf_filter, subscription_name):
db.session.add(new_filter)
-def get_subscription_by_name(subscription_name):
+def query_subscription_by_name(subscription_name):
"""
- Retrieves the subscription information by name
+ Queries the db for existing subscription by name
Args:
subscription_name (String): Name of the Subscription
@@ -305,7 +306,41 @@ def get_subscription_by_name(subscription_name):
logger.info(f'Attempting to fetch subscription by name: {subscription_name}')
subscription_model = db.session.query(SubscriptionModel) \
.options(joinedload(SubscriptionModel.network_filter),
- joinedload(SubscriptionModel.measurement_groups)) \
+ joinedload(SubscriptionModel.measurement_groups),
+ joinedload(SubscriptionModel.nfs)) \
.filter_by(subscription_name=subscription_name).first()
db.session.remove()
return subscription_model
+
+
+def query_all_subscriptions():
+ """
+ Queries the db for all existing subscriptions defined in PMSH
+
+ Returns
+ list (SubscriptionModel): of all subscriptions else None
+ """
+ logger.info('Attempting to fetch all the subscriptions')
+ subscriptions = db.session.query(SubscriptionModel) \
+ .options(joinedload(SubscriptionModel.network_filter),
+ joinedload(SubscriptionModel.measurement_groups)) \
+ .all()
+ db.session.remove()
+ return subscriptions
+
+
+def get_subscriptions_list():
+ """ Converts all subscriptions to JSON and appends to list
+
+ Returns
+ list: dict of all subscriptions else empty
+ """
+ subscriptions = query_all_subscriptions()
+ subscriptions_list = []
+ if subscriptions is not None:
+ logger.info('Queried all the subscriptions was successful')
+ for subscription in subscriptions:
+ if (subscription.network_filter is not None) and \
+ (len(subscription.measurement_groups) != 0):
+ subscriptions_list.append(subscription.serialize())
+ return subscriptions_list
diff --git a/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py b/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py
index 09c97047..1bc58081 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2020 Nordix Foundation.
+# Copyright (C) 2020-2021 Nordix Foundation.
# ============================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,33 +15,31 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-
import json
-
+from mod.pmsh_config import MRTopic, AppConfig
from mod import logger
-from mod.network_function import NetworkFunction
-from mod.subscription import Subscription, AdministrativeState, subscription_nf_states
+from mod.subscription import AdministrativeState, subscription_nf_states
+from mod.api.db_models import MeasurementGroupModel
+from mod.api.services import measurement_group_service
policy_response_handle_functions = {
AdministrativeState.LOCKED.value: {
- 'success': NetworkFunction.delete,
- 'failed': Subscription.update_sub_nf_status
+ 'success': measurement_group_service.delete_nf_to_measurement_group,
+ 'failed': measurement_group_service.update_measurement_group_nf_status
},
AdministrativeState.UNLOCKED.value: {
- 'success': Subscription.update_sub_nf_status,
- 'failed': Subscription.update_sub_nf_status
+ 'success': measurement_group_service.update_measurement_group_nf_status,
+ 'failed': measurement_group_service.update_measurement_group_nf_status
},
AdministrativeState.LOCKING.value: {
- 'success': NetworkFunction.delete,
- 'failed': Subscription.update_sub_nf_status
+ 'success': measurement_group_service.delete_nf_to_measurement_group,
+ 'failed': measurement_group_service.update_measurement_group_nf_status
}
}
class PolicyResponseHandler:
- def __init__(self, mr_sub, app_conf, app):
- self.mr_sub = mr_sub
- self.app_conf = app_conf
+ def __init__(self, app):
self.app = app
def poll_policy_topic(self):
@@ -50,38 +48,49 @@ class PolicyResponseHandler:
relevant subscription and then handles the response
"""
self.app.app_context().push()
- administrative_state = self.app_conf.subscription.administrativeState
logger.info('Polling MR for XNF activation/deactivation policy response events.')
try:
- response_data = self.mr_sub.get_from_topic('dcae_pmsh_policy_cl_input')
+ response_data = AppConfig.get_instance(). \
+ get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 'dcae_pmsh_policy_cl_input')
for data in response_data:
data = json.loads(data)
- if data['status']['subscriptionName'] \
- == self.app_conf.subscription.subscriptionName:
- nf_name = data['status']['nfName']
- response_message = data['status']['message']
- self._handle_response(self.app_conf.subscription.subscriptionName,
- administrative_state, nf_name, response_message)
+ measurement_group_name = data['status']['measurementGroupName']
+ subscription_name = data['status']['subscriptionName']
+ measurement_group = (MeasurementGroupModel.query.filter(
+ MeasurementGroupModel.measurement_group_name == measurement_group_name,
+ subscription_name == MeasurementGroupModel
+ .subscription_name).one_or_none())
+ nf_name = data['status']['nfName']
+ response_message = data['status']['message']
+ if measurement_group:
+ self._handle_response(measurement_group_name,
+ measurement_group.administrative_state,
+ nf_name, response_message)
+ else:
+ logger.info(f'Polled MR response provides missing measurement '
+ f'group name : {measurement_group_name}')
except Exception as err:
logger.error(f'Error trying to poll policy response topic on MR: {err}', exc_info=True)
@staticmethod
- def _handle_response(subscription_name, administrative_state, nf_name, response_message):
+ def _handle_response(measurement_group_name, administrative_state, nf_name, response_message):
"""
Handles the response from Policy, updating the DB
-
Args:
- subscription_name (str): The subscription name
- administrative_state (str): The administrative state of the subscription
- nf_name (str): The network function name
- response_message (str): The message in the response regarding the state (success|failed)
+ measurement_group_name (string): The measurement group name
+ administrative_state (string): The administrative state of the measurement group
+ nf_name (string): The network function name
+ response_message (string): The message in the response
+ regarding the state (success|failed)
"""
- logger.info(f'Response from MR: Sub: {subscription_name} for '
+ logger.info(f'Response from MR: measurement group name: {measurement_group_name} for '
f'NF: {nf_name} received, updating the DB')
try:
- sub_nf_status = subscription_nf_states[administrative_state][response_message].value
+ nf_measure_grp_status = subscription_nf_states[administrative_state][response_message]\
+ .value
policy_response_handle_functions[administrative_state][response_message](
- subscription_name=subscription_name, status=sub_nf_status, nf_name=nf_name)
+ measurement_group_name=measurement_group_name, status=nf_measure_grp_status,
+ nf_name=nf_name)
except Exception as err:
logger.error(f'Error changing nf_sub status in the DB: {err}')
raise
diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py b/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
index 29f9121d..5fbb9a6c 100644
--- a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
+++ b/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py
@@ -18,9 +18,7 @@
from jsonschema import ValidationError
from mod import logger, aai_client
-from mod.aai_event_handler import process_aai_events
from mod.network_function import NetworkFunctionFilter
-from mod.pmsh_utils import PeriodicTask
from mod.subscription import AdministrativeState
@@ -73,7 +71,6 @@ class SubscriptionHandler:
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._start_aai_event_thread()
self.app_conf.subscription.update_sub_params(new_administrative_state,
self.app_conf.subscription.fileBasedGP,
self.app_conf.subscription.fileLocation,
@@ -91,15 +88,6 @@ class SubscriptionHandler:
self.app_conf.subscription.delete_subscription_from_nfs(nfs, self.mr_pub)
self.app_conf.subscription.update_subscription_status()
- def _start_aai_event_thread(self):
- logger.info('Starting polling for NF info on AAI-EVENT topic on DMaaP MR.')
- self.aai_event_thread = PeriodicTask(20, process_aai_events, args=(self.aai_sub,
- self.mr_pub,
- self.app,
- self.app_conf))
- self.aai_event_thread.name = 'aai_event_thread'
- self.aai_event_thread.start()
-
def stop_aai_event_thread(self):
if self.aai_event_thread is not None:
self.aai_event_thread.cancel()
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 0b6544b5..1af01cf1 100755
--- a/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py
+++ b/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py
@@ -17,7 +17,7 @@
# ============LICENSE_END=====================================================
import sys
from signal import signal, SIGTERM
-
+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 as NewAppConfig
@@ -35,13 +35,12 @@ def main():
app_conf = AppConfig()
pmsh_app_conf = NewAppConfig()
policy_mr_pub = app_conf.get_mr_pub('policy_pm_publisher')
- policy_mr_sub = app_conf.get_mr_sub('policy_pm_subscriber')
aai_event_mr_sub = app_conf.get_mr_sub('aai_subscriber')
except Exception as e:
logger.error(f'Failed to get config and create application: {e}', exc_info=True)
sys.exit(e)
- policy_response_handler = PolicyResponseHandler(policy_mr_sub, app_conf, app)
+ policy_response_handler = PolicyResponseHandler(app)
policy_response_handler_thread = PeriodicTask(25, policy_response_handler.poll_policy_topic)
policy_response_handler_thread.name = 'policy_event_thread'
logger.info('Start polling PMSH_CL_INPUT topic on DMaaP MR.')
@@ -52,8 +51,13 @@ def main():
subscription_handler_thread.name = 'sub_handler_thread'
subscription_handler_thread.start()
- periodic_tasks = [subscription_handler_thread, policy_response_handler_thread]
+ aai_event_handler = AAIEventHandler(app)
+ aai_event_handler_thread = PeriodicTask(20, aai_event_handler.execute)
+ aai_event_handler_thread.name = 'aai_event_thread'
+ aai_event_handler_thread.start()
+ periodic_tasks = [subscription_handler_thread, policy_response_handler_thread,
+ aai_event_handler_thread]
signal(SIGTERM, ExitHandler(periodic_tasks=periodic_tasks,
app_conf=app_conf, subscription_handler=subscription_handler))
launch_api_server(pmsh_app_conf)
diff --git a/components/pm-subscription-handler/tests/base_setup.py b/components/pm-subscription-handler/tests/base_setup.py
index 4328f59c..560eaeb8 100755
--- a/components/pm-subscription-handler/tests/base_setup.py
+++ b/components/pm-subscription-handler/tests/base_setup.py
@@ -22,18 +22,37 @@ from unittest import TestCase
from unittest.mock import patch, MagicMock
from mod import create_app, db
-from mod.api.db_models import NetworkFunctionFilterModel, MeasurementGroupModel, SubscriptionModel
+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
def get_pmsh_config(file_path='data/cbs_data_1.json'):
+ """
+ Gets PMSH config from the JSON file
+
+ Args:
+ file_path (String): Name of the file with path
+
+ Returns
+ dict: Dictionary representation of the the service configuration
+ """
with open(os.path.join(os.path.dirname(__file__), file_path), 'r') as data:
return json.load(data)
-def subscription_data(subscription_name):
+def create_subscription_data(subscription_name):
+ """
+ Creates subscription model object
+
+ Args:
+ subscription_name (String): Name of the Subscription
+
+ Returns
+ SubscriptionModel: single subscription model object
+ """
nf_filter = NetworkFunctionFilterModel(subscription_name, '{^pnf.*,^vnf.*}',
'{}', '{}', '{}')
mg_first = MeasurementGroupModel(subscription_name, 'MG1', 'UNLOCKED', 15, '/pm/pm.xml',
@@ -48,9 +67,48 @@ def subscription_data(subscription_name):
'pmsh_control_loop_name', 'LOCKED')
subscription_model.network_filter = nf_filter
subscription_model.measurement_groups = mg_list
+ nf1 = NfSubRelationalModel(subscription_name, "pnf_101", "LOCKED")
+ nf2 = NfSubRelationalModel(subscription_name, "pnf_102", "LOCKED")
+ subscription_model.nfs = [nf1, nf2]
return subscription_model
+def create_multiple_subscription_data(subscription_names):
+ """
+ Creates a list of subscription model objects
+
+ Args:
+ subscription_names (List): Name of the Subscriptions
+
+ Returns
+ list (SubscriptionModel): of subscription model objects
+ """
+ subscriptions = []
+ for subscription_name in subscription_names:
+ subscriptions.append(create_subscription_data(subscription_name))
+ return subscriptions
+
+
+def create_multiple_network_function_data(nf_name_list):
+ """
+ Creates list of network function model objects
+
+ Args:
+ nf_name_list (list): Network function names
+
+ Returns
+ list: of network function model objects
+ """
+ nf_list = []
+ for nf_name in nf_name_list:
+ nf = NetworkFunctionModel(nf_name, '10.10.10.32', '2001:0db8:0:0:0:0:1428:57ab',
+ '687kj45-d396-4efb-af02-6b83499b12f8',
+ 'e80a6ae3-cafd-4d24-850d-e14c084a5ca9',
+ 'model_name', 'pm_control', '1.0.2')
+ nf_list.append(nf)
+ return nf_list
+
+
class BaseClassSetup(TestCase):
app = None
app_context = None
diff --git a/components/pm-subscription-handler/tests/data/mr_aai_events.json b/components/pm-subscription-handler/tests/data/mr_aai_events.json
index 19758982..42639d9f 100755
--- a/components/pm-subscription-handler/tests/data/mr_aai_events.json
+++ b/components/pm-subscription-handler/tests/data/mr_aai_events.json
@@ -2,7 +2,8 @@
"mr_response": [
"{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"UPDATE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3640\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"ipaddress-v4-oam\":\"10.10.10.37\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_newly_discovered\",\"model-invariant-id\":\"7129e420-d396-4efb-af02-6b83499b12f8\",\"model-version-id\":\"e80a6ae3-cafd-4d24-850d-e14c084a5ca9\",\"orchestration-status\":\"Active\"}}",
"{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"UPDATE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3640\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"orchestration-status\":\"Active\",\"ipaddress-v4-oam\":\"10.10.10.37\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_already_active\",\"model-invariant-id\":\"7129e420-d396-4efb-af02-6b83499b12f8\",\"model-version-id\":\"e80a6ae3-cafd-4d24-850d-e14c084a5ca9\",\"orchestration-status\":\"Active\"}}",
- "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"DELETE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3640\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"ipaddress-v4-oam\":\"10.10.10.37\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_to_be_deleted\",\"model-invariant-id\":\"7129e420-d396-4efb-af02-6b83499b12f8\",\"model-version-id\":\"e80a6ae3-cafd-4d24-850d-e14c084a5ca9\",\"orchestration-status\":\"Active\"}}",
+ "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"DELETE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3640\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"ipaddress-v4-oam\":\"10.10.10.37\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_to_be_deleted1\",\"model-invariant-id\":\"7129e420-d396-4efb-af02-6b83499b12f8\",\"model-version-id\":\"e80a6ae3-cafd-4d24-850d-e14c084a5ca9\",\"orchestration-status\":\"Active\"}}",
+ "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"pnf\",\"top-entity-type\":\"pnf\",\"entity-link\":\"/aai/v16/network/pnfs/pnf/pnf_newly_discovered\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"DELETE\",\"sequence-number\":\"0\",\"id\":\"db09e090-196e-4f84-9645-e449b1cd3641\",\"source-name\":\"dcae-curl\",\"version\":\"v16\",\"timestamp\":\"20200203-15:14:08:807\"},\"entity\":{\"ipaddress-v4-oam\":\"10.10.10.38\",\"nf-role\":\"gNB\",\"equip-type\":\"val8\",\"relationship-list\":{\"relationship\":[{\"related-to\":\"service-instance\",\"relationship-data\":[{\"relationship-value\":\"Demonstration\",\"relationship-key\":\"customer.global-customer-id\"},{\"relationship-value\":\"vCPE\",\"relationship-key\":\"service-subscription.service-type\"},{\"relationship-value\":\"2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-key\":\"service-instance.service-instance-id\"}],\"related-link\":\"/aai/v16/business/customers/customer/Demonstration/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/2c03b2a8-e31a-4749-9e99-3089ab441400\",\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\",\"related-to-property\":[{\"property-key\":\"service-instance.service-instance-name\",\"property-value\":\"Svc6_1\"}]}]},\"equip-vendor\":\"Ericsson\",\"serial-number\":\"6061ZW3\",\"ipaddress-v6-oam\":\"2001:0db8:0:0:0:0:1428:57ab\",\"equip-model\":\"val6\",\"in-maint\":false,\"resource-version\":\"1578668956804\",\"sw-version\":\"val7\",\"pnf-id\":\"eabcfaf7-b7f3-45fb-94e7-e6112fb3e8b8\",\"pnf-name\":\"pnf_to_be_deleted2\",\"model-invariant-id\":\"7129e420-d396-4efb-af02-6b83499b12f8\",\"model-version-id\":\"e80a6ae3-cafd-4d24-850d-e14c084a5ca9\",\"orchestration-status\":\"Active\"}}",
"{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"model-ver\",\"top-entity-type\":\"model\",\"entity-link\":\"/aai/v19/service-design-and-creation/models/model/60cd7bbf-0a6b-43ce-a5af-07cbf168ecdc/model-vers/model-ver/5485c7ac-825f-414d-aba4-e24147107d0b\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"UPDATE\",\"sequence-number\":\"0\",\"id\":\"e16cb0f9-3617-4a14-9c81-f7ee4cdf9df7\",\"source-name\":\"UNKNOWN\",\"version\":\"v19\",\"timestamp\":\"20200701-12:06:12:135\"},\"entity\":{\"model-type\":\"service\",\"model-vers\":{\"model-ver\":[{\"model-version-id\":\"5485c7ac-825f-414d-aba4-e24147107d0b\",\"resource-version\":\"1593605171956\",\"model-description\":\"catalog service description\",\"model-name\":\"Demo_pNF_WCcM9Z2VNE3eGfLIKulP\",\"model-elements\":{\"model-element\":[{\"relationship-list\":{\"relationship\":[{\"related-to\":\"model-ver\",\"relationship-data\":[{\"relationship-value\":\"82194af1-3c2c-485a-8f44-420e22a9eaa4\",\"relationship-key\":\"model.model-invariant-id\"},{\"relationship-value\":\"46b92144-923a-4d20-b85a-3cbd847668a9\",\"relationship-key\":\"model-ver.model-version-id\"}],\"related-link\":\"/aai/v19/service-design-and-creation/models/model/82194af1-3c2c-485a-8f44-420e22a9eaa4/model-vers/model-ver/46b92144-923a-4d20-b85a-3cbd847668a9\",\"relationship-label\":\"org.onap.relationships.inventory.IsA\",\"related-to-property\":[{\"property-key\":\"model-ver.model-name\",\"property-value\":\"service-instance\"}]}]},\"resource-version\":\"1593605012006\",\"model-elements\":{\"model-element\":[{\"relationship-list\":{\"relationship\":[{\"related-to\":\"model-ver\",\"relationship-data\":[{\"relationship-value\":\"c8fb1064-f38a-4a13-90a6-ec60289879ac\",\"relationship-key\":\"model.model-invariant-id\"},{\"relationship-value\":\"94c051c3-4484-425e-a107-6914816321a6\",\"relationship-key\":\"model-ver.model-version-id\"}],\"related-link\":\"/aai/v19/service-design-and-creation/models/model/c8fb1064-f38a-4a13-90a6-ec60289879ac/model-vers/model-ver/94c051c3-4484-425e-a107-6914816321a6\",\"relationship-label\":\"org.onap.relationships.inventory.IsA\",\"related-to-property\":[{\"property-key\":\"model-ver.model-name\",\"property-value\":\"pNF 77be3d89-b735\"}]}]},\"resource-version\":\"1593605012006\",\"new-data-del-flag\":\"T\",\"cardinality\":\"unbounded\",\"model-element-uuid\":\"44712769-981d-4970-9ea5-4c99b86f838e\"}]},\"new-data-del-flag\":\"T\",\"cardinality\":\"unbounded\",\"model-element-uuid\":\"4a601305-9e09-4152-98ad-b8c466d57813\"}]},\"model-version\":\"1.0\",\"distribution-status\":\"DISTRIBUTION_COMPLETE_OK\"}]},\"model-invariant-id\":\"60cd7bbf-0a6b-43ce-a5af-07cbf168ecdc\"}}",
"{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"customer\",\"top-entity-type\":\"customer\",\"entity-link\":\"/aai/v19/business/customers/customer/ETE_Customer_5638d7b4-a02d-4cc4-801e-77ee837d2855\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"CREATE\",\"sequence-number\":\"0\",\"id\":\"ef390383-3d08-4268-a013-d11c14efd716\",\"source-name\":\"robot-ete\",\"version\":\"v19\",\"timestamp\":\"20200701-12:06:50:388\"},\"entity\":{\"global-customer-id\":\"ETE_Customer_5638d7b4-a02d-4cc4-801e-77ee837d2855\",\"subscriber-type\":\"INFRA\",\"resource-version\":\"1593605210258\",\"subscriber-name\":\"ETE_Customer_5638d7b4-a02d-4cc4-801e-77ee837d2855\",\"service-subscriptions\":{\"service-subscription\":[{\"relationship-list\":{\"relationship\":[{\"related-to\":\"tenant\",\"relationship-data\":[{\"relationship-value\":\"CloudOwner\",\"relationship-key\":\"cloud-region.cloud-owner\"},{\"relationship-value\":\"RegionForPNF\",\"relationship-key\":\"cloud-region.cloud-region-id\"},{\"relationship-value\":\"dummy_tenant_id_for_pnf\",\"relationship-key\":\"tenant.tenant-id\"}],\"related-link\":\"/aai/v19/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionForPNF/tenants/tenant/dummy_tenant_id_for_pnf\",\"relationship-label\":\"org.onap.relationships.inventory.Uses\",\"related-to-property\":[{\"property-key\":\"tenant.tenant-name\",\"property-value\":\"dummy_tenant_for_pnf\"}]}]},\"resource-version\":\"1593605210258\",\"service-type\":\"pNF\"}]}}}"
]
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 46c4bac7..97353afe 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
@@ -23,9 +23,9 @@ from mod.network_function import NetworkFunction
from mod.pmsh_config import AppConfig
from mod import db
from tests.base_setup import BaseClassSetup
-from mod.api.services import measurement_group_service
-from mod.api.db_models import MeasurementGroupModel, NfMeasureGroupRelationalModel,\
- SubscriptionModel
+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
@@ -99,17 +99,94 @@ class MeasurementGroupServiceTestCase(BaseClassSetup):
MeasurementGroupModel.subscription_name == 'ExtraPM-All-gNB-R2B').one_or_none())
self.assertIsNotNone(measurement_grp)
- def test_apply_nf_to_measgroup(self):
- measurement_group_service.apply_nf_to_measgroup("pnf_test", "measure_grp_name")
+ 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)
db.session.commit()
measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name',
NfMeasureGroupRelationalModel.nf_name == 'pnf_test').one_or_none())
- db.session.commit()
self.assertIsNotNone(measurement_grp_rel)
self.assertEqual(measurement_grp_rel.nf_measure_grp_status,
SubNfState.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)
+ measurement_group_service.update_measurement_group_nf_status(
+ "measure_grp_name", SubNfState.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)
+
+ 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)
+ measurement_group_service.apply_nf_status_to_measurement_group(
+ "pnf_test1", "measure_grp_name2", SubNfState.PENDING_CREATE.value)
+ measurement_group_service.delete_nf_to_measurement_group(
+ "pnf_test1", "measure_grp_name1", SubNfState.DELETED.value)
+ measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name1',
+ NfMeasureGroupRelationalModel.nf_name == 'pnf_test1').one_or_none())
+ self.assertIsNone(measurement_grp_rel)
+ network_function = (NetworkFunctionModel.query.filter(
+ NetworkFunctionModel.nf_name == 'pnf_test1').one_or_none())
+ self.assertIsNotNone(network_function)
+
+ def test_delete_nf_to_measurement_group_with_nf_delete(self):
+ nf = NetworkFunction(nf_name='pnf_test2')
+ 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)
+ measurement_group_service.delete_nf_to_measurement_group(
+ "pnf_test2", "measure_grp_name2", SubNfState.DELETED.value)
+ measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name2',
+ NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNone(measurement_grp_rel)
+ network_function = (NetworkFunctionModel.query.filter(
+ NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNone(network_function)
+
+ @patch.object(NetworkFunction, 'delete')
+ @patch('mod.logger.error')
+ def test_delete_nf_to_measurement_group_failure(self, mock_logger, nf_delete_func):
+ nf = NetworkFunction(nf_name='pnf_test2')
+ 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)
+ nf_delete_func.side_effect = Exception('delete failed')
+ measurement_group_service.delete_nf_to_measurement_group(
+ "pnf_test2", "measure_grp_name2", SubNfState.DELETED.value)
+ measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter(
+ NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name2',
+ NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNone(measurement_grp_rel)
+ network_function = (NetworkFunctionModel.query.filter(
+ NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none())
+ self.assertIsNotNone(network_function)
+ mock_logger.assert_called_with('Failed to delete nf: pnf_test2 for '
+ 'measurement group: measure_grp_name2 due to: delete failed')
+
+ @patch.object(db.session, 'commit')
+ @patch('mod.logger.error')
+ 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")
+ mock_logger.assert_called_with('Failed to update nf: pnf_test2 for '
+ 'measurement group: measure_grp_name2 due to: update failed')
+
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 a0e4d541..44fb4eff 100644
--- a/components/pm-subscription-handler/tests/services/test_subscription_service.py
+++ b/components/pm-subscription-handler/tests/services/test_subscription_service.py
@@ -29,6 +29,7 @@ from mod.api.custom_exception import DuplicateDataException, InvalidDataExceptio
from mod.pmsh_config import AppConfig
from tests.base_setup import BaseClassSetup
from mod.api.services import subscription_service, nf_service, measurement_group_service
+from tests.base_setup import create_multiple_subscription_data
class SubscriptionServiceTestCase(BaseClassSetup):
@@ -170,7 +171,7 @@ class SubscriptionServiceTestCase(BaseClassSetup):
@patch.object(aai_client, '_get_all_aai_nf_data')
@patch.object(aai_client, 'get_aai_model_data')
- @patch.object(measurement_group_service, 'apply_nf_to_measgroup')
+ @patch.object(measurement_group_service, 'apply_nf_status_to_measurement_group')
@patch.object(NetworkFunctionFilter, 'get_network_function_filter')
def test_apply_measurement_grp_to_nfs(self, mock_filter_call, mock_apply_nf,
mock_model_aai, mock_aai):
@@ -357,3 +358,22 @@ class SubscriptionServiceTestCase(BaseClassSetup):
db_string = '{}'
db_array = convert_db_string_to_list(db_string)
self.assertEqual(len(db_array), 0)
+
+ @patch('mod.api.services.subscription_service.query_all_subscriptions',
+ MagicMock(return_value=create_multiple_subscription_data(
+ ['sub_demo_one', 'sub_demo_two'])))
+ def test_get_subscriptions_list(self):
+ subs = subscription_service.get_subscriptions_list()
+ self.assertEqual(subs[0]['subscription']['subscriptionName'], 'sub_demo_one')
+ self.assertEqual(subs[1]['subscription']['subscriptionName'], 'sub_demo_two')
+ self.assertEqual(subs[1]['subscription']['measurementGroups'][0]['measurementGroup']
+ ['measurementGroupName'], 'MG1')
+ self.assertEqual(len(subs[1]['subscription']['measurementGroups']), 2)
+ self.assertEqual(len(subs), 2)
+ self.assertEqual(len(subs[0]['subscription']['nfs']), 2)
+
+ @patch('mod.api.services.subscription_service.query_all_subscriptions',
+ MagicMock(return_value=[]))
+ def test_get_subscriptions_list_empty(self):
+ subs = subscription_service.get_subscriptions_list()
+ self.assertEqual(subs, [])
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 0ae19429..d06b7728 100755
--- a/components/pm-subscription-handler/tests/test_aai_event_handler.py
+++ b/components/pm-subscription-handler/tests/test_aai_event_handler.py
@@ -1,5 +1,5 @@
# ============LICENSE_START===================================================
-# Copyright (C) 2020 Nordix Foundation.
+# Copyright (C) 2020-2021 Nordix Foundation.
# ============================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,27 +15,28 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
+import copy
import json
from os import path
-from unittest.mock import patch, Mock
-
-from mod.aai_event_handler import process_aai_events
+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 import db
class AAIEventHandlerTest(BaseClassSetup):
-
@classmethod
def setUpClass(cls):
super().setUpClass()
def setUp(self):
super().setUp()
+ super().setUpAppConf()
with open(path.join(path.dirname(__file__), 'data/mr_aai_events.json'), 'r') as data:
self.mr_aai_events = json.load(data)["mr_response"]
- self.mock_mr_sub = Mock(get_from_topic=Mock(return_value=self.mr_aai_events))
- self.mock_mr_pub = Mock()
- self.mock_app = Mock()
def tearDown(self):
super().tearDown()
@@ -44,12 +45,100 @@ class AAIEventHandlerTest(BaseClassSetup):
def tearDownClass(cls):
super().tearDownClass()
- @patch('mod.network_function.NetworkFunction.set_nf_model_params')
- @patch('mod.subscription.Subscription.create_subscription_on_nfs')
+ @patch('mod.pmsh_config.AppConfig.get_from_topic')
@patch('mod.aai_event_handler.NetworkFunction.delete')
- def test_process_aai_update_and_delete_events(self, mock_nf_delete, mock_activate_sub,
- mock_set_sdnc_params):
+ def test_process_aai_delete_events(self, mock_nf_delete, mr_aai_mock):
+ mr_aai_mock.return_value = self.mr_aai_events
+ aai_handler = AAIEventHandler(self.app)
+ network_function = NetworkFunctionModel(
+ nf_name="pnf_to_be_deleted1",
+ ipv4_address='204.120.0.15',
+ ipv6_address='2001:db8:3333:4444:5555:6666:7777:8888',
+ model_invariant_id='123',
+ model_version_id='234',
+ model_name='pnf',
+ sdnc_model_name='p-node',
+ sdnc_model_version='v1')
+ db.session.add(network_function)
+ network_function2 = copy.deepcopy(network_function)
+ network_function2.nf_name = "pnf_to_be_deleted2"
+ db.session.add(network_function2)
+ db.session.commit()
+ aai_handler.execute()
+ self.assertEqual(mock_nf_delete.call_count, 2)
+
+ @patch('mod.aai_event_handler.AAIEventHandler.apply_nfs_to_subscriptions')
+ @patch('mod.network_function.NetworkFunction.set_nf_model_params')
+ @patch('mod.pmsh_config.AppConfig.get_from_topic')
+ def test_process_aai_update_events(self, mr_aai_mock, mock_set_sdnc_params, mock_apply_nfs):
+ mock_set_sdnc_params.return_value = True
+ mr_aai_mock.return_value = self.mr_aai_events
+ aai_handler = AAIEventHandler(self.app)
+ aai_handler.execute()
+ self.assertEqual(mock_apply_nfs.call_count, 1)
+
+ @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
+ @patch('mod.api.services.subscription_service.apply_measurement_grp_to_nfs')
+ @patch('mod.network_function.NetworkFunction.set_nf_model_params')
+ @patch('mod.pmsh_config.AppConfig.get_from_topic')
+ def test_process_aai_apply_nfs_to_subscriptions(self, mr_aai_mock, mock_set_sdnc_params,
+ apply_nfs_to_measure_grp):
mock_set_sdnc_params.return_value = True
- process_aai_events(self.mock_mr_sub, self.mock_mr_pub, self.mock_app, self.app_conf)
- self.assertEqual(mock_activate_sub.call_count, 2)
- mock_nf_delete.assert_called_once()
+ 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')
+ db.session.commit()
+ aai_handler.execute()
+ self.assertEqual(apply_nfs_to_measure_grp.call_count, 2)
+
+ @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
+ @patch('mod.api.services.subscription_service.apply_measurement_grp_to_nfs')
+ @patch('mod.network_function.NetworkFunction.set_nf_model_params')
+ @patch('mod.logger.error')
+ @patch('mod.pmsh_config.AppConfig.get_from_topic')
+ def test_process_aai_apply_msg_failure(self, mr_aai_mock, mock_logger, mock_set_sdnc_params,
+ apply_nfs_to_measure_grp):
+ mock_set_sdnc_params.return_value = True
+ 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 '
+ 'due to: publish failed')
+
+ @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None))
+ @patch('mod.network_function.NetworkFunction.set_nf_model_params')
+ @patch('mod.logger.error')
+ @patch('mod.pmsh_config.AppConfig.get_from_topic')
+ def test_process_aai__failure(self, mr_aai_mock, mock_logger, mock_set_sdnc_params):
+ 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_controller.py b/components/pm-subscription-handler/tests/test_controller.py
index 7bd72a29..962e8fb2 100755
--- a/components/pm-subscription-handler/tests/test_controller.py
+++ b/components/pm-subscription-handler/tests/test_controller.py
@@ -20,13 +20,16 @@ import os
from unittest.mock import patch, MagicMock
from http import HTTPStatus
-from mod import aai_client
-from mod.api.controller import status, post_subscription, get_subscription_by_name
+from mod import aai_client, db
+from mod.api.controller import status, post_subscription, get_subscription_by_name, \
+ get_subscriptions, get_meas_group_with_nfs
from tests.base_setup import BaseClassSetup
from mod.api.db_models import SubscriptionModel, NfMeasureGroupRelationalModel
from mod.subscription import SubNfState
from mod.network_function import NetworkFunctionFilter
-from tests.base_setup import subscription_data
+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
class ControllerTestCase(BaseClassSetup):
@@ -111,11 +114,11 @@ class ControllerTestCase(BaseClassSetup):
self.assertEqual(response[1], 400)
self.assertEqual(response[0], 'No value provided in subscription name')
- @patch('mod.api.services.subscription_service.get_subscription_by_name',
- MagicMock(return_value=subscription_data('sub_demo')))
+ @patch('mod.api.services.subscription_service.query_subscription_by_name',
+ MagicMock(return_value=create_subscription_data('sub_demo')))
def test_get_subscription_by_name_api(self):
sub, status_code = get_subscription_by_name('sub_demo')
- self.assertEqual(status_code, HTTPStatus.OK)
+ self.assertEqual(status_code, HTTPStatus.OK.value)
self.assertEqual(sub['subscription']['subscriptionName'], 'sub_demo')
self.assertEqual(sub['subscription']['nfFilter']['nfNames'],
['^pnf.*', '^vnf.*'])
@@ -125,16 +128,74 @@ class ControllerTestCase(BaseClassSetup):
self.assertEqual(sub['subscription']['operationalPolicyName'],
'pmsh_operational_policy')
- @patch('mod.api.services.subscription_service.get_subscription_by_name',
+ @patch('mod.api.services.subscription_service.query_subscription_by_name',
MagicMock(return_value=None))
- def test_get_subscription_by_name_api_error(self):
+ def test_get_subscription_by_name_api_none(self):
sub, status_code = get_subscription_by_name('sub_demo')
- self.assertEqual(status_code, HTTPStatus.NOT_FOUND)
+ self.assertEqual(status_code, HTTPStatus.NOT_FOUND.value)
self.assertEqual(sub['error'],
'Subscription was not defined with the name : sub_demo')
- @patch('mod.api.services.subscription_service.get_subscription_by_name',
+ @patch('mod.api.services.subscription_service.query_subscription_by_name',
MagicMock(side_effect=Exception('something failed')))
def test_get_subscription_by_name_api_exception(self):
sub, status_code = get_subscription_by_name('sub_demo')
- self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR)
+ self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value)
+
+ @patch('mod.api.services.subscription_service.query_all_subscriptions',
+ MagicMock(return_value=create_multiple_subscription_data(
+ ['sub_demo_one', 'sub_demo_two'])))
+ def test_get_subscriptions_api(self):
+ subs, status_code = get_subscriptions()
+ self.assertEqual(status_code, HTTPStatus.OK.value)
+ self.assertEqual(subs[0]['subscription']['subscriptionName'], 'sub_demo_one')
+ self.assertEqual(subs[1]['subscription']['subscriptionName'], 'sub_demo_two')
+ self.assertEqual(subs[1]['subscription']['measurementGroups'][0]['measurementGroup']
+ ['measurementGroupName'], 'MG1')
+ self.assertEqual(len(subs[1]['subscription']['measurementGroups']), 2)
+ self.assertEqual(len(subs), 2)
+
+ @patch('mod.api.services.subscription_service.query_all_subscriptions',
+ MagicMock(return_value=None))
+ def test_get_subscriptions_api_none(self):
+ subs, status_code = get_subscriptions()
+ self.assertEqual(status_code, HTTPStatus.OK.value)
+ self.assertEqual(subs, [])
+
+ @patch('mod.api.services.subscription_service.query_all_subscriptions',
+ MagicMock(side_effect=Exception('something failed')))
+ def test_get_subscriptions_api_exception(self):
+ subs, status_code = get_subscriptions()
+ self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value)
+
+ def test_get_meas_group_with_nfs_api(self):
+ sub = create_subscription_data('sub1')
+ nf_list = create_multiple_network_function_data(['pnf101', 'pnf102'])
+ measurement_group_service.save_measurement_group(sub.measurement_groups[0].
+ serialize()['measurementGroup'],
+ sub.subscription_name)
+ for nf in nf_list:
+ nf_service.save_nf(nf)
+ measurement_group_service. \
+ apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[0].
+ measurement_group_name,
+ SubNfState.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)
+ self.assertEqual(mg_with_nfs['subscriptionName'], 'sub1')
+ self.assertEqual(mg_with_nfs['measurementGroupName'], 'MG1')
+ self.assertEqual(mg_with_nfs['administrativeState'], 'UNLOCKED')
+ self.assertEqual(len(mg_with_nfs['networkFunctions']), 2)
+
+ def test_get_meas_group_with_nfs_api_none(self):
+ error, status_code = get_meas_group_with_nfs('sub1', 'MG1')
+ self.assertEqual(error['error'], 'measurement group was not defined with '
+ 'the sub name: sub1 and meas group name: MG1')
+ self.assertEqual(status_code, HTTPStatus.NOT_FOUND.value)
+
+ @patch('mod.api.services.measurement_group_service.query_meas_group_by_name',
+ MagicMock(side_effect=Exception('something failed')))
+ def test_get_meas_group_with_nfs_api_exception(self):
+ error, status_code = get_meas_group_with_nfs('sub1', 'MG1')
+ self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value)
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 9bf15939..3e6abf94 100644
--- a/components/pm-subscription-handler/tests/test_policy_response_handler.py
+++ b/components/pm-subscription-handler/tests/test_policy_response_handler.py
@@ -15,30 +15,26 @@
#
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=====================================================
-from unittest.mock import patch
+from unittest.mock import patch, MagicMock
-from mod.api.db_models import SubscriptionModel
+from mod import db
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
+from tests.base_setup import BaseClassSetup, create_subscription_data
class PolicyResponseHandlerTest(BaseClassSetup):
-
@classmethod
def setUpClass(cls):
super().setUpClass()
@patch('mod.create_app')
- @patch('mod.pmsh_utils._MrSub')
- def setUp(self, mock_mr_sub, mock_app):
+ def setUp(self, mock_app):
super().setUp()
- self.mock_policy_mr_sub = mock_mr_sub
+ super().setUpAppConf()
self.nf = NetworkFunction(nf_name='nf1')
- self.policy_response_handler = PolicyResponseHandler(self.mock_policy_mr_sub,
- self.app_conf,
- mock_app)
+ self.policy_response_handler = PolicyResponseHandler(mock_app)
def tearDown(self):
super().tearDown()
@@ -52,46 +48,67 @@ class PolicyResponseHandlerTest(BaseClassSetup):
with patch.dict(policy_response_handle_functions,
{AdministrativeState.LOCKED.value: {'success': mock_delete}}):
self.policy_response_handler._handle_response(
- self.app_conf.subscription.subscriptionName,
+ 'msr_grp_name',
AdministrativeState.LOCKED.value,
self.nf.nf_name, 'success')
-
mock_delete.assert_called()
- @patch('mod.subscription.Subscription.update_sub_nf_status')
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
def test_handle_response_locked_failed(self, mock_update_sub_nf):
with patch.dict(policy_response_handle_functions,
{AdministrativeState.LOCKED.value: {'failed': mock_update_sub_nf}}):
self.policy_response_handler._handle_response(
- self.app_conf.subscription.subscriptionName,
+ 'msr_grp_name',
AdministrativeState.LOCKED.value,
self.nf.nf_name, 'failed')
mock_update_sub_nf.assert_called_with(
- subscription_name=self.app_conf.subscription.subscriptionName,
+ measurement_group_name='msr_grp_name',
+ status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name)
+
+ @patch('mod.network_function.NetworkFunction.delete')
+ def test_handle_response_locking_success(self, mock_delete):
+ with patch.dict(policy_response_handle_functions,
+ {AdministrativeState.LOCKING.value: {'success': mock_delete}}):
+ self.policy_response_handler._handle_response(
+ 'msr_grp_name',
+ AdministrativeState.LOCKING.value,
+ self.nf.nf_name, 'success')
+ mock_delete.assert_called()
+
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
+ def test_handle_response_locking_failed(self, mock_update_sub_nf):
+ with patch.dict(policy_response_handle_functions,
+ {AdministrativeState.LOCKING.value: {'failed': mock_update_sub_nf}}):
+ self.policy_response_handler._handle_response(
+ 'msr_grp_name',
+ AdministrativeState.LOCKING.value,
+ 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)
- @patch('mod.subscription.Subscription.update_sub_nf_status')
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
def test_handle_response_unlocked_success(self, mock_update_sub_nf):
with patch.dict(policy_response_handle_functions,
{AdministrativeState.UNLOCKED.value: {'success': mock_update_sub_nf}}):
self.policy_response_handler._handle_response(
- self.app_conf.subscription.subscriptionName,
+ 'msr_grp_name',
AdministrativeState.UNLOCKED.value,
self.nf.nf_name, 'success')
mock_update_sub_nf.assert_called_with(
- subscription_name=self.app_conf.subscription.subscriptionName,
+ measurement_group_name='msr_grp_name',
status=SubNfState.CREATED.value, nf_name=self.nf.nf_name)
- @patch('mod.subscription.Subscription.update_sub_nf_status')
+ @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status')
def test_handle_response_unlocked_failed(self, mock_update_sub_nf):
with patch.dict(policy_response_handle_functions,
{AdministrativeState.UNLOCKED.value: {'failed': mock_update_sub_nf}}):
self.policy_response_handler._handle_response(
- self.app_conf.subscription.subscriptionName,
+ 'msr_grp_name',
AdministrativeState.UNLOCKED.value,
self.nf.nf_name, 'failed')
mock_update_sub_nf.assert_called_with(
- subscription_name=self.app_conf.subscription.subscriptionName,
+ measurement_group_name='msr_grp_name',
status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name)
def test_handle_response_exception(self):
@@ -99,45 +116,34 @@ class PolicyResponseHandlerTest(BaseClassSetup):
'wrong_state', 'nf1', 'wrong_message')
@patch('mod.policy_response_handler.PolicyResponseHandler._handle_response')
- @patch('mod.subscription.Subscription.get')
- def test_poll_policy_topic_calls_methods_correct_sub(self, mock_get_sub, mock_handle_response):
+ @patch('mod.pmsh_config.AppConfig.get_from_topic')
+ def test_poll_policy_topic_calls_methods_correct_mg(self, mock_policy_mr_sub,
+ mock_handle_response):
response_data = ['{"name": "ResponseEvent","status": { "subscriptionName": '
- '"ExtraPM-All-gNB-R2B", "nfName": "pnf300", "message": "success" } }']
- self.mock_policy_mr_sub.get_from_topic.return_value = response_data
- mock_get_sub.return_value = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
- operational_policy_name='policy-name',
- control_loop_name='control-loop-name',
- status=AdministrativeState.UNLOCKED.value)
+ '"ExtraPM-All-gNB-R2B2", "nfName": "pnf300", "message": "success", '
+ '"measurementGroupName":"MG1"} }']
+ mock_policy_mr_sub.return_value = response_data
+ sub_model = create_subscription_data('ExtraPM-All-gNB-R2B2')
+ db.session.add(sub_model)
+ db.session.commit()
self.policy_response_handler.poll_policy_topic()
- self.mock_policy_mr_sub.get_from_topic.assert_called()
- mock_handle_response.assert_called_with(self.app_conf.subscription.subscriptionName,
+ mock_handle_response.assert_called_with("MG1",
AdministrativeState.UNLOCKED.value, 'pnf300',
'success')
@patch('mod.policy_response_handler.PolicyResponseHandler._handle_response')
- @patch('mod.subscription.Subscription.get')
- def test_poll_policy_topic_no_method_calls_incorrect_sub(self, mock_get_sub,
- mock_handle_response):
+ @patch('mod.pmsh_config.AppConfig.get_from_topic')
+ def test_poll_policy_topic_no_method_calls_unavailable_mg(self, mock_policy_mr_sub,
+ mock_handle_response):
response_data = ['{"name": "ResponseEvent","status": { "subscriptionName": '
- '"Different_Subscription", "nfName": "pnf300", "message": "success" } }']
- self.mock_policy_mr_sub.get_from_topic.return_value = response_data
- mock_get_sub.return_value = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
- operational_policy_name='policy-name',
- control_loop_name='control-loop-name',
- status=AdministrativeState.UNLOCKED.value)
+ '"Different_Subscription", "nfName": "pnf300", "message": "success",'
+ '"measurementGroupName":"msr_grp_name" } }']
+ mock_policy_mr_sub.return_value = response_data
self.policy_response_handler.poll_policy_topic()
-
- self.mock_policy_mr_sub.get_from_topic.assert_called()
-
mock_handle_response.assert_not_called()
+ @patch('mod.pmsh_config.AppConfig.get_from_topic', MagicMock(return_value='wrong_return'))
@patch('mod.logger.error')
- @patch('mod.subscription.Subscription.get')
- def test_poll_policy_topic_exception(self, mock_get_sub, mock_logger):
- self.mock_policy_mr_sub.get_from_topic.return_value = 'wrong_return'
- mock_get_sub.return_value = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B',
- operational_policy_name='policy-name',
- control_loop_name='control-loop-name',
- status=AdministrativeState.UNLOCKED.value)
+ def test_poll_policy_topic_exception(self, mock_logger):
self.policy_response_handler.poll_policy_topic()
mock_logger.assert_called()
diff --git a/components/pm-subscription-handler/tests/test_subscription_handler.py b/components/pm-subscription-handler/tests/test_subscription_handler.py
index fe338327..1843eb44 100644
--- a/components/pm-subscription-handler/tests/test_subscription_handler.py
+++ b/components/pm-subscription-handler/tests/test_subscription_handler.py
@@ -61,8 +61,6 @@ class SubscriptionHandlerTest(BaseClassSetup):
mock_logger.assert_called_with('Administrative State did not change '
'in the app config: UNLOCKED')
- @patch('mod.subscription_handler.SubscriptionHandler._start_aai_event_thread',
- MagicMock())
@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')
@@ -91,7 +89,6 @@ class SubscriptionHandlerTest(BaseClassSetup):
sub_handler.execute()
mock_deactivate_sub.assert_called_with(self.nfs, self.mock_mr_pub)
- @patch('mod.subscription_handler.SubscriptionHandler._start_aai_event_thread', MagicMock())
@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')
diff --git a/components/pm-subscription-handler/tox.ini b/components/pm-subscription-handler/tox.ini
index 6f0cb630..38acbbb8 100644
--- a/components/pm-subscription-handler/tox.ini
+++ b/components/pm-subscription-handler/tox.ini
@@ -31,7 +31,7 @@ deps=
setenv =
PYTHONPATH={toxinidir}/pmsh_service:{toxinidir}/pmsh_service/mod:{toxinidir}/tests
commands=
- pytest --junitxml xunit-results.xml --cov pmsh_service --cov-report xml --cov-report term \
+ pytest --junitxml xunit-results.xml --cov pmsh_service --cov-report xml --cov-report term-missing \
tests --verbose --cov-fail-under=70
[testenv:flake8]
diff --git a/components/slice-analysis-ms/ChangeLog.md b/components/slice-analysis-ms/ChangeLog.md
index 5d64d124..8d8a60d6 100644
--- a/components/slice-analysis-ms/ChangeLog.md
+++ b/components/slice-analysis-ms/ChangeLog.md
@@ -4,8 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
-## [1.0.6] - 2021/08/28
- - [DCAEGEN2-2885](https://jira.onap.org/browse/DCAEGEN2-2885) - DCAE SliceAnalysis MS - CPS Integration
+## [1.0.7] - 2021/12/16
+ - [DCAEGEN2-2963](https://jira.onap.org/browse/DCAEGEN2-2963) - Use onap/integration-java11 image
+
+ - [DCAEGEN2-2966](https://jira.onap.org/browse/DCAEGEN2-2966) - Switch CBS client library to 1.8.7
- - [DCAEGEN2-2811](https://jira.onap.org/browse/DCAEGEN2-2811) - Remove security vulnerabilities
+ - [DCAEGEN2-3025](https://jira.onap.org/browse/DCAEGEN2-3025) - Fix null pointer exception while fetching slice-config
+
+## [1.0.6] - 2021/08/28
+ - [DCAEGEN2-2885](https://jira.onap.org/browse/DCAEGEN2-2885) - DCAE SliceAnalysis MS - CPS Integration
+ - [DCAEGEN2-2811](https://jira.onap.org/browse/DCAEGEN2-2811) - Remove security vulnerabilities
diff --git a/components/slice-analysis-ms/entry.sh b/components/slice-analysis-ms/entry.sh
index 2859fe93..83225b94 100644
--- a/components/slice-analysis-ms/entry.sh
+++ b/components/slice-analysis-ms/entry.sh
@@ -1,3 +1,3 @@
-#!/bin/bash
+#!/bin/sh
export trustpass=`cat /opt/app/sliceanalysisms/etc/cert/trust.pass`
-java -Djavax.net.ssl.trustStore=/opt/app/sliceanalysisms/etc/cert/trust.jks -Djavax.net.ssl.trustStorePassword=$trustpass -jar /bin/application.jar \ No newline at end of file
+java -Djavax.net.ssl.trustStore=/opt/app/sliceanalysisms/etc/cert/trust.jks -Djavax.net.ssl.trustStorePassword="$trustpass" -jar /bin/application.jar
diff --git a/components/slice-analysis-ms/pom.xml b/components/slice-analysis-ms/pom.xml
index 23fab21e..faf60322 100644
--- a/components/slice-analysis-ms/pom.xml
+++ b/components/slice-analysis-ms/pom.xml
@@ -4,8 +4,8 @@
* ============LICENSE_START=======================================================
* slice-analysis-ms
* ================================================================================
- * Copyright (C) 2020-2021 Wipro Limited.
- * ==============================================================================
+ * Copyright (C) 2020-2021 Wipro Limited.
+ * ================================================================================
* 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
@@ -20,39 +20,41 @@
* ============LICENSE_END=========================================================
*
*******************************************************************************/
- -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.oparent</groupId>
- <artifactId>oparent</artifactId>
- <version>2.0.0</version>
- </parent>
- <groupId>org.onap.dcaegen2.services.components</groupId>
- <artifactId>slice-analysis-ms</artifactId>
- <version>1.0.6-SNAPSHOT</version>
- <name>dcaegen2-services-slice-analysis-ms</name>
- <description>Network slice PM analyser</description>
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>2.0.0</version>
+ </parent>
+ <groupId>org.onap.dcaegen2.services.components</groupId>
+ <artifactId>slice-analysis-ms</artifactId>
+ <version>1.0.7-SNAPSHOT</version>
+ <name>dcaegen2-services-slice-analysis-ms</name>
+ <description>Network slice PM analyser</description>
<packaging>jar</packaging>
- <properties>
- <java.version>11</java.version>
- <sdk.version>1.1.4</sdk.version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <maven.compiler.source>11</maven.compiler.source>
- <maven.compiler.target>11</maven.compiler.target>
- <docker.image.name>onap/${project.groupId}.${project.artifactId}</docker.image.name>
- <!-- NEXUS RELATED SETTINGS -->
- <nexusproxy>https://nexus.onap.org</nexusproxy>
- <snapshots.path>content/repositories/snapshots/</snapshots.path>
- <releases.path>content/repositories/releases/</releases.path>
- <site.path>content/sites/site/org/onap/dcaegen2/services/${project.artifactId}/${project.version}</site.path>
- <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
- <sonar.coverage.jacoco.xmlReportPaths>
- ${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml
- </sonar.coverage.jacoco.xmlReportPaths>
- </properties>
- <dependencies>
+ <properties>
+ <java.version>11</java.version>
+ <sdk.version>1.8.7</sdk.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <docker.image.name>onap/${project.groupId}.${project.artifactId}</docker.image.name>
+ <!-- NEXUS RELATED SETTINGS -->
+ <nexusproxy>https://nexus.onap.org</nexusproxy>
+ <snapshots.path>content/repositories/snapshots/</snapshots.path>
+ <releases.path>content/repositories/releases/</releases.path>
+ <site.path>content/sites/site/org/onap/dcaegen2/services/${project.artifactId}/${project.version}</site.path>
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
+ <sonar.coverage.jacoco.xmlReportPaths>
+ ${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml
+ </sonar.coverage.jacoco.xmlReportPaths>
+ </properties>
+ <dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-util -->
<dependency>
<groupId>org.apache.tomcat</groupId>
@@ -66,30 +68,30 @@
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>5.3.7</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>5.3.7</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-beans</artifactId>
- <version>5.3.7</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-expression</artifactId>
- <version>5.3.7</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>5.3.7</version>
- </dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>5.3.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>5.3.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>5.3.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-expression</artifactId>
+ <version>5.3.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>5.3.7</version>
+ </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
@@ -100,234 +102,227 @@
<artifactId>spring-data-commons</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
- <!-- cbs client -->
- <dependency>
- <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
- <artifactId>cbs-client</artifactId>
- <version>${sdk.version}</version>
- </dependency>
- <dependency>
- <groupId>org.onap.dcaegen2.services.sdk.security.crypt</groupId>
- <artifactId>crypt-password</artifactId>
- <version>${sdk.version}</version>
- </dependency>
- <dependency>
- <!-- Import dependency management from Spring Boot -->
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-dependencies</artifactId>
- <version>2.1.3.RELEASE</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>com.att.nsa</groupId>
- <artifactId>cambriaClient</artifactId>
- <version>0.0.1</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.11.0</version>
- </dependency>
- <dependency>
- <groupId>net.javacrumbs.json-unit</groupId>
- <artifactId>json-unit-assertj</artifactId>
- <version>2.14.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.11.0</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/javax.json/javax.json-api -->
- <dependency>
- <groupId>javax.json</groupId>
- <artifactId>javax.json-api</artifactId>
- <version>1.1.2</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- <version>2.1.3.RELEASE</version>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.postgresql</groupId>
- <artifactId>postgresql</artifactId>
- <version>42.2.13</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- <version>2.1.3.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate.javax.persistence</groupId>
- <artifactId>hibernate-jpa-2.0-api</artifactId>
- <version>1.0.1.Final</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <version>2.1.3.RELEASE</version>
- <scope>test</scope>
- <!-- exclusions> <exclusion> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId>
- </exclusion> </exclusions -->
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>2.21.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.openpojo</groupId>
- <artifactId>openpojo</artifactId>
- <version>0.8.10</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <scope>test</scope>
- </dependency>
+ <!-- cbs client -->
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>cbs-client</artifactId>
+ <version>${sdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.security.crypt</groupId>
+ <artifactId>crypt-password</artifactId>
+ <version>${sdk.version}</version>
+ </dependency>
+ <dependency>
+ <!-- Import dependency management from Spring Boot -->
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>2.1.3.RELEASE</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.nsa</groupId>
+ <artifactId>cambriaClient</artifactId>
+ <version>0.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.11.0</version>
+ </dependency>
+ <dependency>
+ <groupId>net.javacrumbs.json-unit</groupId>
+ <artifactId>json-unit-assertj</artifactId>
+ <version>2.14.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.11.0</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/javax.json/javax.json-api -->
+ <dependency>
+ <groupId>javax.json</groupId>
+ <artifactId>javax.json-api</artifactId>
+ <version>1.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <version>2.1.3.RELEASE</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>42.2.13</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ <version>2.1.3.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.0-api</artifactId>
+ <version>1.0.1.Final</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <version>2.1.3.RELEASE</version>
+ <scope>test</scope>
+ <!-- exclusions> <exclusion> <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artiifactId> </exclusion> </exclusions -->
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.21.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.openpojo</groupId>
+ <artifactId>openpojo</artifactId>
+ <version>0.8.10</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
<!-- https://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2 -->
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-api-mockito2</artifactId>
- <version>2.0.2</version>
- <exclusions>
- <exclusion>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.powermock/powermock-module-junit4 -->
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-junit4</artifactId>
- <version>2.0.2</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.functionaljava</groupId>
- <artifactId>functionaljava</artifactId>
- <version>3.0</version>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>4.5.13</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
- <dependency>
- <groupId>commons-beanutils</groupId>
- <artifactId>commons-beanutils</artifactId>
- <version>1.9.4</version>
- </dependency>
- <!-- mvnrepository.com/artifact/org.eclipse.jetty/jetty-server -->
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- <version>9.4.41.v20210516</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.webjars/bootstrap -->
- <dependency>
- <groupId>org.webjars</groupId>
- <artifactId>bootstrap</artifactId>
- <version>4.3.1</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
- <dependency>
- <groupId>javax.xml.bind</groupId>
- <artifactId>jaxb-api</artifactId>
- <version>2.3.0</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
- <dependency>
- <groupId>org.javassist</groupId>
- <artifactId>javassist</artifactId>
- <version>3.24.1-GA</version>
- </dependency>
- <dependency>
- <groupId>org.apache.tomcat.embed</groupId>
- <artifactId>tomcat-embed-core</artifactId>
- <version>9.0.46</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/nl.jqno.equalsverifier/equalsverifier -->
- <dependency>
- <groupId>nl.jqno.equalsverifier</groupId>
- <artifactId>equalsverifier</artifactId>
- <version>3.5.5</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <version>2.3.1.RELEASE</version>
- <executions>
- <execution>
- <goals>
- <goal>repackage</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>com.spotify</groupId>
- <artifactId>docker-maven-plugin</artifactId>
- <configuration>
- <serverId>${onap.nexus.dockerregistry.daily}</serverId>
- <imageName>${onap.nexus.dockerregistry.daily}/${docker.image.name}</imageName>
- <imageTags>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>2.0.2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/org.powermock/powermock-module-junit4 -->
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>2.0.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.functionaljava</groupId>
+ <artifactId>functionaljava</artifactId>
+ <version>3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.13</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
+ <dependency>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ <version>1.9.4</version>
+ </dependency>
+ <!-- mvnrepository.com/artifact/org.eclipse.jetty/jetty-server -->
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>9.4.41.v20210516</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/org.webjars/bootstrap -->
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>bootstrap</artifactId>
+ <version>4.3.1</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.3.0</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>3.24.1-GA</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-core</artifactId>
+ <version>9.0.46</version>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/nl.jqno.equalsverifier/equalsverifier -->
+ <dependency>
+ <groupId>nl.jqno.equalsverifier</groupId>
+ <artifactId>equalsverifier</artifactId>
+ <version>3.5.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>2.3.1.RELEASE</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.spotify</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <configuration>
+ <serverId>${onap.nexus.dockerregistry.daily}</serverId>
+ <imageName>${onap.nexus.dockerregistry.daily}/${docker.image.name}</imageName>
+ <imageTags>
<imageTag>${project.version}-${maven.build.timestamp}Z</imageTag>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
- </imageTags>
- <baseImage>openjdk:11.0.6-jre-slim</baseImage>
- <user>sliceanalysis</user>
- <resources>
- <resource>
- <targetPath>/bin</targetPath>
- <directory>${project.build.directory}</directory>
- <include>${project.artifactId}-${project.version}.jar</include>
- </resource>
- <resource>
- <targetPath>/bin</targetPath>
- <directory>${project.basedir}</directory>
- <include>entry.sh</include>
- </resource>
- </resources>
- <runs>
- <!-- Maven is loosing file permissions during artifacts copy -->
- <run>adduser --disabled-password sliceanalysis </run>
- <run>mv /bin/*.jar /bin/application.jar</run>
- <run>chmod -R 777 /bin</run>
- <run>chmod +x /bin/entry.sh</run>
- </runs>
- <exposes>
- <expose>8080</expose>
- </exposes>
- <entryPoint>./bin/entry.sh</entryPoint>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ </imageTags>
+ <baseImage>nexus3.onap.org:10001/onap/integration-java11:10.0.0</baseImage>
+ <user>sliceanalysis></user>
+ <dockerDirectory>${project.basedir}/src/main/docker/dockerfile</dockerDirectory>
+ <buildArgs>
+ <JAR_FILE>${project.artifactId}-${project.version}.jar</JAR_FILE>
+ </buildArgs>
+ <resources>
+ <resource>
+ <targetPath>/bin</targetPath>
+ <directory>${project.build.directory}</directory>
+ <include>${project.artifactId}-${project.version}.jar</include>
+ </resource>
+ <resource>
+ <targetPath>/bin</targetPath>
+ <directory>${project.basedir}</directory>
+ <include>entry.sh</include>
+ </resource>
+ </resources>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/components/slice-analysis-ms/src/main/docker/dockerfile/Dockerfile b/components/slice-analysis-ms/src/main/docker/dockerfile/Dockerfile
new file mode 100644
index 00000000..fa87897c
--- /dev/null
+++ b/components/slice-analysis-ms/src/main/docker/dockerfile/Dockerfile
@@ -0,0 +1,29 @@
+# ============LICENSE_START===================================================
+# Copyright (C) 2021 Wipro Limited
+# ============================================================================
+# 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 nexus3.onap.org:10001/onap/integration-java11:10.0.0
+ADD /bin/${JAR_FILE} /bin/
+ADD /bin/entry.sh /bin/
+USER root
+RUN adduser sliceanalysis --disabled-password sliceanalysis
+RUN mv /bin/*.jar /bin/application.jar
+RUN chmod -R 777 /bin
+RUN chmod +x /bin/entry.sh
+USER sliceanalysis
+EXPOSE 8080
+ENTRYPOINT /bin/entry.sh
diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java
index 5798a40f..50a60ac3 100644
--- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java
+++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* slice-analysis-ms
* ================================================================================
- * Copyright (C) 2020 Wipro Limited.
+ * Copyright (C) 2020-2021 Wipro Limited.
* ==============================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import org.onap.slice.analysis.ms.models.Configuration;
import org.onap.slice.analysis.ms.models.configdb.CellsModel;
@@ -35,82 +36,97 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
/**
- *
+ *
* Service for config db interfaces
*
*/
@Service
public class ConfigDbInterfaceService implements IConfigDbService {
- @Autowired
- private ConfigDbRestClient restclient;
- private String configDbBaseUrl = Configuration.getInstance().getConfigDbService();
+ @Autowired
+ private ConfigDbRestClient restclient;
+ private String configDbBaseUrl = Configuration.getInstance().getConfigDbService();
+
+ /**
+ * Fetches the current configuration of an S-NSSAI from config DB
+ */
+ public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai){
+ Map<String,Integer> responseMap = null;
+ String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/profile-config/"+snssai;
- /**
- * Fetches the current configuration of an S-NSSAI from config DB
- */
- public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai){
- Map<String,Integer> responseMap = null;
- String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/profile-config/"+snssai;
+ ResponseEntity<Map<String,Integer>> response=restclient.sendGetRequest(reqUrl,new ParameterizedTypeReference<Map<String, Integer>>() {
+ });
+ responseMap=response.getBody();
+ return responseMap;
+ }
- ResponseEntity<Map<String,Integer>> response=restclient.sendGetRequest(reqUrl,new ParameterizedTypeReference<Map<String, Integer>>() {
- });
- responseMap=response.getBody();
- return responseMap;
- }
+ /**
+ * Fetches the current configuration of RIC from config DB
+ */
+ public Map<String, Map<String, Object>> fetchCurrentConfigurationOfRIC(String snssai) {
+ String reqUrl = configDbBaseUrl + "/api/sdnc-config-db/v4/slice-config/" + snssai;
+ Map<String, Map<String, Object>> responseMap = new HashMap<String, Map<String, Object>>();
+ ResponseEntity<Map<String, List<Map<String, Object>>>> response = restclient.sendGetRequest(reqUrl,
+ new ParameterizedTypeReference<Map<String, List<Map<String, Object>>>>() {
+ });
+ if (Objects.nonNull(response)) {
+ for (Map.Entry<String, List<Map<String, Object>>> entry : response.getBody().entrySet()) {
+ List<Map<String, Object>> list = entry.getValue();
+ if (!list.isEmpty()) {
+ list.forEach(l -> {
+ if (l.containsKey("nearRTRICId")) {
+ responseMap.put(String.valueOf(l.get("nearRTRICId")), l);
+ }
+ });
+ }
- /**
- * Fetches the current configuration of RIC from config DB
- */
- public Map<String,Map<String,Object>> fetchCurrentConfigurationOfRIC(String snssai){
- String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/slice-config/"+snssai;
- ResponseEntity<Map<String,Map<String,Object>>> response=restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<Map<String,Map<String,Object>>>() {
- });
- return response.getBody();
- }
+ }
+ }
+ return responseMap;
+ }
- /**
- * Fetches all the network functions of an S-NSSAI from config DB
- */
- public List<String> fetchNetworkFunctionsOfSnssai(String snssai){
- List<String> responseList=new ArrayList<>();
- String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/du-list/"+snssai;
- ResponseEntity<List<NetworkFunctionModel>> response=restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<List<NetworkFunctionModel>>() {
- });
- for(NetworkFunctionModel networkFn:response.getBody()) {
- responseList.add(networkFn.getgNBDUId());
- }
- return responseList;
- }
+ /**
+ * Fetches all the network functions of an S-NSSAI from config DB
+ */
+ public List<String> fetchNetworkFunctionsOfSnssai(String snssai){
+ List<String> responseList=new ArrayList<>();
+ String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/du-list/"+snssai;
+ ResponseEntity<List<NetworkFunctionModel>> response=restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<List<NetworkFunctionModel>>() {
+ });
+ for(NetworkFunctionModel networkFn:response.getBody()) {
+ responseList.add(networkFn.getgNBDUId());
+ }
+ return responseList;
+ }
- /**
- * Fetches the RICS of an S-NSSAI from config DB
- */
- public Map<String, List<String>> fetchRICsOfSnssai(String snssai){
- Map<String,List<String>> responseMap=new HashMap<>();
- String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/du-cell-list/"+snssai;
- ResponseEntity<Map<String,List<CellsModel>>> response = restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<Map<String,List<CellsModel>>>() {
- });
+ /**
+ * Fetches the RICS of an S-NSSAI from config DB
+ */
+ public Map<String, List<String>> fetchRICsOfSnssai(String snssai){
+ Map<String,List<String>> responseMap=new HashMap<>();
+ String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/du-cell-list/"+snssai;
+ ResponseEntity<Map<String,List<CellsModel>>> response = restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<Map<String,List<CellsModel>>>() {
+ });
- for (Map.Entry<String, List<CellsModel>> entry : response.getBody().entrySet()) {
- List<String> cellslist=new ArrayList<>();
- for(CellsModel cellmodel:entry.getValue()) {
- cellslist.add(cellmodel.getCellLocalId());
- }
- responseMap.put(entry.getKey(), cellslist);
- }
- return responseMap;
- }
+ for (Map.Entry<String, List<CellsModel>> entry : response.getBody().entrySet()) {
+ List<String> cellslist=new ArrayList<>();
+ for(CellsModel cellmodel:entry.getValue()) {
+ cellslist.add(cellmodel.getCellLocalId());
+ }
+ responseMap.put(entry.getKey(), cellslist);
+ }
+ return responseMap;
+ }
- /**
- * Fetches the details of a service
- */
- public Map<String,String> fetchServiceDetails(String snssai){
- String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/subscriber-details/"+snssai;
- ResponseEntity<Map<String,String>> response=restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<Map<String,String>>() {
- });
- return response.getBody();
- }
+ /**
+ * Fetches the details of a service
+ */
+ public Map<String,String> fetchServiceDetails(String snssai){
+ String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/subscriber-details/"+snssai;
+ ResponseEntity<Map<String,String>> response=restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<Map<String,String>>() {
+ });
+ return response.getBody();
+ }
}
diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java
index 01fa91d0..fbb47e32 100644
--- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java
+++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* slice-analysis-ms
* ================================================================================
- * Copyright (C) 2020 Wipro Limited.
+ * Copyright (C) 2020-2021 Wipro Limited.
* ==============================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,8 @@ import java.util.Map;
import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClientFactory;
import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsRequests;
import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsRequest;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties;
+import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.model.logging.ImmutableRequestDiagnosticContext;
import org.onap.dcaegen2.services.sdk.rest.services.model.logging.RequestDiagnosticContext;
import org.onap.slice.analysis.ms.models.ConfigPolicy;
import org.onap.slice.analysis.ms.models.Configuration;
@@ -69,8 +70,9 @@ public class ConfigFetchFromCbs implements Runnable {
log.info("getAppconfig start ..");
RequestDiagnosticContext diagnosticContext = RequestDiagnosticContext.create();
// Read necessary properties from the environment
- final EnvProperties env = EnvProperties.fromEnvironment();
- log.debug("environments {}", env);
+ final CbsClientConfiguration cbsClientConfiguration = CbsClientConfiguration.fromEnvironment();
+
+ log.debug("environments {}", cbsClientConfiguration);
ConfigPolicy configPolicy = ConfigPolicy.getInstance();
// Polling properties
@@ -79,7 +81,7 @@ public class ConfigFetchFromCbs implements Runnable {
// Create the client and use it to get the configuration
final CbsRequest request = CbsRequests.getAll(diagnosticContext);
- return CbsClientFactory.createCbsClient(env)
+ return CbsClientFactory.createCbsClient(cbsClientConfiguration)
.flatMapMany(cbsClient -> cbsClient.updates(request, initialDelay, period)).subscribe(jsonObject -> {
log.info("configuration and policy from CBS {}", jsonObject);
JsonObject config = jsonObject.getAsJsonObject("config");
diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java
index ccb34edb..d802f81d 100644
--- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java
+++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java
@@ -48,181 +48,201 @@ import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class SnssaiSamplesProcessor {
- private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class);
-
- @Autowired
- private PolicyService policyService;
-
- @Autowired
- private IConfigDbService configDbService;
-
- @Autowired
- private PmDataQueue pmDataQueue;
-
- @Autowired
- private AverageCalculator averageCalculator;
-
- @Autowired
- private AaiInterface aaiInterface;
-
- @Autowired
- private CpsInterface cpsInterface;
-
- private List<MeasurementObject> snssaiMeasurementList = new ArrayList<>();
- private Map<String, List<String>> ricToCellMapping = new HashMap<>();
- private Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>();
- private Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>();
- private int noOfSamples;
- private List<String> pmsToCompute;
- private Map<String, String> prbThroughputMapping = new HashMap<>();
- private int minPercentageChange;
-
- @PostConstruct
- public void init() {
- Configuration configuration = Configuration.getInstance();
- noOfSamples = configuration.getSamples();
- pmsToCompute = new ArrayList<>();
- pmsToCompute.add("PrbUsedDl");
- pmsToCompute.add("PrbUsedUl");
- prbThroughputMapping = new HashMap<>();
- prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice");
- prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice");
- minPercentageChange = configuration.getMinPercentageChange();
- }
-
- /**
- * process the measurement data of an S-NSSAI
- */
- public boolean processSamplesOfSnnsai(String snssai, List<String> networkFunctions) {
- Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true
- : Configuration.getInstance().getConfigDbEnabled();
- List<MeasurementObject> sample = null;
- List<List<MeasurementObject>> samples = null;
- Map<String, String> serviceDetails =null;
- log.info("Network Functions {} of snssai {}", networkFunctions, snssai);
- for (String nf : networkFunctions) {
- log.debug("Average of samples for {}:", snssai);
- samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples);
- if (samples != null) {
- sample = averageCalculator.findAverageOfSamples(samples);
- addToMeasurementList(sample);
- } else {
- log.info("Not enough samples present for nf {}", nf);
- return false;
- }
- }
- log.info("snssai measurement list {}", snssaiMeasurementList);
- Map<String, Map<String, Object>> ricConfiguration;
- Map<String, Integer> sliceConfiguration;
- if (isConfigDbEnabled) {
- ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai);
- ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai);
- sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai);
- serviceDetails = configDbService.fetchServiceDetails(snssai);
- } else {
- ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai);
- ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai);
- sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai);
- serviceDetails = aaiInterface.fetchServiceDetails(snssai);
- }
- log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping);
- log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration);
- pmsToCompute.forEach(pm -> {
- log.debug("processing for pm {}", pm);
- sumOfPrbsAcrossCells(pm);
- int sum = computeSum(pm);
- computeThroughput(sliceConfiguration, sum, pm);
- calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm));
- });
- updateConfiguration();
- if (ricToThroughputMapping.size() > 0) {
- AdditionalProperties<Map<String, Map<String, Integer>>> addProps = new AdditionalProperties<>();
- addProps.setResourceConfig(ricToThroughputMapping);
- policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails);
- }
- return true;
- }
-
- /**
- * process the measurement data of an S-NSSAI
- */
- protected void updateConfiguration() {
- Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
- Map.Entry<String, Map<String, Integer>> entry = null;
- while (it.hasNext()) {
- entry = it.next();
- if (entry.getValue().size() == 0) {
- it.remove();
- }
- }
- }
-
- private void addToMeasurementList(List<MeasurementObject> sample) {
- snssaiMeasurementList.addAll(sample);
- }
-
- /**
- * Calculate the change in the configuration value and keep the configuration
- * only if it is greater than a specific limit
- */
- protected void calculatePercentageChange(Map<String, Map<String, Object>> ricConfiguration, String pm) {
- Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
- Map.Entry<String, Map<String, Integer>> entry = null;
- float existing = 0;
- float change = 0;
- while (it.hasNext()) {
- entry = it.next();
- existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm));
- change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100;
- if (change <= minPercentageChange) {
- ricToThroughputMapping.get(entry.getKey()).remove(pm);
- log.info("Removing pm data {} for RIC {}", pm, entry.getKey());
- }
- }
- }
-
- protected void sumOfPrbsAcrossCells(String pmName) {
- ricToCellMapping.forEach((ric, cells) -> {
- int sumOfPrbs = 0;
- for (String cell : cells) {
- int index = MeasurementObject.findIndex(cell, snssaiMeasurementList);
- sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName);
- }
- if (ricToPrbsMapping.containsKey(ric)) {
- ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs);
- } else {
- Map<String, Integer> pmToPrbMapping = new HashMap<>();
- pmToPrbMapping.put(pmName, sumOfPrbs);
- ricToPrbsMapping.put(ric, pmToPrbMapping);
- }
- });
- log.info("PRBs sum computed for RIC {}", ricToPrbsMapping);
- }
-
- protected Integer computeSum(String pm) {
- return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum);
- }
-
- protected void computeThroughput(Map<String, Integer> sliceConfiguration, int sum, String pm) {
- Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToPrbsMapping.entrySet().iterator();
- Map.Entry<String, Map<String, Integer>> entry = null;
- Map<String, Integer> throughtputMap = null;
- String ric = "";
- int value = 0;
- while (it.hasNext()) {
- entry = it.next();
- ric = entry.getKey();
- value = Math.round(((float) entry.getValue().get(pm) / sum)
- * (float) sliceConfiguration.get(prbThroughputMapping.get(pm)));
- if (ricToThroughputMapping.containsKey(ric)) {
- ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value);
- } else {
- throughtputMap = new HashMap<>();
- throughtputMap.put(prbThroughputMapping.get(pm), value);
- ricToThroughputMapping.put(ric, throughtputMap);
- }
- }
- log.info("Throughput computed for RIC {}", ricToThroughputMapping);
- }
+ private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class);
+
+ @Autowired
+ private PolicyService policyService;
+
+ @Autowired
+ private IConfigDbService configDbService;
+
+ @Autowired
+ private PmDataQueue pmDataQueue;
+
+ @Autowired
+ private AverageCalculator averageCalculator;
+
+ @Autowired
+ private AaiInterface aaiInterface;
+
+ @Autowired
+ private CpsInterface cpsInterface;
+
+ private List<MeasurementObject> snssaiMeasurementList = new ArrayList<>();
+ private Map<String, List<String>> ricToCellMapping = new HashMap<>();
+ private Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>();
+ private Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>();
+ private int noOfSamples;
+ private List<String> pmsToCompute;
+ private Map<String, String> prbThroughputMapping = new HashMap<>();
+ private int minPercentageChange;
+
+ @PostConstruct
+ public void init() {
+ Configuration configuration = Configuration.getInstance();
+ noOfSamples = configuration.getSamples();
+ pmsToCompute = new ArrayList<>();
+ pmsToCompute.add("PrbUsedDl");
+ pmsToCompute.add("PrbUsedUl");
+ prbThroughputMapping = new HashMap<>();
+ prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice");
+ prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice");
+ minPercentageChange = configuration.getMinPercentageChange();
+ }
+
+ /**
+ * process the measurement data of an S-NSSAI
+ */
+ public boolean processSamplesOfSnnsai(String snssai, List<String> networkFunctions) {
+ Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true
+ : Configuration.getInstance().getConfigDbEnabled();
+ List<MeasurementObject> sample = null;
+ List<List<MeasurementObject>> samples = null;
+ Map<String, String> serviceDetails =null;
+ log.info("Network Functions {} of snssai {}", networkFunctions, snssai);
+ for (String nf : networkFunctions) {
+ log.debug("Average of samples for {}:", snssai);
+ samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples);
+ if (samples != null) {
+ sample = averageCalculator.findAverageOfSamples(samples);
+ addToMeasurementList(sample);
+ } else {
+ log.info("Not enough samples present for nf {}", nf);
+ return false;
+ }
+ }
+ log.info("snssai measurement list {}", snssaiMeasurementList);
+ Map<String, Map<String, Object>> ricConfiguration;
+ Map<String, Integer> sliceConfiguration;
+ if (isConfigDbEnabled) {
+ ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai);
+ ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai);
+ sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai);
+ serviceDetails = configDbService.fetchServiceDetails(snssai);
+ } else {
+ ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai);
+ ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai);
+ serviceDetails = aaiInterface.fetchServiceDetails(snssai);
+ sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai);
+ }
+ log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping);
+ log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration);
+ pmsToCompute.forEach(pm -> {
+ log.debug("processing for pm {}", pm);
+ sumOfPrbsAcrossCells(pm);
+ int sum = computeSum(pm);
+ computeThroughput(sliceConfiguration, sum, pm);
+ calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm));
+ });
+ updateConfiguration();
+ if (ricToThroughputMapping.size() > 0) {
+ AdditionalProperties<Map<String, List<Map<String, Integer>>>> addProps = new AdditionalProperties<>();
+ addProps.setResourceConfig(getChangedRIConfigFormat(ricToThroughputMapping));
+ policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails);
+ }
+ return true;
+ }
+
+ /**
+ * change the RICConfig data format to be compatible with SDN-R
+ */
+ protected Map<String, List<Map<String, Integer>>> getChangedRIConfigFormat(
+ Map<String, Map<String, Integer>> ricToThroughputMapping) {
+ Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
+ Map.Entry<String, Map<String, Integer>> entry = null;
+ List<Map<String, Integer>> ricConfigList = new ArrayList<>();
+ Map<String, List<Map<String, Integer>>> ricConfigData = new HashMap<>();
+ while (it.hasNext()) {
+ Map<String, Integer> newConfigMap = new HashMap<>();
+ entry = it.next();
+ newConfigMap = entry.getValue();
+ newConfigMap.put("nearRTRICId", Integer.parseInt(entry.getKey()));
+ ricConfigList.add(newConfigMap);
+ }
+ ricConfigData.put("data", ricConfigList);
+ return ricConfigData;
+ }
+
+ /**
+ * process the measurement data of an S-NSSAI
+ */
+ protected void updateConfiguration() {
+ Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
+ Map.Entry<String, Map<String, Integer>> entry = null;
+ while (it.hasNext()) {
+ entry = it.next();
+ if (entry.getValue().size() == 0) {
+ it.remove();
+ }
+ }
+ }
+
+ private void addToMeasurementList(List<MeasurementObject> sample) {
+ snssaiMeasurementList.addAll(sample);
+ }
+
+ /**
+ * Calculate the change in the configuration value and keep the configuration
+ * only if it is greater than a specific limit
+ */
+ protected void calculatePercentageChange(Map<String, Map<String, Object>> ricConfiguration, String pm) {
+ Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator();
+ Map.Entry<String, Map<String, Integer>> entry = null;
+ float existing = 0;
+ float change = 0;
+ while (it.hasNext()) {
+ entry = it.next();
+ existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm));
+ change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100;
+ if (change <= minPercentageChange) {
+ ricToThroughputMapping.get(entry.getKey()).remove(pm);
+ log.info("Removing pm data {} for RIC {}", pm, entry.getKey());
+ }
+ }
+ }
+
+ protected void sumOfPrbsAcrossCells(String pmName) {
+ ricToCellMapping.forEach((ric, cells) -> {
+ int sumOfPrbs = 0;
+ for (String cell : cells) {
+ int index = MeasurementObject.findIndex(cell, snssaiMeasurementList);
+ sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName);
+ }
+ if (ricToPrbsMapping.containsKey(ric)) {
+ ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs);
+ } else {
+ Map<String, Integer> pmToPrbMapping = new HashMap<>();
+ pmToPrbMapping.put(pmName, sumOfPrbs);
+ ricToPrbsMapping.put(ric, pmToPrbMapping);
+ }
+ });
+ log.info("PRBs sum computed for RIC {}", ricToPrbsMapping);
+ }
+
+ protected Integer computeSum(String pm) {
+ return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum);
+ }
+
+ protected void computeThroughput(Map<String, Integer> sliceConfiguration, int sum, String pm) {
+ Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToPrbsMapping.entrySet().iterator();
+ Map.Entry<String, Map<String, Integer>> entry = null;
+ Map<String, Integer> throughtputMap = null;
+ String ric = "";
+ int value = 0;
+ while (it.hasNext()) {
+ entry = it.next();
+ ric = entry.getKey();
+ value = Math.round(((float) entry.getValue().get(pm) / sum)
+ * (float) sliceConfiguration.get(prbThroughputMapping.get(pm)));
+ if (ricToThroughputMapping.containsKey(ric)) {
+ ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value);
+ } else {
+ throughtputMap = new HashMap<>();
+ throughtputMap.put(prbThroughputMapping.get(pm), value);
+ ricToThroughputMapping.put(ric, throughtputMap);
+ }
+ }
+ log.info("Throughput computed for RIC {}", ricToThroughputMapping);
+ }
}
diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java
index 3cb0a3b7..885a9171 100644
--- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java
+++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java
@@ -41,89 +41,100 @@ import org.springframework.http.ResponseEntity;
@RunWith(org.mockito.junit.MockitoJUnitRunner.class)
public class ConfigDbInterfaceServiceTest {
- @InjectMocks
- ConfigDbInterfaceService configdbservice;
-
- @Mock
- ConfigDbRestClient restclient;
-
- @Test
- public void fetchCurrentConfigurationOfSlice() {
-
- Map<String, Integer> responsemap=new HashMap<>();
- responsemap.put("dLThptPerSlice", 1);
- responsemap.put("uLThptPerSlice", 2);
- Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<Object>(responsemap, HttpStatus.OK));
- assertEquals(responsemap, configdbservice.fetchCurrentConfigurationOfSlice("snssai"));
- }
-
- @Test
- public void fetchCurrentConfigurationOfRIC() {
- Map<String,Integer> map=new HashMap<>();
- Map<String, Map<String,Integer>> responsemap=new HashMap<>();
- map.put("dLThptPerSlice", 45);
- map.put("uLThptPerSlice", 50);
- responsemap.put("1", map);
-
- Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<Object>(responsemap, HttpStatus.OK));
- assertEquals(responsemap, configdbservice.fetchCurrentConfigurationOfRIC("snssai"));
-
- }
- @Test
- public void fetchRICsOfSnssai() {
- Map<String, List<CellsModel>> response=new HashMap<>();
- List<CellsModel> cellslist=new ArrayList<>();
- List<CellsModel> cellslist1=new ArrayList<>();
- CellsModel cellsmodel1=new CellsModel();
- cellsmodel1.setCellLocalId("1111");
- CellsModel cellsmodel2=new CellsModel();
- cellsmodel2.setCellLocalId("2222");
- cellslist.add(cellsmodel1);
- cellslist.add(cellsmodel2);
- response.put("1", cellslist);
- CellsModel cellsmodel3=new CellsModel();
- cellsmodel3.setCellLocalId("3333");
- CellsModel cellsmodel4=new CellsModel();
- cellsmodel4.setCellLocalId("4444");
- cellslist1.add(cellsmodel3);
- cellslist1.add(cellsmodel4);
- response.put("2", cellslist1);
- Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<Object>(response, HttpStatus.OK));
- List<String> outputlist=new ArrayList<>();
- outputlist.add("1111");
- outputlist.add("2222");
- Map<String,List<String>> output= configdbservice.fetchRICsOfSnssai("snssai");
- assertEquals(outputlist, output.get("1"));
-
- }
-
- @Test
- public void fetchNetworkFunctionsOfSnssai() {
-
- List<String> responsemap=new ArrayList<>();
- List<NetworkFunctionModel> networkfunctionslist=new ArrayList<NetworkFunctionModel>();
- NetworkFunctionModel nf1=new NetworkFunctionModel();
- nf1.setgNBDUId("1111");
- NetworkFunctionModel nf2=new NetworkFunctionModel();
- nf2.setgNBDUId("2222");
- NetworkFunctionModel nf3=new NetworkFunctionModel();
- nf3.setgNBDUId("3333");
- networkfunctionslist.add(nf1);
- networkfunctionslist.add(nf2);
- networkfunctionslist.add(nf3);
- Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<Object>(networkfunctionslist, HttpStatus.OK));
- responsemap=configdbservice.fetchNetworkFunctionsOfSnssai("snssai");
- assertEquals(3, responsemap.size());
-
- }
- public void fetchServiceProfile() {
- Map<String,String> responseMap=new HashMap<String, String>();
- responseMap.put("sNSSAI", "001-010");
- responseMap.put("ranNFNSSIId","1111");
- responseMap.put("sliceProfileId","2222");
- responseMap.put("globalSubscriberId","110-345");
- Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<Object>(responseMap, HttpStatus.OK));
- assertEquals(responseMap, configdbservice.fetchServiceDetails("snssai"));
- }
+ @InjectMocks
+ ConfigDbInterfaceService configdbservice;
+
+ @Mock
+ ConfigDbRestClient restclient;
+
+ @Test
+ public void fetchCurrentConfigurationOfSlice() {
+
+ Map<String, Integer> responsemap=new HashMap<>();
+ responsemap.put("dLThptPerSlice", 1);
+ responsemap.put("uLThptPerSlice", 2);
+ Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any()))
+ .thenReturn(new ResponseEntity<Object>(responsemap, HttpStatus.OK));
+ assertEquals(responsemap, configdbservice.fetchCurrentConfigurationOfSlice("snssai"));
+ }
+
+ @Test
+ public void fetchCurrentConfigurationOfRIC() {
+ Map<String,Integer> map=new HashMap<>();
+ Map<String, Map<String,Integer>> responsemap=new HashMap<>();
+ Map<String, List<Map<String,Integer>>> result =new HashMap<String, List<Map<String,Integer>>>();
+ map.put("dLThptPerSlice", 45);
+ map.put("uLThptPerSlice", 60);
+ map.put("nearRTRICId",1);
+ responsemap.put("1", map);
+ List<Map<String,Integer>> list = new ArrayList<Map<String,Integer>>();
+ list.add(map);
+ result.put("data",list);
+ Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any()))
+ .thenReturn(new ResponseEntity<Object>(result, HttpStatus.OK));
+ assertEquals(responsemap, configdbservice.fetchCurrentConfigurationOfRIC("snssai"));
+
+ }
+
+ @Test
+ public void fetchRICsOfSnssai() {
+ Map<String, List<CellsModel>> response=new HashMap<>();
+ List<CellsModel> cellslist=new ArrayList<>();
+ List<CellsModel> cellslist1=new ArrayList<>();
+ CellsModel cellsmodel1=new CellsModel();
+ cellsmodel1.setCellLocalId("1111");
+ CellsModel cellsmodel2=new CellsModel();
+ cellsmodel2.setCellLocalId("2222");
+ cellslist.add(cellsmodel1);
+ cellslist.add(cellsmodel2);
+ response.put("1", cellslist);
+ CellsModel cellsmodel3=new CellsModel();
+ cellsmodel3.setCellLocalId("3333");
+ CellsModel cellsmodel4=new CellsModel();
+ cellsmodel4.setCellLocalId("4444");
+ cellslist1.add(cellsmodel3);
+ cellslist1.add(cellsmodel4);
+ response.put("2", cellslist1);
+ Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any()))
+ .thenReturn(new ResponseEntity<Object>(response, HttpStatus.OK));
+ List<String> outputlist=new ArrayList<>();
+ outputlist.add("1111");
+ outputlist.add("2222");
+ Map<String,List<String>> output= configdbservice.fetchRICsOfSnssai("snssai");
+ assertEquals(outputlist, output.get("1"));
+
+ }
+
+ @Test
+ public void fetchNetworkFunctionsOfSnssai() {
+
+ List<String> responsemap=new ArrayList<>();
+ List<NetworkFunctionModel> networkfunctionslist=new ArrayList<NetworkFunctionModel>();
+ NetworkFunctionModel nf1=new NetworkFunctionModel();
+ nf1.setgNBDUId("1111");
+ NetworkFunctionModel nf2=new NetworkFunctionModel();
+ nf2.setgNBDUId("2222");
+ NetworkFunctionModel nf3=new NetworkFunctionModel();
+ nf3.setgNBDUId("3333");
+ networkfunctionslist.add(nf1);
+ networkfunctionslist.add(nf2);
+ networkfunctionslist.add(nf3);
+ Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any()))
+ .thenReturn(new ResponseEntity<Object>(networkfunctionslist, HttpStatus.OK));
+ responsemap=configdbservice.fetchNetworkFunctionsOfSnssai("snssai");
+ assertEquals(3, responsemap.size());
+
+ }
+
+ public void fetchServiceProfile() {
+ Map<String,String> responseMap=new HashMap<String, String>();
+ responseMap.put("sNSSAI", "001-010");
+ responseMap.put("ranNFNSSIId","1111");
+ responseMap.put("sliceProfileId","2222");
+ responseMap.put("globalSubscriberId","110-345");
+ Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any()))
+ .thenReturn(new ResponseEntity<Object>(responseMap, HttpStatus.OK));
+ assertEquals(responseMap, configdbservice.fetchServiceDetails("snssai"));
+ }
}
diff --git a/components/slice-analysis-ms/version.properties b/components/slice-analysis-ms/version.properties
index 2a687c49..4434ce3b 100644
--- a/components/slice-analysis-ms/version.properties
+++ b/components/slice-analysis-ms/version.properties
@@ -20,7 +20,7 @@
###############################################################################
major=1
minor=0
-patch=6
+patch=7
base_version=${major}.${minor}.${patch}
release_version=${base_version}
snapshot_version=${base_version}-SNAPSHOT