From: maopeng zhang Date: Sat, 26 Aug 2017 07:48:31 +0000 (+0000) Subject: Merge "Fix VFC swagger bug" X-Git-Tag: v1.0.0~130 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=vfc%2Fnfvo%2Flcm.git;a=commitdiff_plain;h=538871695bdd5e55a8a3fdf4886bd804c19f3f87;hp=6064cbde7436bfcba7407b307d390fcdfd045339 Merge "Fix VFC swagger bug" --- diff --git a/lcm/ns/ns_heal.py b/lcm/ns/ns_heal.py index 6973e466..a9cbc324 100644 --- a/lcm/ns/ns_heal.py +++ b/lcm/ns/ns_heal.py @@ -19,7 +19,7 @@ import datetime import time from lcm.ns.const import NS_INST_STATUS -from lcm.pub.database.models import JobModel, NSInstModel +from lcm.pub.database.models import JobModel, NSInstModel, NfInstModel from lcm.ns.vnfs.heal_vnfs import NFHealService from lcm.pub.exceptions import NSLCMException from lcm.pub.utils.jobutil import JobUtil, JOB_MODEL_STATUS @@ -49,13 +49,17 @@ class NSHealService(threading.Thread): def do_biz(self): self.update_job(1, desc='ns heal start') - self.update_ns_status(NS_INST_STATUS.HEALING) self.get_and_check_params() + self.update_ns_status(NS_INST_STATUS.HEALING) self.do_vnfs_heal() self.update_ns_status(NS_INST_STATUS.ACTIVE) self.update_job(100, desc='ns heal success') def get_and_check_params(self): + ns_info = NSInstModel.objects.filter(id=self.ns_instance_id) + if not ns_info: + logger.error('NS [id=%s] does not exist' % self.ns_instance_id) + raise NSLCMException('NS [id=%s] does not exist' % self.ns_instance_id) self.heal_vnf_data = ignore_case_get(self.request_data, 'healVnfData') if not self.heal_vnf_data: logger.error('healVnfData parameter does not exist or value is incorrect.') diff --git a/lcm/ns/ns_instant.py b/lcm/ns/ns_instant.py index 4a64c093..d16ea526 100644 --- a/lcm/ns/ns_instant.py +++ b/lcm/ns/ns_instant.py @@ -21,9 +21,9 @@ import uuid from rest_framework import status from lcm.pub.database.models import DefPkgMappingModel, ServiceBaseInfoModel, InputParamMappingModel -from lcm.pub.database.models import NSInstModel, NfPackageModel, VNFFGInstModel, WFPlanModel -from lcm.pub.msapi.catalog import get_process_id, get_download_url_from_catalog -from lcm.pub.msapi.catalog import query_rawdata_from_catalog, get_servicetemplate_id, get_servicetemplate +from lcm.pub.database.models import NSInstModel, NfPackageModel, VNFFGInstModel, WFPlanModel, NSDModel +from lcm.pub.msapi.catalog import get_process_id, query_rawdata_from_catalog +from lcm.pub.msapi.catalog import get_servicetemplate_id, get_servicetemplate from lcm.pub.msapi.wso2bpel import workflow_run from lcm.pub.msapi.extsys import select_vnfm from lcm.pub.utils.jobutil import JobUtil @@ -33,6 +33,7 @@ from lcm.pub.exceptions import NSLCMException from lcm.pub.config.config import WORKFLOW_OPTION from lcm.workflows import build_in from lcm.pub.msapi import activiti +from lcm.pub.utils import toscaparser logger = logging.getLogger(__name__) @@ -61,9 +62,15 @@ class InstantNSService(object): location_constraints = self.req_data['locationConstraints'] JobUtil.add_job_status(job_id, 5, 'Start query nsd(%s)' % ns_inst.nspackage_id) - src_plan = query_rawdata_from_catalog(ns_inst.nspackage_id, input_parameters) - dst_plan = toscautil.convert_nsd_model(src_plan["rawData"]) + dst_plan = None + if WORKFLOW_OPTION == "wso2": + src_plan = query_rawdata_from_catalog(ns_inst.nspackage_id, input_parameters) + dst_plan = toscautil.convert_nsd_model(src_plan["rawData"]) + else: + nsd_pkg = NSDModel.objects.get(id=ns_inst.nspackage_id) + dst_plan = toscaparser.parse_nsd(nsd_pkg.nsd_path, input_parameters) logger.debug('tosca plan dest:%s' % dst_plan) + NSInstModel.objects.filter(id=self.ns_inst_id).update(nsd_model=dst_plan) params_json = json.JSONEncoder().encode(self.req_data["additionalParamForNs"]) @@ -112,11 +119,15 @@ class InstantNSService(object): creator='--', create_time=int(time.time()*1000)).save() - service_tpl = get_servicetemplate(ns_inst.nsd_id) - DefPkgMappingModel(service_id=self.ns_inst_id, - service_def_id=service_tpl['csarId'], - template_name=service_tpl['templateName'], - template_id=service_tpl['serviceTemplateId']).save() + if WORKFLOW_OPTION == "wso2": + service_tpl = get_servicetemplate(ns_inst.nsd_id) + DefPkgMappingModel(service_id=self.ns_inst_id, + service_def_id=service_tpl['csarId'], + template_name=service_tpl['templateName'], + template_id=service_tpl['serviceTemplateId']).save() + else: + # TODO: + pass for key, val in self.req_data['additionalParamForNs'].items(): InputParamMappingModel(service_id=self.ns_inst_id, diff --git a/lcm/ns/tests/test_ns_heal.py b/lcm/ns/tests/test_ns_heal.py index 87cd174d..0d77dbc0 100644 --- a/lcm/ns/tests/test_ns_heal.py +++ b/lcm/ns/tests/test_ns_heal.py @@ -13,48 +13,85 @@ # limitations under the License. import mock -import uuid + from rest_framework import status from django.test import TestCase from django.test import Client -from lcm.pub.database.models import NSDModel, NSInstModel +from lcm.pub.database.models import NSInstModel, NfInstModel from lcm.pub.utils.jobutil import JobUtil, JOB_TYPE from lcm.ns.const import NS_INST_STATUS from lcm.pub.utils import restcall +from lcm.pub.exceptions import NSLCMException from lcm.ns.ns_heal import NSHealService class TestHealNsViews(TestCase): def setUp(self): - self.nsd_id = str(uuid.uuid4()) - self.ns_package_id = str(uuid.uuid4()) - self.ns_inst_id = str(uuid.uuid4()) + + self.ns_inst_id = '1' + self.nf_inst_id = '1' + self.nf_uuid = '1-1-1' + self.job_id = JobUtil.create_job("NS", JOB_TYPE.HEAL_VNF, self.ns_inst_id) - NSDModel(id=self.ns_package_id, nsd_id=self.nsd_id, name='name').save() self.client = Client() - self.context = '{"vnfs": ["a", "b"], "sfcs": ["c"], "vls": ["d", "e", "f"]}' - NSInstModel(id=self.ns_inst_id, name="abc", nspackage_id="7", nsd_id="111").save() + + model = '{"metadata": {"vnfdId": "1","vnfdName": "PGW001","vnfProvider": "zte","vnfdVersion": "V00001",' \ + '"vnfVersion": "V5.10.20","productType": "CN","vnfType": "PGW",' \ + '"description": "PGW VNFD description","isShared":true,"vnfExtendType":"driver"}}' + NSInstModel(id=self.ns_inst_id, name="ns_name", status='null').save() + NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1', + vnfm_inst_id='1', ns_inst_id=self.ns_inst_id, + max_cpu='14', max_ram='12296', max_hd='101', max_shd="20", max_net=10, + status='null', mnfinstid=self.nf_uuid, package_id='pkg1', + vnfd_model=model) def tearDown(self): NSInstModel.objects.filter().delete() + NfInstModel.objects.filter().delete() @mock.patch.object(NSHealService, 'run') - def test_ns_heal(self, mock_run): + def test_heal_vnf_url(self, mock_run): data = { - 'nsdid': self.nsd_id, - 'nsname': 'ns', - 'description': 'description'} - response = self.client.post("/api/nslcm/v1/ns/%s/heal" % self.nsd_id, data=data) - self.failUnlessEqual(status.HTTP_202_ACCEPTED, response.status_code) + "healVnfData": { + "vnfInstanceId": self.nf_inst_id, + "cause": "vm is down", + "additionalParams": { + "action": "restartvm", + "actionvminfo": { + "vmid": "33", + "vmname": "xgw-smp11" + } + } + } + } + + response = self.client.post("/api/nslcm/v1/ns/%s/heal" % self.ns_inst_id, data=data) + self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code) + self.assertIsNotNone(response.data) + self.assertIn("jobId", response.data) + self.assertNotIn("error", response.data) - @mock.patch.object(restcall, 'call_req') - def test_ns_heal_thread(self, mock_call): + response = self.client.delete("/api/nslcm/v1/ns/%s" % self.ns_inst_id) + self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) + + @mock.patch.object(NSHealService, 'start') + @mock.patch.object(NSHealService, 'wait_job_finish') + @mock.patch.object(NSHealService, 'update_job') + def test_ns_manual_scale_thread(self, mock_start, mock_wait, mock_update): data = { - 'nsdid': self.nsd_id, - 'nsname': 'ns', - 'description': 'description' + "healVnfData": { + "vnfInstanceId": self.nf_inst_id, + "cause": "vm is down", + "additionalParams": { + "action": "restartvm", + "actionvminfo": { + "vmid": "33", + "vmname": "xgw-smp11" + } + } + } } NSHealService(self.ns_inst_id, data, self.job_id).run() @@ -63,3 +100,39 @@ class TestHealNsViews(TestCase): def test_swagger_ok(self): resp = self.client.get("/api/nslcm/v1/swagger.json", format='json') self.assertEqual(resp.status_code, status.HTTP_200_OK) + + @mock.patch.object(NSHealService, "start") + def test_ns_heal_non_existing_ns(self, mock_start): + mock_start.side_effect = NSLCMException("NS Not Found") + + ns_inst_id = "2" + + data = { + "healVnfData": { + "vnfInstanceId": self.nf_inst_id, + "cause": "vm is down", + "additionalParams": { + "action": "restartvm", + "actionvminfo": { + "vmid": "33", + "vmname": "xgw-smp11" + } + } + } + } + + response = self.client.post("/api/nslcm/v1/ns/%s/heal" % ns_inst_id, data=data) + self.assertEqual(response.data["error"], "NS Not Found") + self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR) + self.assertIn("error", response.data) + + @mock.patch.object(NSHealService, "start") + def test_ns_heal_empty_post(self, mock_start): + mock_start.side_effect = NSLCMException("healVnfData parameter does not exist or value is incorrect.") + + data = {} + + response = self.client.post("/api/nslcm/v1/ns/%s/heal" % self.ns_inst_id, data=data) + self.assertEqual(response.data["error"], "healVnfData parameter does not exist or value is incorrect.") + self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR) + self.assertIn("error", response.data) diff --git a/lcm/ns/tests/vnfs/tests.py b/lcm/ns/tests/vnfs/tests.py index 4b78963b..73cecd96 100644 --- a/lcm/ns/tests/vnfs/tests.py +++ b/lcm/ns/tests/vnfs/tests.py @@ -30,6 +30,7 @@ from lcm.ns.vnfs.terminate_nfs import TerminateVnfs from lcm.ns.vnfs.scale_vnfs import NFManualScaleService from lcm.ns.vnfs.heal_vnfs import NFHealService from lcm.pub.utils.jobutil import JobUtil, JOB_TYPE +from lcm.pub.exceptions import NSLCMException class TestGetVnfViews(TestCase): @@ -308,6 +309,8 @@ class TestHealVnfViews(TestCase): self.nf_inst_id = str(uuid.uuid4()) self.nf_uuid = '111' + self.job_id = JobUtil.create_job("VNF", JOB_TYPE.HEAL_VNF, self.nf_inst_id) + NSInstModel(id=self.ns_inst_id, name="ns_name").save() NfInstModel.objects.create(nfinstid=self.nf_inst_id, nf_name='name_1', vnf_id='1', vnfm_inst_id='1', ns_inst_id='111,2-2-2', @@ -326,21 +329,63 @@ class TestHealVnfViews(TestCase): @mock.patch.object(restcall, "call_req") def test_heal_vnf(self, mock_call_req): + + mock_vals = { + "/api/ztevmanagerdriver/v1/1/vnfs/111/heal": + [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'], + "/api/extsys/v1/vnfms/1": + [0, json.JSONEncoder().encode({"name": 'vnfm1', "type": 'ztevmanagerdriver'}), '200'], + "/api/resmgr/v1/vnf/1": + [0, json.JSONEncoder().encode({"jobId": self.job_id}), '200'], + "/api/ztevmanagerdriver/v1/1/jobs/" + self.job_id + "?responseId=0": + [0, json.JSONEncoder().encode({"jobId": self.job_id, + "responsedescriptor": {"progress": "100", + "status": JOB_MODEL_STATUS.FINISHED, + "responseid": "3", + "statusdescription": "creating", + "errorcode": "0", + "responsehistorylist": [ + {"progress": "0", + "status": JOB_MODEL_STATUS.PROCESSING, + "responseid": "2", + "statusdescription": "creating", + "errorcode": "0"}]}}), '200']} + + def side_effect(*args): + return mock_vals[args[4]] + + mock_call_req.side_effect = side_effect + req_data = { "action": "vmReset", "affectedvm": { - "vmid": 1, - "vduid": 1, + "vmid": "1", + "vduid": "1", "vmname": "name", } } - NFHealService(self.ns_inst_id, req_data).run() - nsIns = NfInstModel.objects.filter(nfinstid=self.nf_inst_id) - if nsIns: - self.failUnlessEqual(1, 1) - else: - self.failUnlessEqual(1, 0) + NFHealService(self.nf_inst_id, req_data).run() + + self.assertEqual(NfInstModel.objects.get(nfinstid=self.nf_inst_id).status, VNF_STATUS.ACTIVE) + + @mock.patch.object(NFHealService, "run") + def test_heal_vnf_non_existing_vnf(self, mock_biz): + mock_biz.side_effect = NSLCMException("VNF Not Found") + + nf_inst_id = "1" + + req_data = { + "action": "vmReset", + "affectedvm": { + "vmid": "1", + "vduid": "1", + "vmname": "name", + } + } + + self.assertRaises(NSLCMException, NFHealService(nf_inst_id, req_data).run) + self.assertEqual(len(NfInstModel.objects.filter(nfinstid=nf_inst_id)), 0) vnfd_model_dict = { 'local_storages': [], diff --git a/lcm/ns/vnfs/heal_vnfs.py b/lcm/ns/vnfs/heal_vnfs.py index a8a1ed69..d6ad1527 100644 --- a/lcm/ns/vnfs/heal_vnfs.py +++ b/lcm/ns/vnfs/heal_vnfs.py @@ -54,8 +54,8 @@ class NFHealService(threading.Thread): def do_biz(self): self.update_job(1, desc='nf heal start') - self.update_nf_status(VNF_STATUS.HEALING) self.get_and_check_params() + self.update_nf_status(VNF_STATUS.HEALING) self.send_nf_healing_request() self.update_nf_status(VNF_STATUS.ACTIVE) self.update_job(100, desc='nf heal success') diff --git a/lcm/packages/tests/test_nf.py b/lcm/packages/tests/test_nf.py index 8e7bad03..2e922d4f 100644 --- a/lcm/packages/tests/test_nf.py +++ b/lcm/packages/tests/test_nf.py @@ -165,7 +165,7 @@ class TestNfPackage(TestCase): "vimIds": ["1"] }, format='json') self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED) -""" + @mock.patch.object(restcall, 'call_req') def test_nf_pkg_on_boarding_when_on_boarded(self, mock_call_req): mock_call_req.return_value = [0, json.JSONEncoder().encode({"onBoardState": "onBoarded"}), '200'] @@ -190,7 +190,7 @@ class TestNfPackage(TestCase): @mock.patch.object(restcall, 'call_req') def test_nf_on_boarding_when_nfd_already_exists(self, mock_call_req): mock_vals = { - "/api/catalog/v0/csars/2": + "/api/catalog/v1/csars/2": [0, json.JSONEncoder().encode({ "onBoardState": "onBoardFailed", "processState": "deleteFailed"}), '200'], "/api/catalog/v1/servicetemplates/queryingrawdata": @@ -467,5 +467,5 @@ class TestNfPackage(TestCase): self.assertEqual(1, len(resp.data["csars"])) self.assertEqual("1", resp.data["csars"][0]["csarId"]) self.assertEqual("2", resp.data["csars"][0]["vnfdId"]) -""" + diff --git a/lcm/packages/tests/test_sdc_nf.py b/lcm/packages/tests/test_sdc_nf.py index 1747be01..1ae8e134 100644 --- a/lcm/packages/tests/test_sdc_nf.py +++ b/lcm/packages/tests/test_sdc_nf.py @@ -254,7 +254,7 @@ class TestNfPackage(TestCase): "vimIds": ["1"] }, format='json') self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED) - """ + def test_nf_pkg_distribute_when_csar_already_exist(self): NfPackageModel(uuid="1", nfpackageid="1", vnfdid="vcpe_vfw_zte_1_0").save() SdcNfDistributeThread(csar_id="1", @@ -297,7 +297,6 @@ class TestNfPackage(TestCase): lab_vim_id="", job_id="4").run() self.assert_job_result("4", 100, "CSAR(1) distribute successfully.") - """ ############################################################################################################### @@ -305,7 +304,7 @@ class TestNfPackage(TestCase): def test_nf_pkg_delete_normal(self, mock_run): resp = self.client.delete("/api/nslcm/v1/vnfpackage/1") self.assertEqual(resp.status_code, status.HTTP_202_ACCEPTED) - """ + def test_nf_pkg_normal_delete(self): NfPackageModel(uuid="2", nfpackageid="2", vnfdid="vcpe_vfw_zte_1_0").save() SdcNfPkgDeleteThread(csar_id="2", job_id="2", force_delete=False).run() @@ -322,7 +321,6 @@ class TestNfPackage(TestCase): NfInstModel(nfinstid="3", package_id="3").save() SdcNfPkgDeleteThread(csar_id="3", job_id="2", force_delete=False).run() self.assert_job_result("2", 255, "NfInst by csar(3) exists, cannot delete.") - """ def test_nf_pkg_get_all(self): NfPackageModel(uuid="3", nfpackageid="3", vnfdid="4").save() diff --git a/lcm/pub/utils/toscaparser/vnfdmodel.py b/lcm/pub/utils/toscaparser/vnfdmodel.py index eac1f0b7..cf29ea68 100644 --- a/lcm/pub/utils/toscaparser/vnfdmodel.py +++ b/lcm/pub/utils/toscaparser/vnfdmodel.py @@ -17,6 +17,7 @@ class EtsiVnfdInfoModel(EtsiNsdInfoModel): tosca.nodetemplates) self.services = self._get_all_services(nodeTemplates) + self.vcloud = self._get_all_vcloud(nodeTemplates) def _get_all_services(self, nodeTemplates): @@ -33,4 +34,24 @@ class EtsiVnfdInfoModel(EtsiNsdInfoModel): service['networks'] = map(lambda x: self.get_requirement_node_name(x), self.getVirtualLinks(node)) ret.append(service) - return ret \ No newline at end of file + return ret + + def _get_all_vcloud(self, nodeTemplates): + rets = [] + for node in nodeTemplates: + if self._isVcloud(node): + ret = {} + if 'vdc_name' in node['properties']: + ret['vdc_name'] = node['properties']['vdc_name'] + else: + ret['vdc_name'] = "" + if 'storage_clusters' in node['properties']: + ret['storage_clusters'] = node['properties']['storage_clusters'] + else: + ret['storage_clusters'] = [] + + rets.append(ret) + return rets + + def _isVcloud(self, node): + return node['nodeType'].upper().find('.VCLOUD.') >= 0 or node['nodeType'].upper().endswith('.VCLOUD') \ No newline at end of file