From 9975ee2ab76998715538fa3aeee377b947125b7e Mon Sep 17 00:00:00 2001 From: laili Date: Thu, 13 Sep 2018 10:54:16 +0800 Subject: [PATCH] Notification stuffs. - Send operation and terminate notification using notificationutil. Change-Id: Id32d6ed37cf8f09c836c90c03819b8125135e69a Issue-ID: VFC-1095 Signed-off-by: laili --- lcm/lcm/nf/biz/instantiate_vnf.py | 4 +- lcm/lcm/nf/biz/operate_vnf.py | 15 +++--- lcm/lcm/nf/biz/terminate_vnf.py | 15 +++--- lcm/lcm/nf/const.py | 63 +++++++++++++++++------- lcm/lcm/nf/serializers/affected_storages.py | 9 ++-- lcm/lcm/nf/serializers/affected_vls.py | 13 ++--- lcm/lcm/nf/serializers/affected_vnfcs.py | 9 ++-- lcm/lcm/nf/tests/test_operate_vnf.py | 74 ++++++++++++++++++++++++++--- lcm/lcm/nf/tests/test_terminate_vnf.py | 38 +++++++++++++-- lcm/lcm/pub/msapi/gvnfmdriver.py | 4 +- 10 files changed, 187 insertions(+), 57 deletions(-) diff --git a/lcm/lcm/nf/biz/instantiate_vnf.py b/lcm/lcm/nf/biz/instantiate_vnf.py index f86baab4..73109c80 100644 --- a/lcm/lcm/nf/biz/instantiate_vnf.py +++ b/lcm/lcm/nf/biz/instantiate_vnf.py @@ -30,7 +30,7 @@ from lcm.pub.utils.notificationsutil import NotificationsUtil from lcm.pub.utils.values import ignore_case_get, get_none, get_boolean, get_integer from lcm.pub.vimapi import adaptor from lcm.nf.biz.grant_vnf import grant_resource -from lcm.nf.const import GRANT_TYPE +from lcm.nf.const import CHANGE_TYPE, GRANT_TYPE, OPERATION_TYPE logger = logging.getLogger(__name__) @@ -131,7 +131,7 @@ class InstantiateVnf(Thread): logger.info("Create resource finish") def lcm_notify(self): - notification_content = prepare_notification_data(self.nf_inst_id, self.job_id, "ADDED") + notification_content = prepare_notification_data(self.nf_inst_id, self.job_id, CHANGE_TYPE.ADDED, OPERATION_TYPE.INSTANTIATE) logger.info('Notify request data = %s' % notification_content) # resp = notify_lcm_to_nfvo(json.dumps(notification_content)) # logger.info('Lcm notify end, response %s' % resp) diff --git a/lcm/lcm/nf/biz/operate_vnf.py b/lcm/lcm/nf/biz/operate_vnf.py index 99c1e6d9..1c01adaf 100644 --- a/lcm/lcm/nf/biz/operate_vnf.py +++ b/lcm/lcm/nf/biz/operate_vnf.py @@ -12,20 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json +# import json import logging import traceback from threading import Thread from lcm.pub.database.models import NfInstModel, VmInstModel from lcm.pub.exceptions import NFLCMException -from lcm.pub.msapi.gvnfmdriver import notify_lcm_to_nfvo, prepare_notification_data +from lcm.pub.msapi.gvnfmdriver import prepare_notification_data +# from lcm.pub.msapi.gvnfmdriver import notify_lcm_to_nfvo from lcm.pub.utils.jobutil import JobUtil from lcm.pub.utils.timeutil import now_time +from lcm.pub.utils.notificationsutil import NotificationsUtil from lcm.pub.utils.values import ignore_case_get from lcm.pub.vimapi import adaptor from lcm.nf.biz.grant_vnf import grant_resource -from lcm.nf.const import VNF_STATUS, RESOURCE_MAP, GRANT_TYPE +from lcm.nf.const import VNF_STATUS, RESOURCE_MAP, CHANGE_TYPE, GRANT_TYPE, OPERATION_TYPE logger = logging.getLogger(__name__) @@ -88,10 +90,11 @@ class OperateVnf(Thread): logger.info('Operate resource complete') def lcm_notify(self): - notification_content = prepare_notification_data(self.nf_inst_id, self.job_id, "MODIFIED") + notification_content = prepare_notification_data(self.nf_inst_id, self.job_id, CHANGE_TYPE.MODIFIED, OPERATION_TYPE.OPERATE) logger.info('Notify request data = %s' % notification_content) - resp = notify_lcm_to_nfvo(json.dumps(notification_content)) - logger.info('Lcm notify end, response %s' % resp) + # resp = notify_lcm_to_nfvo(json.dumps(notification_content)) + # logger.info('Lcm notify end, response %s' % resp) + NotificationsUtil().send_notification(notification_content) def vnf_operate_failed_handle(self, error_msg): logger.error('VNF Operation failed, detail message: %s' % error_msg) diff --git a/lcm/lcm/nf/biz/terminate_vnf.py b/lcm/lcm/nf/biz/terminate_vnf.py index 5b299f20..4f74f62d 100644 --- a/lcm/lcm/nf/biz/terminate_vnf.py +++ b/lcm/lcm/nf/biz/terminate_vnf.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json +# import json import logging import traceback from threading import Thread @@ -24,13 +24,15 @@ from lcm.pub.database.models import ( FlavourInstModel, SubNetworkInstModel ) from lcm.pub.exceptions import NFLCMException -from lcm.pub.msapi.gvnfmdriver import prepare_notification_data, notify_lcm_to_nfvo +from lcm.pub.msapi.gvnfmdriver import prepare_notification_data +# from lcm.pub.msapi.gvnfmdriver import notify_lcm_to_nfvo from lcm.pub.utils.jobutil import JobUtil from lcm.pub.utils.timeutil import now_time +from lcm.pub.utils.notificationsutil import NotificationsUtil from lcm.pub.utils.values import ignore_case_get from lcm.pub.vimapi import adaptor from lcm.nf.biz.grant_vnf import grant_resource -from lcm.nf.const import GRANT_TYPE +from lcm.nf.const import CHANGE_TYPE, GRANT_TYPE, OPERATION_TYPE logger = logging.getLogger(__name__) @@ -98,7 +100,7 @@ class TerminateVnf(Thread): } def query_notify_data(self): - self.notify_data = prepare_notification_data(self.nf_inst_id, self.job_id, "RMOVED") + self.notify_data = prepare_notification_data(self.nf_inst_id, self.job_id, CHANGE_TYPE.REMOVED, OPERATION_TYPE.TERMINATE) NetworkInstModel.objects.filter(instid=self.nf_inst_id) StorageInstModel.objects.filter(instid=self.nf_inst_id) PortInstModel.objects.filter(instid=self.nf_inst_id) @@ -120,8 +122,9 @@ class TerminateVnf(Thread): def lcm_notify(self): NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status='NOT_INSTANTIATED', lastuptime=now_time()) logger.info('Send notify request to nfvo') - resp = notify_lcm_to_nfvo(json.dumps(self.notify_data)) - logger.info('Lcm notify end, response: %s' % resp) + # resp = notify_lcm_to_nfvo(json.dumps(self.notify_data)) + # logger.info('Lcm notify end, response: %s' % resp) + NotificationsUtil().send_notification(self.notify_data) def vnf_term_failed_handle(self, error_msg): logger.error('VNF termination failed, detail message: %s' % error_msg) diff --git a/lcm/lcm/nf/const.py b/lcm/lcm/nf/const.py index 15e27155..912b9c38 100644 --- a/lcm/lcm/nf/const.py +++ b/lcm/lcm/nf/const.py @@ -22,6 +22,37 @@ VNF_STATUS = enum(NULL='null', INSTANTIATING="instantiating", INACTIVE='inactive FAILED="failed", TERMINATING="terminating", SCALING="scaling", OPERATING="operating", UPDATING="updating", HEALING="healing") +OPERATION_TYPE = enum( + INSTANTIATE="INSTANTIATE", + SCALE="SCALE", + SCALE_TO_LEVEL="SCALE_TO_LEVEL", + CHANGE_FLAVOUR="CHANGE_FLAVOUR", + TERMINATE="TERMINATE", + HEAL="HEAL", + OPERATE="OPERATE", + CHANGE_EXT_CONN="CHANGE_EXT_CONN", + MODIFY_INFO="MODIFY_INFO" +) + +OPERATION_STATE_TYPE = enum( + STARTING="STARTING", + PROCESSING="PROCESSING", + COMPLETED="COMPLETED", + FAILED_TEMP="FAILED_TEMP", + FAILED="FAILED", + ROLLING_BACK="ROLLING_BACK", + ROLLED_BACK="ROLLED_BACK" +) + +CHANGE_TYPE = enum( + ADDED='ADDED', + REMOVED='REMOVED', + MODIFIED='MODIFIED', + TEMPORARY='TEMPORARY', + LINK_PORT_ADDED='LINK_PORT_ADDED', + LINK_PORT_REMOVED='LINK_PORT_REMOVED' +) + RESOURCE_MAP = {'Storage': 'volumn', 'Network': 'network', 'SubNetwork': 'subnet', 'Port': 'port', 'Flavour': 'flavor', 'Vm': 'vm'} @@ -42,25 +73,25 @@ NOTIFICATION_TYPES = [ ] LCM_OPERATION_TYPES = [ - "INSTANTIATE", - "SCALE", - "SCALE_TO_LEVEL", - "CHANGE_FLAVOUR", - "TERMINATE", - "HEAL", - "OPERATE", - "CHANGE_EXT_CONN", - "MODIFY_INFO" + OPERATION_TYPE.INSTANTIATE, + OPERATION_TYPE.SCALE, + OPERATION_TYPE.SCALE_TO_LEVEL, + OPERATION_TYPE.CHANGE_FLAVOUR, + OPERATION_TYPE.TERMINATE, + OPERATION_TYPE.HEAL, + OPERATION_TYPE.OPERATE, + OPERATION_TYPE.CHANGE_EXT_CONN, + OPERATION_TYPE.MODIFY_INFO ] LCM_OPERATION_STATE_TYPES = [ - "STARTING", - "PROCESSING", - "COMPLETED", - "FAILED_TEMP", - "FAILED", - "ROLLING_BACK", - "ROLLED_BACK" + OPERATION_STATE_TYPE.STARTING, + OPERATION_STATE_TYPE.PROCESSING, + OPERATION_STATE_TYPE.COMPLETED, + OPERATION_STATE_TYPE.FAILED_TEMP, + OPERATION_STATE_TYPE.FAILED, + OPERATION_STATE_TYPE.ROLLING_BACK, + OPERATION_STATE_TYPE.ROLLED_BACK ] diff --git a/lcm/lcm/nf/serializers/affected_storages.py b/lcm/lcm/nf/serializers/affected_storages.py index de66f288..1c01fefb 100644 --- a/lcm/lcm/nf/serializers/affected_storages.py +++ b/lcm/lcm/nf/serializers/affected_storages.py @@ -16,12 +16,13 @@ from rest_framework import serializers from resource_handle import ResourceHandleSerializer +from lcm.nf.const import CHANGE_TYPE CHANGE_TYPES = [ - "ADDED", - "REMOVED", - "MODIFIED", - "TEMPORARY" + CHANGE_TYPE.ADDED, + CHANGE_TYPE.REMOVED, + CHANGE_TYPE.MODIFIED, + CHANGE_TYPE.TEMPORARY ] diff --git a/lcm/lcm/nf/serializers/affected_vls.py b/lcm/lcm/nf/serializers/affected_vls.py index 7bd362ec..0b47b27f 100644 --- a/lcm/lcm/nf/serializers/affected_vls.py +++ b/lcm/lcm/nf/serializers/affected_vls.py @@ -16,14 +16,15 @@ from rest_framework import serializers from resource_handle import ResourceHandleSerializer +from lcm.nf.const import CHANGE_TYPE CHANGE_TYPES = [ - "ADDED", - "REMOVED", - "MODIFIED", - "TEMPORARY", - "LINK_PORT_ADDED", - "LINK_PORT_REMOVED" + CHANGE_TYPE.ADDED, + CHANGE_TYPE.REMOVED, + CHANGE_TYPE.MODIFIED, + CHANGE_TYPE.TEMPORARY, + CHANGE_TYPE.LINK_PORT_ADDED, + CHANGE_TYPE.LINK_PORT_REMOVED ] diff --git a/lcm/lcm/nf/serializers/affected_vnfcs.py b/lcm/lcm/nf/serializers/affected_vnfcs.py index 85b83641..10d93473 100644 --- a/lcm/lcm/nf/serializers/affected_vnfcs.py +++ b/lcm/lcm/nf/serializers/affected_vnfcs.py @@ -16,12 +16,13 @@ from rest_framework import serializers from resource_handle import ResourceHandleSerializer +from lcm.nf.const import CHANGE_TYPE CHANGE_TYPES = [ - "ADDED", - "REMOVED", - "MODIFIED", - "TEMPORARY" + CHANGE_TYPE.ADDED, + CHANGE_TYPE.REMOVED, + CHANGE_TYPE.MODIFIED, + CHANGE_TYPE.TEMPORARY ] diff --git a/lcm/lcm/nf/tests/test_operate_vnf.py b/lcm/lcm/nf/tests/test_operate_vnf.py index 625d40a3..3ebc90a2 100644 --- a/lcm/lcm/nf/tests/test_operate_vnf.py +++ b/lcm/lcm/nf/tests/test_operate_vnf.py @@ -13,15 +13,17 @@ # limitations under the License. import json +import uuid import mock from django.test import TestCase, Client from rest_framework import status from lcm.nf.biz.operate_vnf import OperateVnf -from lcm.pub.database.models import NfInstModel, JobStatusModel, VmInstModel +from lcm.pub.database.models import NfInstModel, JobStatusModel, VmInstModel, SubscriptionModel from lcm.pub.utils import restcall from lcm.pub.utils.jobutil import JobUtil +from lcm.pub.utils.notificationsutil import NotificationsUtil from lcm.pub.utils.timeutil import now_time from lcm.pub.vimapi import api @@ -68,7 +70,8 @@ class TestNFOperate(TestCase): @mock.patch.object(restcall, 'call_req') @mock.patch.object(api, 'call') - def test_operate_vnf_success_start(self, mock_call, mock_call_req): + @mock.patch.object(NotificationsUtil, 'post_notification') + def test_operate_vnf_success_start(self, mock_post_notification, mock_call, mock_call_req): NfInstModel.objects.create(nfinstid='1111', nf_name='2222', vnfminstid='1', @@ -93,11 +96,39 @@ class TestNFOperate(TestCase): vmname="test_01", is_predefined=1, operationalstate=1) + + SubscriptionModel.objects.create( + subscription_id=str(uuid.uuid4()), + callback_uri='api/gvnfmdriver/v1/vnfs/lifecyclechangesnotification', + auth_info=json.JSONEncoder().encode({ + 'authType': ['BASIC'], + 'paramsBasic': { + 'userName': 'username', + 'password': 'password' + } + }), + notification_types=str([ + 'VnfLcmOperationOccurrenceNotification', + 'VnfIdentifierCreationNotification', + 'VnfIdentifierDeletionNotification' + ]), + operation_types=str(['OPERATE']), + operation_states=str(['COMPLETED']), + vnf_instance_filter=json.JSONEncoder().encode({ + 'vnfdIds': [], + 'vnfProductsFromProviders': [], + 'vnfInstanceIds': ['1111'], + 'vnfInstanceNames': [], + }) + ) + t1_apply_grant_result = [0, json.JSONEncoder().encode(''), '200'] - t2_lcm_notify_result = [0, json.JSONEncoder().encode(''), '200'] + # t2_lcm_notify_result = [0, json.JSONEncoder().encode(''), '200'] t3_action_vm_start_result = [0, json.JSONEncoder().encode(''), '202'] - mock_call_req.side_effect = [t1_apply_grant_result, t2_lcm_notify_result, t3_action_vm_start_result] + # mock_call_req.side_effect = [t1_apply_grant_result, t2_lcm_notify_result, t3_action_vm_start_result] + mock_call_req.side_effect = [t1_apply_grant_result, t3_action_vm_start_result] mock_call.return_value = None + mock_post_notification.return_value = None req_data = { "changeStateTo": "STARTED" } @@ -111,7 +142,8 @@ class TestNFOperate(TestCase): @mock.patch.object(restcall, 'call_req') @mock.patch.object(api, 'call') - def test_operate_vnf_success_stop(self, mock_call, mock_call_req): + @mock.patch.object(NotificationsUtil, 'post_notification') + def test_operate_vnf_success_stop(self, mock_post_notification, mock_call, mock_call_req): NfInstModel.objects.create(nfinstid='1111', nf_name='2222', vnfminstid='1', @@ -136,11 +168,39 @@ class TestNFOperate(TestCase): vmname="test_01", is_predefined=1, operationalstate=1) + + SubscriptionModel.objects.create( + subscription_id=str(uuid.uuid4()), + callback_uri='api/gvnfmdriver/v1/vnfs/lifecyclechangesnotification', + auth_info=json.JSONEncoder().encode({ + 'authType': ['BASIC'], + 'paramsBasic': { + 'userName': 'username', + 'password': 'password' + } + }), + notification_types=str([ + 'VnfLcmOperationOccurrenceNotification', + 'VnfIdentifierCreationNotification', + 'VnfIdentifierDeletionNotification' + ]), + operation_types=str(['OPERATE']), + operation_states=str(['COMPLETED']), + vnf_instance_filter=json.JSONEncoder().encode({ + 'vnfdIds': [], + 'vnfProductsFromProviders': [], + 'vnfInstanceIds': ['1111'], + 'vnfInstanceNames': [], + }) + ) + t1_apply_grant_result = [0, json.JSONEncoder().encode(''), '200'] - t2_lcm_notify_result = [0, json.JSONEncoder().encode(''), '200'] + # t2_lcm_notify_result = [0, json.JSONEncoder().encode(''), '200'] t3_action_vm_stop_result = [0, json.JSONEncoder().encode(''), '202'] - mock_call_req.side_effect = [t1_apply_grant_result, t2_lcm_notify_result, t3_action_vm_stop_result] + # mock_call_req.side_effect = [t1_apply_grant_result, t2_lcm_notify_result, t3_action_vm_stop_result] + mock_call_req.side_effect = [t1_apply_grant_result, t3_action_vm_stop_result] mock_call.return_value = None + mock_post_notification.return_value = None req_data = { "changeStateTo": "STOPPED" } diff --git a/lcm/lcm/nf/tests/test_terminate_vnf.py b/lcm/lcm/nf/tests/test_terminate_vnf.py index 97330b6c..5e9a9a84 100644 --- a/lcm/lcm/nf/tests/test_terminate_vnf.py +++ b/lcm/lcm/nf/tests/test_terminate_vnf.py @@ -22,10 +22,11 @@ from rest_framework import status from lcm.nf.biz.terminate_vnf import TerminateVnf from lcm.pub.database.models import NfInstModel, JobStatusModel, VmInstModel, NetworkInstModel, SubNetworkInstModel, \ - PortInstModel, FlavourInstModel, StorageInstModel + PortInstModel, FlavourInstModel, StorageInstModel, SubscriptionModel from lcm.pub.utils import restcall from lcm.pub.utils.jobutil import JobUtil from lcm.pub.utils.timeutil import now_time +from lcm.pub.utils.notificationsutil import NotificationsUtil from lcm.pub.vimapi import api @@ -115,7 +116,8 @@ class TestNFTerminate(TestCase): @mock.patch.object(restcall, 'call_req') @mock.patch.object(api, 'call') - def test_terminate_vnf_success(self, mock_call, mock_call_req): + @mock.patch.object(NotificationsUtil, 'post_notification') + def test_terminate_vnf_success(self, mock_post_notification, mock_call, mock_call_req): NfInstModel.objects.create(nfinstid='1111', nf_name='2222', vnfminstid='1', @@ -131,6 +133,32 @@ class TestNFTerminate(TestCase): vnfConfigurableProperties='todo', localizationLanguage='EN_US', create_time=now_time()) + + SubscriptionModel.objects.create( + subscription_id=str(uuid.uuid4()), + callback_uri='api/gvnfmdriver/v1/vnfs/lifecyclechangesnotification', + auth_info=json.JSONEncoder().encode({ + 'authType': ['BASIC'], + 'paramsBasic': { + 'userName': 'username', + 'password': 'password' + } + }), + notification_types=str([ + 'VnfLcmOperationOccurrenceNotification', + 'VnfIdentifierCreationNotification', + 'VnfIdentifierDeletionNotification' + ]), + operation_types=str(['TERMINATE']), + operation_states=str(['COMPLETED']), + vnf_instance_filter=json.JSONEncoder().encode({ + 'vnfdIds': ['111'], + 'vnfProductsFromProviders': [], + 'vnfInstanceIds': ['1111'], + 'vnfInstanceNames': [], + }) + ) + t1_apply_grant_result = [0, json.JSONEncoder().encode( { "id": "1", @@ -143,10 +171,12 @@ class TestNFTerminate(TestCase): } ] }), '200'] - t2_lcm_notify_result = [0, json.JSONEncoder().encode(''), '200'] + # t2_lcm_notify_result = [0, json.JSONEncoder().encode(''), '200'] t3_delete_flavor = [0, json.JSONEncoder().encode({"vim_id": "vimid_1"}), '200'] - mock_call_req.side_effect = [t1_apply_grant_result, t2_lcm_notify_result, t3_delete_flavor] + # mock_call_req.side_effect = [t1_apply_grant_result, t2_lcm_notify_result, t3_delete_flavor] + mock_call_req.side_effect = [t1_apply_grant_result, t3_delete_flavor] mock_call.return_value = None + mock_post_notification.return_value = None data = { "terminationType": "FORCEFUL", "gracefulTerminationTimeout": 120 diff --git a/lcm/lcm/pub/msapi/gvnfmdriver.py b/lcm/lcm/pub/msapi/gvnfmdriver.py index a61227f1..13e8dee5 100644 --- a/lcm/lcm/pub/msapi/gvnfmdriver.py +++ b/lcm/lcm/pub/msapi/gvnfmdriver.py @@ -51,7 +51,7 @@ def notify_lcm_to_nfvo(data): return ret[1] -def prepare_notification_data(nfinstid, jobid, changetype): +def prepare_notification_data(nfinstid, jobid, changetype, operation): logger.info('Send notify request to nfvo') affected_vnfcs = [] vnfcs = VNFCInstModel.objects.filter(instid=nfinstid) @@ -122,7 +122,7 @@ def prepare_notification_data(nfinstid, jobid, changetype): 'notificationStatus': 'RESULT', 'operationState': 'COMPLETED', 'vnfInstanceId': nfinstid, - 'operation': 'INSTANTIATE', + 'operation': operation, 'isAutomaticInvocation': False, 'vnfLcmOpOccId': jobid, 'affectedVnfcs': affected_vnfcs, -- 2.16.6