Add seed codes of nfvo
[vfc/nfvo/lcm.git] / lcm / ns / ns_instant.py
1 # Copyright 2016-2017 ZTE Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import json
16 import logging
17 import traceback
18 import time
19 import uuid
20
21 from rest_framework import status
22
23 from lcm.pub.database.models import DefPkgMappingModel, ServiceBaseInfoModel, InputParamMappingModel
24 from lcm.pub.database.models import NSInstModel, NfPackageModel, VNFFGInstModel
25 from lcm.pub.msapi.catalog import get_process_id, get_download_url_from_catalog
26 from lcm.pub.msapi.catalog import query_rawdata_from_catalog, get_servicetemplate_id, get_servicetemplate
27 from lcm.pub.msapi.wso2bpel import workflow_run
28 from lcm.pub.msapi.extsys import select_vnfm
29 from lcm.pub.utils.jobutil import JobUtil
30 from lcm.pub.utils import toscautil
31 from lcm.pub.utils.values import ignore_case_get
32 from lcm.pub.exceptions import NSLCMException
33
34 logger = logging.getLogger(__name__)
35
36
37 class InstantNSService(object):
38     def __init__(self, ns_inst_id, plan_content):
39         self.ns_inst_id = ns_inst_id
40         self.req_data = plan_content
41
42     def do_biz(self):
43         try:
44             job_id = JobUtil.create_job("NS", "NS_INST", self.ns_inst_id)
45             logger.debug('ns-instant(%s) workflow starting...' % self.ns_inst_id)
46             logger.debug('req_data=%s' % self.req_data)
47             ns_inst = NSInstModel.objects.get(id=self.ns_inst_id)
48
49             input_parameters = []
50             for key, val in self.req_data['additionalParamForNs'].items():
51                 input_parameters.append({"key": key, "value": val})
52
53             vim_id = ''
54             if 'location' in self.req_data['additionalParamForNs']:
55                 vim_id = self.req_data['additionalParamForNs']['location']
56             location_constraints = []
57             if 'locationConstraints' in self.req_data:
58                 location_constraints = self.req_data['locationConstraints']
59             
60             JobUtil.add_job_status(job_id, 5, 'Start query nsd(%s)' % ns_inst.nspackage_id)
61             src_plan = query_rawdata_from_catalog(ns_inst.nspackage_id, input_parameters)
62             dst_plan = toscautil.convert_nsd_model(src_plan["rawData"])
63             logger.debug('tosca plan dest:%s' % dst_plan)
64             NSInstModel.objects.filter(id=self.ns_inst_id).update(nsd_model=dst_plan)
65
66             params_json = json.JSONEncoder().encode(self.req_data["additionalParamForNs"])
67             # start
68             params_vnf = []
69             plan_dict = json.JSONDecoder().decode(dst_plan)
70             for vnf in ignore_case_get(plan_dict, "vnfs"):
71                 vnfd_id = vnf['properties']['id']
72                 vnfd = NfPackageModel.objects.get(vnfdid=vnfd_id)
73                 vnfd_model = json.JSONDecoder().decode(vnfd.vnfdmodel)
74                 vnfm_type = vnfd_model["metadata"].get("vnfmType", "ztevmanagerdriver")
75                 vimid = self.get_vnf_vim_id(vim_id, location_constraints, vnfd_id)
76                 vnfm_info = select_vnfm(vnfm_type=vnfm_type, vim_id=vimid)
77                 params_vnf.append({
78                     "vnfProfileId": vnf["vnf_id"],
79                     "additionalParam": {
80                         "vimId": vimid,
81                         "vnfmInstanceId": vnfm_info["vnfmId"],
82                         "vnfmType": vnfm_type,
83                         "inputs": params_json
84                     }
85                 })
86             # end
87             
88             self.set_vl_vim_id(vim_id, location_constraints, plan_dict)
89             dst_plan = json.JSONEncoder().encode(plan_dict)
90             logger.debug('tosca plan dest add vimid:%s' % dst_plan)
91             NSInstModel.objects.filter(id=self.ns_inst_id).update(nsd_model=dst_plan)
92             
93             vnf_params_json = json.JSONEncoder().encode(params_vnf)
94             plan_input = {'jobId': job_id, 
95                 'nsInstanceId': self.req_data["nsInstanceId"],
96                 'object_context': dst_plan,
97                 'object_additionalParamForNs': params_json,
98                 'object_additionalParamForVnf': vnf_params_json}
99             plan_input.update(**self.get_model_count(dst_plan))
100             plan_input["sdnControllerId"] = ignore_case_get(
101                 self.req_data['additionalParamForNs'], "sdncontroller")
102
103             ServiceBaseInfoModel(service_id=self.ns_inst_id,
104                                  service_name=ns_inst.name,
105                                  service_type='NFVO',
106                                  description=ns_inst.description,
107                                  active_status='--',
108                                  status=ns_inst.status,
109                                  creator='--',
110                                  create_time=int(time.time()*1000)).save()
111
112             service_tpl = get_servicetemplate(ns_inst.nsd_id)
113             DefPkgMappingModel(service_id=self.ns_inst_id,
114                                service_def_id=service_tpl['csarId'],
115                                template_name=service_tpl['templateName'],
116                                template_id=service_tpl['serviceTemplateId']).save()
117
118             for key, val in self.req_data['additionalParamForNs'].items():
119                 InputParamMappingModel(service_id=self.ns_inst_id,
120                     input_key=key, input_value=val).save()
121
122             for vnffg in ignore_case_get(plan_dict, "vnffgs"):
123                 VNFFGInstModel(vnffgdid=vnffg["vnffg_id"],
124                     vnffginstid=str(uuid.uuid4()),
125                     nsinstid=self.ns_inst_id,
126                     endpointnumber=0).save()
127
128             servicetemplate_id = get_servicetemplate_id(ns_inst.nsd_id)
129             process_id = get_process_id('init', servicetemplate_id)
130             data = {"processId": process_id, "params": {"planInput": plan_input}}
131             logger.debug('ns-instant(%s) workflow data:%s' % (self.ns_inst_id, data))
132
133             ret = workflow_run(data)
134             logger.info("ns-instant(%s) workflow result:%s" % (self.ns_inst_id, ret))
135             JobUtil.add_job_status(job_id, 10, 'NS inst(%s) workflow started: %s' % (
136                 self.ns_inst_id, ret.get('status')))
137             if ret.get('status') == 1:
138                 return dict(data={'jobId': job_id}, status=status.HTTP_200_OK)
139             return dict(data={'error': ret['message']}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
140         except Exception as e:
141             logger.error(traceback.format_exc())
142             logger.error("ns-instant(%s) workflow error:%s" % (self.ns_inst_id, e.message))
143             JobUtil.add_job_status(job_id, 255, 'NS instantiation failed: %s' % e.message)
144             return dict(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
145             
146     def get_vnf_vim_id(self, vim_id, location_constraints, vnfdid):
147         for location in location_constraints:
148             if "vnfProfileId" in location and vnfdid == location["vnfProfileId"]:
149                 return location["locationConstraints"]["vimId"]
150         if vim_id:
151             return vim_id
152         raise NSLCMException("No Vim info is found for vnf(%s)." % vnfdid)
153         
154     def set_vl_vim_id(self, vim_id, location_constraints, plan_dict):
155         if "vls" not in plan_dict:
156             logger.debug("No vl is found in nsd.")
157             return
158         vl_vnf = {}
159         for vnf in ignore_case_get(plan_dict, "vnfs"):
160             if "dependencies" in vnf:
161                 for depend in vnf["dependencies"]:
162                     vl_vnf[depend["vl_id"]] = vnf['properties']['id']
163         vnf_vim = {}
164         for location in location_constraints:
165             if "vnfProfileId" in location:
166                 vnfd_id = location["vnfProfileId"]
167                 vnf_vim[vnfd_id] = location["locationConstraints"]["vimId"]
168         for vl in plan_dict["vls"]:
169             vnfdid = ignore_case_get(vl_vnf, vl["vl_id"])
170             vimid = ignore_case_get(vnf_vim, vnfdid)
171             if not vimid:
172                 vimid = vim_id
173             if not vimid:
174                 raise NSLCMException("No Vim info for vl(%s) of vnf(%s)." % (vl["vl_id"], vnfdid))
175             if "location_info" not in vl["properties"]:
176                 vl["properties"]["location_info"] = {}
177             vl["properties"]["location_info"]["vimid"] = vimid
178        
179     @staticmethod
180     def get_model_count(context):
181         data = json.JSONDecoder().decode(context)
182         vls = len(data.get('vls', []))
183         sfcs = len(data.get('fps', []))
184         vnfs = len(data.get('vnfs', []))
185         return {'vlCount': str(vls), 'sfcCount': str(sfcs), 'vnfCount': str(vnfs)}