From 48f7b3d0d6fc76f6949b0608465267325237c00c Mon Sep 17 00:00:00 2001 From: laili Date: Sat, 15 Sep 2018 16:26:26 +0800 Subject: [PATCH] Trigger subscription in nslcm. Delete subscription when terminate vnf. Change-Id: Ic7d94f3698b2bf73543f702d9ffbb41ceac26b7e Issue-ID: VFC-1126 Signed-off-by: laili --- lcm/ns_vnfs/biz/create_vnfs.py | 7 ++--- lcm/ns_vnfs/biz/subscribe.py | 55 ++++++++++++++++++++++++++++++++++++---- lcm/ns_vnfs/biz/terminate_nfs.py | 7 ++++- lcm/ns_vnfs/tests/tests.py | 44 ++++++++++++++++++++++++++++++-- lcm/pub/database/models.py | 13 ++++++++++ 5 files changed, 115 insertions(+), 11 deletions(-) diff --git a/lcm/ns_vnfs/biz/create_vnfs.py b/lcm/ns_vnfs/biz/create_vnfs.py index ec3cc312..ea755362 100644 --- a/lcm/ns_vnfs/biz/create_vnfs.py +++ b/lcm/ns_vnfs/biz/create_vnfs.py @@ -1,4 +1,4 @@ -# Copyright 2016 ZTE Corporation. +# Copyright 2016-2018 ZTE Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,6 +11,7 @@ # 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. + import json import logging import traceback @@ -34,7 +35,7 @@ from lcm.pub.utils import restcall from lcm.ns_vnfs.const import VNF_STATUS, NFVO_VNF_INST_TIMEOUT_SECOND, INST_TYPE, INST_TYPE_NAME from lcm.ns_vnfs.biz.wait_job import wait_job_finish from lcm.pub.config.config import REG_TO_MSB_REG_PARAM, OOF_BASE_URL, OOF_PASSWD, OOF_USER -from lcm.ns_vnfs.biz.subscribe import Subscription +from lcm.ns_vnfs.biz.subscribe import SubscriptionCreation logger = logging.getLogger(__name__) @@ -335,7 +336,7 @@ class CreateVnfs(Thread): 'vnfInstanceId': self.vnfm_nf_inst_id, 'vnfmId': self.vnfm_inst_id } - Subscription(data).do_biz() + SubscriptionCreation(data).do_biz() def write_vnf_creation_info(self): logger.debug("write_vnf_creation_info start") diff --git a/lcm/ns_vnfs/biz/subscribe.py b/lcm/ns_vnfs/biz/subscribe.py index 71ef6ccd..2a4a8173 100644 --- a/lcm/ns_vnfs/biz/subscribe.py +++ b/lcm/ns_vnfs/biz/subscribe.py @@ -15,14 +15,16 @@ import json import logging +from lcm.pub.database.models import SubscriptionModel from lcm.pub.exceptions import NSLCMException from lcm.pub.msapi.extsys import get_vnfm_by_id from lcm.pub.utils.restcall import req_by_msb +from lcm.pub.utils.values import ignore_case_get logger = logging.getLogger(__name__) -class Subscription(object): +class SubscriptionCreation(object): def __init__(self, data): self.data = data self.vnf_instance_id = self.data['vnfInstanceId'] @@ -34,7 +36,7 @@ class Subscription(object): def do_biz(self): logger.debug('Start subscribing...') self.prepare_subscription_request_data() - self.subscribe_lccn_notification() + self.send_subscription_request() self.save_subscription_response_data() logger.debug('Subscribing has completed.') @@ -80,12 +82,55 @@ class Subscription(object): } } - def subscribe_lccn_notification(self): - ret = req_by_msb('api/gvnfmdrvier/v1/%s/subscriptions' % self.vnfm_id, self.subscription_request_data) + def send_subscription_request(self): + ret = req_by_msb('api/gvnfmdrvier/v1/%s/subscriptions' % self.vnfm_id, 'POST', self.subscription_request_data) if ret[0] != 0: logger.error("Status code is %s, detail is %s.", ret[2], ret[1]) raise NSLCMException("Failed to subscribe from vnfm(%s)." % self.vnfm_id) self.subscription_response_data = json.JSONDecoder().decode(ret[1]) def save_subscription_response_data(self): - pass + logger.debug("Save subscription[%s] to the database" % self.subscription_response_data['id']) + lccn_filter = self.subscription_response_data['filter'] + SubscriptionModel.objects.create( + subscription_id=self.subscription_response_data['id'], + notification_types=json.dumps(lccn_filter['notificationTypes']), + operation_types=json.dumps(lccn_filter['operationTypes']), + operation_states=json.dumps(lccn_filter['operationStates']), + vnf_instance_filter=json.dumps(lccn_filter['vnfInstanceSubscriptionFilter']), + callback_uri=self.subscription_response_data['callbackUri'], + links=json.dumps(self.subscription_response_data['_links']) + ) + logger.debug('Subscription[%s] has been created', self.subscription_response_data['id']) + + +class SubscriptionDeletion(object): + def __init__(self, vnfm_id, vnf_instance_id): + self.vnfm_id = vnfm_id + self.vnf_instance_id = vnf_instance_id + self.subscription_id = None + self.subscription = None + + def do_biz(self): + self.filter_subscription() + self.send_subscription_deletion_request() + self.delete_subscription_in_db() + + def filter_subscription(self): + subscritptions = SubscriptionModel.objects.filter(vnf_instance_filter__contains=self.vnf_instance_id) + if not subscritptions.exists(): + logger.debug("Subscription contains VNF(%s) does not exist." % self.vnf_instacne_id) + self.subscription = subscritptions.first() + + def send_subscription_deletion_request(self): + if self.subscription: + self.subscription_id = ignore_case_get(self.subscription, 'id') + ret = req_by_msb('api/gvnfmdrvier/v1/%s/subscriptions/%s' % (self.vnfm_id, self.subscription_id), 'DELETE') + if ret[0] != 0: + logger.error('Status code is %s, detail is %s.', ret[2], ret[1]) + raise NSLCMException("Failed to subscribe from vnfm(%s)." % self.vnfm_id) + logger.debug('Subscripton(%s) in vnfm(%s) has been deleted.' % (self.subscription, self.vnfm_id)) + + def delete_subscription_in_db(self): + if self.subscription: + self.subscription.delete() diff --git a/lcm/ns_vnfs/biz/terminate_nfs.py b/lcm/ns_vnfs/biz/terminate_nfs.py index 98bc7d20..f921edd0 100644 --- a/lcm/ns_vnfs/biz/terminate_nfs.py +++ b/lcm/ns_vnfs/biz/terminate_nfs.py @@ -1,4 +1,4 @@ -# Copyright 2016 ZTE Corporation. +# Copyright 2016-2018 ZTE Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ from lcm.pub.utils.jobutil import JOB_MODEL_STATUS, JobUtil from lcm.pub.utils.values import ignore_case_get from lcm.ns_vnfs.const import VNF_STATUS, NFVO_VNF_INST_TIMEOUT_SECOND, INST_TYPE from lcm.ns_vnfs.biz.wait_job import wait_job_finish +from lcm.ns_vnfs.biz.subscribe import SubscriptionDeletion logger = logging.getLogger(__name__) @@ -53,6 +54,7 @@ class TerminateVnfs(threading.Thread): if REPORT_TO_AAI: self.delete_vserver_in_aai() self.delete_vnf_in_aai() + self.delete_subscription() self.delete_data_from_db() except NSLCMException as e: self.set_job_err(e.message) @@ -128,6 +130,9 @@ class TerminateVnfs(threading.Thread): logger.error('VNF terminate failed on VNFM side.') raise NSLCMException('VNF terminate failed on VNFM side.') + def delete_subscription(self): + SubscriptionDeletion(self.vnfm_inst_id, self.vnf_inst_id).do_biz() + def delete_data_from_db(self): NfInstModel.objects.filter(nfinstid=self.vnf_inst_id).delete() JobUtil.add_job_status(self.job_id, 100, 'vnf terminate success', 0) diff --git a/lcm/ns_vnfs/tests/tests.py b/lcm/ns_vnfs/tests/tests.py index ba92e194..6669fbc7 100644 --- a/lcm/ns_vnfs/tests/tests.py +++ b/lcm/ns_vnfs/tests/tests.py @@ -18,7 +18,7 @@ import mock from django.test import TestCase, Client from rest_framework import status -from lcm.pub.database.models import NfInstModel, JobModel, NSInstModel, VmInstModel, OOFDataModel +from lcm.pub.database.models import NfInstModel, JobModel, NSInstModel, VmInstModel, OOFDataModel, SubscriptionModel from lcm.pub.exceptions import NSLCMException from lcm.pub.utils import restcall from lcm.pub.utils.jobutil import JOB_MODEL_STATUS @@ -28,6 +28,7 @@ from lcm.pub.utils.values import ignore_case_get from lcm.ns_vnfs.biz.create_vnfs import CreateVnfs from lcm.ns_vnfs.biz.heal_vnfs import NFHealService from lcm.ns_vnfs.biz.scale_vnfs import NFManualScaleService +from lcm.ns_vnfs.biz.subscribe import SubscriptionDeletion from lcm.ns_vnfs.biz.terminate_nfs import TerminateVnfs from lcm.ns_vnfs.const import VNF_STATUS, INST_TYPE from lcm.ns_vnfs.biz import create_vnfs @@ -257,7 +258,8 @@ class TestTerminateVnfViews(TestCase): self.failUnlessEqual(status.HTTP_202_ACCEPTED, response.status_code) @mock.patch.object(restcall, 'call_req') - def test_terminate_vnf(self, mock_call_req): + @mock.patch.object(SubscriptionDeletion, 'send_subscription_deletion_request') + def test_terminate_vnf(self, mock_send_subscription_deletion_request, mock_call_req): job_id = JobUtil.create_job("VNF", JOB_TYPE.TERMINATE_VNF, self.nf_inst_id) nfinst = NfInstModel.objects.filter(nfinstid=self.nf_inst_id) @@ -266,6 +268,43 @@ class TestTerminateVnfViews(TestCase): else: self.failUnlessEqual(1, 0) + notification_types = ["VnfLcmOperationOccurrenceNotification"], + operation_types = [ + "INSTANTIATE", + "SCALE", + "SCALE_TO_LEVEL", + "CHANGE_FLAVOUR", + "TERMINATE", + "HEAL", + "OPERATE", + "CHANGE_EXT_CONN", + "MODIFY_INFO" + ], + operation_states = [ + "STARTING", + "PROCESSING", + "COMPLETED", + "FAILED_TEMP", + "FAILED", + "ROLLING_BACK", + "ROLLED_BACK" + ], + vnf_instance_subscription_filter = { + "vnfdIds": [], + "vnfInstanceIds": '1', + "vnfInstanceNames": [], + "vnfProductsFromProviders": {} + } + SubscriptionModel.objects.create( + subscription_id='1', + notification_types=json.dumps(notification_types), + operation_types=json.dumps(operation_types), + operation_states=json.dumps(operation_states), + vnf_instance_filter=json.dumps(vnf_instance_subscription_filter), + # callback_uri, + # links=json.dumps(...) + ) + vnf_info = { "vnf-id": "vnf-id-test111", "vnf-name": "vnf-name-test111", @@ -317,6 +356,7 @@ class TestTerminateVnfViews(TestCase): def side_effect(*args): return mock_vals[args[4]] + mock_call_req.side_effect = side_effect req_data = { diff --git a/lcm/pub/database/models.py b/lcm/pub/database/models.py index 7c6fee73..f1aa57ab 100644 --- a/lcm/pub/database/models.py +++ b/lcm/pub/database/models.py @@ -330,3 +330,16 @@ class OOFDataModel(models.Model): cloud_owner = models.CharField(db_column='CLOUDOWNER', max_length=100, null=True, blank=True) cloud_region_id = models.CharField(db_column='CLOUDREGIONID', max_length=255, null=True, blank=True) vdu_info = models.TextField(db_column='VDUINFO', max_length=65535, null=True, blank=True) + + +class SubscriptionModel(models.Model): + class Meta: + db_table = 'NFVO_SUBSCRIPTION' + + subscription_id = models.CharField(db_column='SUBSCRIPTIONID', max_length=255, primary_key=True) + vnf_instance_filter = models.TextField(db_column='VNFINSTANCEFILTER', null=True) + notification_types = models.TextField(db_column='NOTIFICATIONTYPES', null=True) + operation_types = models.TextField(db_column='OPERATIONTYPES', null=True) + operation_states = models.TextField(db_column='OPERATIONSTATES', null=True) + callback_uri = models.CharField(db_column='CALLBACKURI', max_length=255) + links = models.TextField(db_column='LINKS', max_length=20000) -- 2.16.6