682d18b68d75b2835418fc21110ba4328a5d1260
[vfc/gvnfm/vnflcm.git] / lcm / lcm / nf / biz / instantiate_vnf.py
1 # Copyright 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 from threading import Thread
19
20 from lcm.pub.database.models import NfInstModel
21 from lcm.pub.exceptions import NFLCMException
22 from lcm.pub.msapi.gvnfmdriver import prepare_notification_data
23 from lcm.pub.msapi.gvnfmdriver import notify_lcm_to_nfvo
24 from lcm.pub.msapi.sdc_run_catalog import query_vnfpackage_by_id
25 from lcm.pub.utils.jobutil import JobUtil
26 from lcm.pub.utils.timeutil import now_time
27 from lcm.pub.utils.notificationsutil import NotificationsUtil
28 from lcm.pub.utils.values import ignore_case_get
29 from lcm.pub.vimapi import adaptor
30 from lcm.nf.biz.grant_vnf import grant_resource
31 from lcm.nf.const import CHANGE_TYPE, GRANT_TYPE, OPERATION_TYPE
32 from lcm.nf.biz import common
33
34 logger = logging.getLogger(__name__)
35
36
37 class InstantiateVnf(Thread):
38     def __init__(self, data, nf_inst_id, job_id):
39         super(InstantiateVnf, self).__init__()
40         self.data = data
41         self.nf_inst_id = nf_inst_id
42         self.job_id = job_id
43         self.vim_id = ignore_case_get(ignore_case_get(self.data, "additionalParams"), "vimId")
44         self.grant_type = GRANT_TYPE.INSTANTIATE
45
46     def run(self):
47         try:
48             self.inst_pre()
49             self.apply_grant()
50             self.create_res()
51             self.lcm_notify()
52             JobUtil.add_job_status(self.job_id, 100, "Instantiate Vnf success.")
53         except NFLCMException as e:
54             self.vnf_inst_failed_handle(e.message)
55         except Exception as e:
56             logger.error(e.message)
57             logger.error(traceback.format_exc())
58             self.vnf_inst_failed_handle('unexpected exception')
59
60     def inst_pre(self):
61         vnf_insts = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
62         if not vnf_insts.exists():
63             raise NFLCMException('VNF nf_inst_id is not exist.')
64
65         if vnf_insts[0].status != 'NOT_INSTANTIATED':
66             raise NFLCMException('VNF instantiationState is not NOT_INSTANTIATED.')
67
68         JobUtil.add_job_status(self.job_id, 5, 'Get packageinfo by vnfd_id')
69         self.vnfd_id = vnf_insts[0].vnfdid
70         JobUtil.add_job_status(self.job_id, 10, 'Get vnf package info from catalog by csar_id')
71         input_parameters = []
72         inputs = ignore_case_get(self.data, "additionalParams")
73         if inputs:
74             if isinstance(inputs, (str, unicode)):
75                 inputs = json.loads(inputs)
76             for key, val in inputs.items():
77                 input_parameters.append({"key": key, "value": val})
78         vnf_package = query_vnfpackage_by_id(self.vnfd_id)
79         pkg_info = ignore_case_get(vnf_package, "packageInfo")
80         self.vnfd_info = json.loads(ignore_case_get(pkg_info, "vnfdModel"))
81
82         self.update_cps()
83         metadata = ignore_case_get(self.vnfd_info, "metadata")
84         csar_id = ignore_case_get(metadata, "id")
85         version = ignore_case_get(metadata, "vnfdVersion")
86         vendor = ignore_case_get(metadata, "vendor")
87         netype = ignore_case_get(metadata, "type")
88         vnfsoftwareversion = ignore_case_get(metadata, "version")
89         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).\
90             update(package_id=csar_id,
91                    flavour_id=ignore_case_get(self.data, "flavourId"),
92                    version=version,
93                    vendor=vendor,
94                    netype=netype,
95                    vnfd_model=json.dumps(self.vnfd_info),
96                    status='NOT_INSTANTIATED',
97                    vnfdid=self.vnfd_id,
98                    localizationLanguage=ignore_case_get(self.data, 'localizationLanguage'),
99                    input_params=input_parameters,
100                    vnfSoftwareVersion=vnfsoftwareversion,
101                    lastuptime=now_time())
102
103         logger.info("VimId = %s" % self.vim_id)
104         '''
105         is_exist = NfvoRegInfoModel.objects.filter(nfvoid=self.nf_inst_id).exists()
106         if not is_exist:
107             NfvoRegInfoModel.objects.create(
108                 nfvoid=self.nf_inst_id,
109                 vnfminstid=ignore_case_get(self.data, "vnfmId"),
110                 apiurl=self.vim_id)
111         '''
112         JobUtil.add_job_status(self.job_id, 15, 'Nf instancing pre-check finish')
113         logger.info("Nf instancing pre-check finish")
114
115     def apply_grant(self):
116         vdus = ignore_case_get(self.vnfd_info, "vdus")
117         apply_result = grant_resource(data=self.data, nf_inst_id=self.nf_inst_id, job_id=self.job_id,
118                                       grant_type=self.grant_type, vdus=vdus)
119         self.set_location(apply_result)
120
121         logger.info('VnfdInfo = %s' % self.vnfd_info)
122         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status='INSTANTIATED', lastuptime=now_time())
123         JobUtil.add_job_status(self.job_id, 20, 'Nf instancing apply grant finish')
124         logger.info("Nf instancing apply grant finish")
125
126     def create_res(self):
127         logger.info("Create resource start")
128         vim_cache, res_cache = {}, {}
129         adaptor.create_vim_res(self.vnfd_info, self.do_notify, vim_cache=vim_cache, res_cache=res_cache)
130         JobUtil.add_job_status(self.job_id, 70, '[NF instantiation] create resource finish')
131         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).\
132             update(vimInfo=json.dumps(vim_cache),
133                    resInfo=json.dumps(res_cache))
134         logger.info("Create resource finish")
135
136     def lcm_notify(self):
137         notification_content = prepare_notification_data(self.nf_inst_id, self.job_id, CHANGE_TYPE.ADDED, OPERATION_TYPE.INSTANTIATE)
138         logger.info('Notify request data = %s' % notification_content)
139         try:
140             resp = notify_lcm_to_nfvo(json.dumps(notification_content))
141             logger.info('Lcm notify end, response %s' % resp)
142         except Exception as e:
143             logger.error("Lcm instantiate notify failed: %s", e.message)
144         NotificationsUtil().send_notification(notification_content)
145
146     def vnf_inst_failed_handle(self, error_msg):
147         logger.error('VNF instantiation failed, detail message: %s' % error_msg)
148         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status='NOT_INSTANTIATED', lastuptime=now_time())
149         JobUtil.add_job_status(self.job_id, 255, error_msg)
150
151     def do_notify(self, res_type, ret):
152         logger.info('Creating [%s] resource' % res_type)
153         resource_save_method = getattr(common, res_type + '_save')
154         resource_save_method(self.job_id, self.nf_inst_id, ret)
155
156     def update_cps(self):
157         for extlink in ignore_case_get(self.data, "extVirtualLinks"):
158             for ext_cp in ignore_case_get(extlink, "extCps"):
159                 cpdid = ignore_case_get(ext_cp, "cpdId")
160                 for cp in ignore_case_get(self.vnfd_info, "cps"):
161                     if cpdid == ignore_case_get(cp, "cp_id"):
162                         cp["networkId"] = ignore_case_get(extlink, "resourceId")
163                         cp["subnetId"] = ignore_case_get(extlink, "resourceSubnetId")
164                         break
165
166     def set_location(self, apply_result):
167         vim_connections = ignore_case_get(apply_result, "vimConnections")
168         vnfid = ignore_case_get(apply_result, "vnfInstanceId")
169         vim_assets = ignore_case_get(apply_result, "vimAssets")
170         access_info = ignore_case_get(vim_connections[0], "accessInfo")
171         tenant = ignore_case_get(access_info, "tenant")
172         vimid = ignore_case_get(vim_connections[0], "vimId")
173         cloud_owner, cloud_regionid = vimid.split("_")
174         vdu_info = []
175
176         for flavor in ignore_case_get(vim_assets, "computeResourceFlavours"):
177             oof_vimid = flavor["vimConnectionId"]
178             if oof_vimid and oof_vimid != "none":
179                 vimid = oof_vimid
180             vdu_info.append({"vduName": flavor["resourceProviderId"],
181                              "flavorId": flavor["vimFlavourId"],
182                              "vimid": vimid})
183
184         for resource_type in ['vdus', 'vls', 'cps', 'volume_storages']:
185             for resource in ignore_case_get(self.vnfd_info, resource_type):
186                 if "location_info" in resource["properties"]:
187                     resource["properties"]["location_info"]["vimid"] = vimid
188                     resource["properties"]["location_info"]["tenant"] = tenant
189                     resource["properties"]["location_info"]["vnfId"] = vnfid
190                     resource["properties"]["location_info"]["cloudOwner"] = cloud_owner
191                     resource["properties"]["location_info"]["cloudRegionId"] = cloud_regionid
192                     resource["properties"]["location_info"]["vduInfo"] = vdu_info
193                 else:
194                     resource["properties"]["location_info"] = {
195                         "vimid": vimid,
196                         "tenant": tenant,
197                         "vnfId": vnfid,
198                         "cloudOwner": cloud_owner,
199                         "cloudRegionId": cloud_regionid,
200                         "vduInfo": vdu_info}
201
202     '''
203     def get_subnet_ids(self, ext_cp):
204         subnet_ids = []
205         for cp_conf in ignore_case_get(ext_cp, "cpConfig"):
206             for cp_protocol in ignore_case_get(ext_cp, "cpProtocolData"):
207                 ip_over_ethernet = ignore_case_get(cp_protocol, "ipOverEthernet")
208                 for ip_address in ignore_case_get(ip_over_ethernet, "ipAddresses"):
209                     subnet_ids.append(ignore_case_get(ip_address, "subnetId"))
210         return subnet_ids
211     '''