From 4b80d09d8c55c6361dcea126e267ae7207bdaac3 Mon Sep 17 00:00:00 2001 From: SagarS Date: Mon, 16 Aug 2021 16:55:10 +0100 Subject: Subscription API DB changes with IPV4, IPV6 updates Issue-ID: DCAEGEN2-2823 Change-Id: Ie455b1016ae1372934fa874667226ca9972b8d7f Signed-off-by: SagarS --- components/pm-subscription-handler/Changelog.md | 1 + .../pmsh_service/mod/aai_client.py | 3 +- .../pmsh_service/mod/aai_event_handler.py | 3 +- .../pmsh_service/mod/api/db_models.py | 136 +++++++++++++++++++-- .../pmsh_service/mod/network_function.py | 20 +-- .../pmsh_service/mod/subscription.py | 20 +-- components/pm-subscription-handler/pom.xml | 2 +- .../tests/data/pm_subscription_event.json | 2 +- .../tests/test_network_function.py | 8 +- .../tests/test_subscription.py | 21 +++- .../tests/test_subscription_handler.py | 6 +- 11 files changed, 186 insertions(+), 36 deletions(-) (limited to 'components/pm-subscription-handler') diff --git a/components/pm-subscription-handler/Changelog.md b/components/pm-subscription-handler/Changelog.md index 58d40cc9..bd5929cd 100755 --- a/components/pm-subscription-handler/Changelog.md +++ b/components/pm-subscription-handler/Changelog.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [1.3.2] ### Changed * Update to use version 2.2.1 of https://pypi.org/project/onap_dcae_cbs_docker_client/ +* Updated DB under Enhanced API for PMSH subscription management Feature (DCAEGEN2-2802) ## [1.3.1] ### Changed diff --git a/components/pm-subscription-handler/pmsh_service/mod/aai_client.py b/components/pm-subscription-handler/pmsh_service/mod/aai_client.py index fff91e7e..e53ea3a2 100755 --- a/components/pm-subscription-handler/pmsh_service/mod/aai_client.py +++ b/components/pm-subscription-handler/pmsh_service/mod/aai_client.py @@ -135,7 +135,8 @@ def _filter_nf_data(nf_data, app_conf): name_identifier = 'pnf-name' if nf['node-type'] == 'pnf' else 'vnf-name' new_nf = mod.network_function.NetworkFunction( nf_name=nf['properties'].get(name_identifier), - ip_address=nf['properties'].get('ipaddress-v4-oam'), + ipv4_address=nf['properties'].get('ipaddress-v4-oam'), + ipv6_address=nf['properties'].get('ipaddress-v6-oam'), model_invariant_id=nf['properties'].get('model-invariant-id'), model_version_id=nf['properties'].get('model-version-id')) if not new_nf.set_nf_model_params(app_conf): 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 46d52f12..6fc4ba90 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 @@ -63,7 +63,8 @@ def process_aai_events(mr_sub, mr_pub, app, app_conf): f'is not "Active"') continue nf = NetworkFunction(nf_name=xnf_name, - ip_address=aai_entity['ipaddress-v4-oam'], + 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): diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py b/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py index a9dd6efe..5c87fa55 100755 --- a/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py +++ b/components/pm-subscription-handler/pmsh_service/mod/api/db_models.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2020 Nordix Foundation. +# Copyright (C) 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. @@ -16,7 +16,7 @@ # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END===================================================== -from sqlalchemy import Column, Integer, String, ForeignKey +from sqlalchemy import Column, Integer, String, ForeignKey, JSON from sqlalchemy.orm import relationship from mod import db @@ -25,7 +25,7 @@ from mod import db class SubscriptionModel(db.Model): __tablename__ = 'subscriptions' id = Column(Integer, primary_key=True, autoincrement=True) - subscription_name = Column(String(100), unique=True) + subscription_name = Column(String(100), unique=True, nullable=False) status = Column(String(20)) nfs = relationship( @@ -33,6 +33,16 @@ class SubscriptionModel(db.Model): cascade='all, delete-orphan', backref='subscription') + network_filter = relationship( + 'NetworkFunctionFilterModel', + cascade='all, delete-orphan', + backref='subscription') + + measurement_groups = relationship( + 'MeasurementGroupModel', + cascade='all, delete-orphan', + backref='subscription') + def __init__(self, subscription_name, status): self.subscription_name = subscription_name self.status = status @@ -57,7 +67,8 @@ class NetworkFunctionModel(db.Model): __tablename__ = 'network_functions' id = Column(Integer, primary_key=True, autoincrement=True) nf_name = Column(String(100), unique=True) - ip_address = Column(String(50)) + ipv4_address = Column(String(50)) + ipv6_address = Column(String(50)) model_invariant_id = Column(String(100)) model_version_id = Column(String(100)) model_name = Column(String(100)) @@ -70,11 +81,12 @@ class NetworkFunctionModel(db.Model): cascade='all, delete-orphan', backref='nf') - def __init__(self, nf_name, ip_address, model_invariant_id, + def __init__(self, nf_name, ipv4_address, ipv6_address, model_invariant_id, model_version_id, model_name, sdnc_model_name, sdnc_model_version, retry_count=0): self.nf_name = nf_name - self.ip_address = ip_address + self.ipv4_address = ipv4_address + self.ipv6_address = ipv6_address self.model_invariant_id = model_invariant_id self.model_version_id = model_version_id self.model_name = model_name @@ -90,7 +102,8 @@ class NetworkFunctionModel(db.Model): return NetworkFunction(sdnc_model_name=self.sdnc_model_name, sdnc_model_version=self.sdnc_model_version, **{'nf_name': self.nf_name, - 'ip_address': self.ip_address, + 'ipv4_address': self.ipv4_address, + 'ipv6_address': self.ipv6_address, 'model_invariant_id': self.model_invariant_id, 'model_version_id': self.model_version_id}) @@ -129,10 +142,117 @@ class NfSubRelationalModel(db.Model): NetworkFunctionModel.nf_name == self.nf_name).one_or_none() db.session.remove() return {'nf_name': self.nf_name, - 'ip_address': nf.ip_address, + 'ipv4_address': nf.ipv4_address, + 'ipv6_address': nf.ipv6_address, 'nf_sub_status': self.nf_sub_status, 'model_invariant_id': nf.model_invariant_id, 'model_version_id': nf.model_version_id, 'model_name': nf.model_name, 'sdnc_model_name': nf.sdnc_model_name, 'sdnc_model_version': nf.sdnc_model_version} + + +class NetworkFunctionFilterModel(db.Model): + __tablename__ = 'nf_filter' + id = Column(Integer, primary_key=True, autoincrement=True) + subscription_name = Column( + String, + ForeignKey(SubscriptionModel.subscription_name, ondelete='cascade', onupdate='cascade'), + unique=True + ) + nf_names = Column(String(100)) + model_invariant_ids = Column(String(100)) + model_version_ids = Column(String(100)) + model_names = Column(String(100)) + + def __init__(self, subscription_name, nf_names, model_invariant_ids, model_version_ids, + model_names): + self.subscription_name = subscription_name + self.nf_names = nf_names + self.model_invariant_ids = model_invariant_ids + self.model_version_ids = model_version_ids + 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}' + + def serialize(self): + return {'subscription_name': self.subscription_name, 'nf_names': self.nf_names, + 'model_invariant_ids': self.model_invariant_ids, + 'model_version_ids': self.model_version_ids, 'model_names': self.model_names} + + +class MeasurementGroupModel(db.Model): + __tablename__ = 'measurement_group' + id = Column(Integer, primary_key=True, autoincrement=True) + subscription_name = Column( + String, + ForeignKey(SubscriptionModel.subscription_name, ondelete='cascade', onupdate='cascade') + ) + measurement_group_name = Column(String(100), unique=True) + administrative_state = Column(String(20)) + file_based_gp = Column(Integer) + file_location = Column(String(100)) + measurement_type = Column(JSON) + managed_object_dns_basic = Column(JSON) + + def __init__(self, subscription_name, measurement_group_name, + administrative_state, file_based_gp, file_location, + measurement_type, managed_object_dns_basic): + self.subscription_name = subscription_name + self.measurement_group_name = measurement_group_name + self.administrative_state = administrative_state + self.file_based_gp = file_based_gp + self.file_location = file_location + self.measurement_type = measurement_type + 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}' + + def serialize(self): + return {'subscription_name': self.subscription_name, + 'measurement_group_name': self.measurement_group_name, + 'administrative_state': self.administrative_state, + 'file_based_gp': self.file_based_gp, + 'file_location': self.file_location, + 'measurement_type': self.measurement_type, + 'managed_object_dns_basic': self.managed_object_dns_basic} + + +class NfMeasureGroupRelationalModel(db.Model): + __tablename__ = 'nf_to_measure_grp_rel' + __mapper_args__ = { + 'confirm_deleted_rows': False + } + id = Column(Integer, primary_key=True, autoincrement=True) + measurement_grp_name = Column( + String, + ForeignKey(MeasurementGroupModel.measurement_group_name, ondelete='cascade', + onupdate='cascade') + ) + nf_name = Column( + String, + ForeignKey(NetworkFunctionModel.nf_name, ondelete='cascade', onupdate='cascade') + ) + nf_measure_grp_status = Column(String(20)) + retry_count = Column(Integer) + + def __init__(self, measurement_grp_name, nf_name, nf_measure_grp_status=None, + retry_count=0): + self.measurement_grp_name = measurement_grp_name + self.nf_name = nf_name + self.nf_measure_grp_status = nf_measure_grp_status + 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}' diff --git a/components/pm-subscription-handler/pmsh_service/mod/network_function.py b/components/pm-subscription-handler/pmsh_service/mod/network_function.py index 83130a8e..f7b682d4 100755 --- a/components/pm-subscription-handler/pmsh_service/mod/network_function.py +++ b/components/pm-subscription-handler/pmsh_service/mod/network_function.py @@ -26,7 +26,8 @@ class NetworkFunction: def __init__(self, sdnc_model_name=None, sdnc_model_version=None, **kwargs): """ Object representation of the NetworkFunction. """ self.nf_name = kwargs.get('nf_name') - self.ip_address = kwargs.get('ip_address') + self.ipv4_address = kwargs.get('ipv4_address') + self.ipv6_address = kwargs.get('ipv6_address') self.model_invariant_id = kwargs.get('model_invariant_id') self.model_version_id = kwargs.get('model_version_id') self.model_name = kwargs.get('model_name') @@ -35,13 +36,14 @@ class NetworkFunction: @classmethod def nf_def(cls): - return cls(nf_name=None, ip_address=None, model_invariant_id=None, - model_version_id=None, model_name=None, + return cls(nf_name=None, ipv4_address=None, ipv6_address=None, + model_invariant_id=None, model_version_id=None, model_name=None, sdnc_model_name=None, sdnc_model_version=None) def __str__(self): return f'nf-name: {self.nf_name}, ' \ - f'ipaddress-v4-oam: {self.ip_address}, ' \ + f'ipaddress-v4-oam: {self.ipv4_address}, ' \ + f'ipaddress-v6-oam: {self.ipv6_address}, ' \ f'model-invariant-id: {self.model_invariant_id}, ' \ f'model-version-id: {self.model_version_id}, ' \ f'model-name: {self.model_name}, ' \ @@ -51,7 +53,8 @@ class NetworkFunction: def __eq__(self, other): return \ self.nf_name == other.nf_name and \ - self.ip_address == other.ip_address and \ + self.ipv4_address == other.ipv4_address and \ + self.ipv6_address == other.ipv6_address and \ self.model_invariant_id == other.model_invariant_id and \ self.model_version_id == other.model_version_id and \ self.model_name == other.model_name and \ @@ -59,8 +62,8 @@ class NetworkFunction: self.sdnc_model_version == other.sdnc_model_version def __hash__(self): - return hash((self.nf_name, self.ip_address, self.model_invariant_id, - self.model_version_id, self.model_name, + return hash((self.nf_name, self.ipv4_address, self.ipv6_address, + self.model_invariant_id, self.model_version_id, self.model_name, self.sdnc_model_name, self.sdnc_model_version)) def create(self): @@ -70,7 +73,8 @@ class NetworkFunction: if existing_nf is None: new_nf = NetworkFunctionModel(nf_name=self.nf_name, - ip_address=self.ip_address, + ipv4_address=self.ipv4_address, + ipv6_address=self.ipv6_address, model_invariant_id=self.model_invariant_id, model_version_id=self.model_version_id, model_name=self.model_name, diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription.py b/components/pm-subscription-handler/pmsh_service/mod/subscription.py index fdc1394c..7e878cd1 100755 --- a/components/pm-subscription-handler/pmsh_service/mod/subscription.py +++ b/components/pm-subscription-handler/pmsh_service/mod/subscription.py @@ -106,7 +106,7 @@ class Subscription: """ Updates the status of subscription in subscription table """ try: SubscriptionModel.query.filter( - SubscriptionModel.subscription_name == self.subscriptionName)\ + SubscriptionModel.subscription_name == self.subscriptionName) \ .update({SubscriptionModel.status: self.administrativeState}, synchronize_session='evaluate') @@ -133,14 +133,16 @@ class Subscription: change_type = 'DELETE' else: change_type = 'CREATE' - sub_event = {'nfName': nf.nf_name, - 'ipv4Address': nf.ip_address, - 'blueprintName': nf.sdnc_model_name, - 'blueprintVersion': nf.sdnc_model_version, - 'policyName': app_conf.operational_policy_name, - 'changeType': change_type, - 'closedLoopControlName': app_conf.control_loop_name, - 'subscription': clean_sub} + + sub_event = { + 'nfName': nf.nf_name, + 'ipAddress': nf.ipv4_address if nf.ipv6_address in (None, '') else nf.ipv6_address, + 'blueprintName': nf.sdnc_model_name, + 'blueprintVersion': nf.sdnc_model_version, + 'policyName': app_conf.operational_policy_name, + 'changeType': change_type, + 'closedLoopControlName': app_conf.control_loop_name, + 'subscription': clean_sub} return sub_event except Exception as e: logger.error(f'Failed to prep Sub event for xNF {nf.nf_name}: {e}', exc_info=True) diff --git a/components/pm-subscription-handler/pom.xml b/components/pm-subscription-handler/pom.xml index fbf44977..a0b58f4d 100644 --- a/components/pm-subscription-handler/pom.xml +++ b/components/pm-subscription-handler/pom.xml @@ -32,7 +32,7 @@ org.onap.dcaegen2.services pmsh dcaegen2-services-pm-subscription-handler - 1.3.1-SNAPSHOT + 1.3.2-SNAPSHOT UTF-8 . diff --git a/components/pm-subscription-handler/tests/data/pm_subscription_event.json b/components/pm-subscription-handler/tests/data/pm_subscription_event.json index cd547d9d..6b94373a 100755 --- a/components/pm-subscription-handler/tests/data/pm_subscription_event.json +++ b/components/pm-subscription-handler/tests/data/pm_subscription_event.json @@ -5,7 +5,7 @@ "policyName":"pmsh-operational-policy", "changeType":"CREATE", "closedLoopControlName":"pmsh-control-loop", - "ipv4Address": "1.2.3.4", + "ipAddress": "204.120.0.15", "subscription":{ "subscriptionName":"ExtraPM-All-gNB-R2B", "administrativeState":"UNLOCKED", diff --git a/components/pm-subscription-handler/tests/test_network_function.py b/components/pm-subscription-handler/tests/test_network_function.py index 5a1a6ba8..3e38b9c6 100755 --- a/components/pm-subscription-handler/tests/test_network_function.py +++ b/components/pm-subscription-handler/tests/test_network_function.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2020 Nordix Foundation. +# Copyright (C) 2019-2021 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -33,12 +33,14 @@ class NetworkFunctionTests(BaseClassSetup): super().setUp() self.nf_1 = NetworkFunction(sdnc_model_name='blah', sdnc_model_version=1.0, **{'nf_name': 'pnf_1', - 'ip_address': '1.2.3.4', + 'ipv4_address': '204.120.0.15', + 'ipv6_address': '2001:db8:3333:4444:5555:6666:7777:8888', 'model_invariant_id': 'some_id', 'model_version_id': 'some_other_id'}) self.nf_2 = NetworkFunction(sdnc_model_name='blah', sdnc_model_version=2.0, **{'nf_name': 'pnf_2', - 'ip_address': '1.2.3.4', + 'ipv4_address': '204.120.0.15', + 'ipv6_address': '2001:db8:3333:4444:5555:6666:7777:8888', 'model_invariant_id': 'some_id', 'model_version_id': 'some_other_id'}) with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data: diff --git a/components/pm-subscription-handler/tests/test_subscription.py b/components/pm-subscription-handler/tests/test_subscription.py index b18f41e8..01c573e3 100755 --- a/components/pm-subscription-handler/tests/test_subscription.py +++ b/components/pm-subscription-handler/tests/test_subscription.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2020 Nordix Foundation. +# Copyright (C) 2019-2021 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -140,7 +140,24 @@ class SubscriptionTest(BaseClassSetup): 'data/pm_subscription_event.json'), 'r') as data: expected_sub_event = json.load(data) nf = NetworkFunction(nf_name='pnf_1', - ip_address='1.2.3.4', + ipv4_address='204.120.0.15', + ipv6_address='', + model_invariant_id='some-id', + model_version_id='some-id') + nf.sdnc_model_name = 'some-name' + nf.sdnc_model_version = 'some-version' + actual_sub_event = self.app_conf.subscription.prepare_subscription_event(nf, self.app_conf) + print(actual_sub_event) + self.assertEqual(expected_sub_event, actual_sub_event) + + def test_prepare_subscription_event_with_ipv6(self): + with open(os.path.join(os.path.dirname(__file__), + 'data/pm_subscription_event.json'), 'r') as data: + expected_sub_event = json.load(data) + expected_sub_event['ipAddress'] = '2001:db8:3333:4444:5555:6666:7777:8888' + nf = NetworkFunction(nf_name='pnf_1', + ipv4_address='204.120.0.15', + ipv6_address='2001:db8:3333:4444:5555:6666:7777:8888', model_invariant_id='some-id', model_version_id='some-id') nf.sdnc_model_name = 'some-name' diff --git a/components/pm-subscription-handler/tests/test_subscription_handler.py b/components/pm-subscription-handler/tests/test_subscription_handler.py index 2293ee50..ecc45f66 100644 --- a/components/pm-subscription-handler/tests/test_subscription_handler.py +++ b/components/pm-subscription-handler/tests/test_subscription_handler.py @@ -109,7 +109,8 @@ class SubscriptionHandlerTest(BaseClassSetup): MagicMock(return_value=NetworkFunctionModel(nf_name='pnf_1', model_invariant_id='some-id', model_version_id='some-id', - ip_address='ip_address', + ipv4_address='ip_address4', + ipv6_address='ip_address6', model_name='model_name', sdnc_model_name='sdnc_model_name', sdnc_model_version='sdnc_model_version'))) @@ -145,7 +146,8 @@ class SubscriptionHandlerTest(BaseClassSetup): MagicMock(return_value=NetworkFunctionModel(nf_name='pnf_1', model_invariant_id='some-id', model_version_id='some-id', - ip_address='ip_address', + ipv4_address='ip_address4', + ipv6_address='ip_address6', model_name='model_name', sdnc_model_name='sdnc_model_name', sdnc_model_version='sdnc_model_version', -- cgit 1.2.3-korg