rollback code in vnflcm\lcm\lcm\nf\biz\instantiate_vnf.py
[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.exceptions import NFLCMExceptionConflict
23 from lcm.pub.msapi.gvnfmdriver import prepare_notification_data
24 from lcm.pub.msapi.gvnfmdriver import notify_lcm_to_nfvo
25 from lcm.pub.msapi.sdc_run_catalog import query_vnfpackage_by_id
26 from lcm.pub.utils.jobutil import JobUtil
27 from lcm.pub.utils.timeutil import now_time
28 from lcm.pub.utils.notificationsutil import NotificationsUtil
29 from lcm.pub.utils.values import ignore_case_get
30 from lcm.pub.vimapi import adaptor
31 from lcm.nf.biz.grant_vnf import grant_resource
32 from lcm.nf.const import CHANGE_TYPE, GRANT_TYPE, OPERATION_TYPE
33 from lcm.nf.const import OPERATION_TASK
34 from lcm.nf.const import OPERATION_STATE_TYPE
35 from lcm.nf.const import SUB_OPERATION_TASK
36 from lcm.nf.biz import common
37 from .operate_vnf_lcm_op_occ import VnfLcmOpOcc
38
39 logger = logging.getLogger(__name__)
40
41
42 class InstantiateVnf(Thread):
43     def __init__(self, data, nf_inst_id, job_id):
44         super(InstantiateVnf, self).__init__()
45         self.data = data
46         self.nf_inst_id = nf_inst_id
47         self.job_id = job_id
48         self.vim_id = ignore_case_get(
49             ignore_case_get(
50                 self.data,
51                 "additionalParams"
52             ),
53             "vimId"
54         )
55         self.grant_type = GRANT_TYPE.INSTANTIATE
56         self.lcm_op_occ = VnfLcmOpOcc(
57             vnf_inst_id=nf_inst_id,
58             lcm_op_id=job_id,
59             operation=OPERATION_TYPE.INSTANTIATE,
60             task=OPERATION_TASK.INSTANTIATE
61         )
62         self.pre_deal()
63
64     def run(self):
65         try:
66             self.inst_pre()
67             self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.STARTING)
68             self.apply_grant()
69             self.lcm_op_occ.upd(
70                 sub_operation=SUB_OPERATION_TASK.GRANTED,
71                 operation_state=OPERATION_STATE_TYPE.PROCESSING
72             )
73             self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.PROCESSING)
74             self.create_res()
75             self.lcm_notify()
76             JobUtil.add_job_status(
77                 self.job_id,
78                 100,
79                 "Instantiate Vnf success."
80             )
81             self.lcm_op_occ.upd(
82                 sub_operation=SUB_OPERATION_TASK.SUCCESS,
83                 operation_state=OPERATION_STATE_TYPE.COMPLETED
84             )
85         except NFLCMException as e:
86             self.vnf_inst_failed_handle(e.args[0])
87         except NFLCMExceptionConflict as e:
88             self.vnf_inst_failed_handle(e.args[0])
89         except Exception as e:
90             logger.error(str(e))
91             logger.error(traceback.format_exc())
92             self.vnf_inst_failed_handle('unexpected exception')
93
94     def pre_deal(self):
95         logger.debug("Start pre deal for VNF instantiate_vnf task")
96
97         vnf_is_in_processing, vnf_op = self.lcm_op_occ.is_in_processing()
98         if vnf_is_in_processing:
99             raise NFLCMExceptionConflict('VNF(%s) %s in processing.' % (
100                 self.nf_inst_id, vnf_op
101             ))
102         self.lcm_op_occ.add()
103
104     def inst_pre(self):
105         vnf_insts = NfInstModel.objects.filter(nfinstid=self.nf_inst_id)
106         if not vnf_insts.exists():
107             raise NFLCMException('VNF nf_inst_id is not exist.')
108
109         if vnf_insts[0].status != 'NOT_INSTANTIATED':
110             raise NFLCMException('VNF instantiationState is not NOT_INSTANTIATED.')
111
112         JobUtil.add_job_status(self.job_id, 5, 'Get packageinfo by vnfd_id')
113         self.vnfd_id = vnf_insts[0].vnfdid
114         JobUtil.add_job_status(self.job_id, 10, 'Get vnf package info from catalog by csar_id')
115         input_parameters = []
116         inputs = ignore_case_get(self.data, "additionalParams")
117         if inputs:
118             if isinstance(inputs, str):
119                 inputs = json.loads(inputs)
120             for key, val in list(inputs.items()):
121                 input_parameters.append({"key": key, "value": val})
122         vnf_package = query_vnfpackage_by_id(self.vnfd_id)
123         pkg_info = ignore_case_get(vnf_package, "packageInfo")
124         self.vnfd_info = json.loads(ignore_case_get(pkg_info, "vnfdModel"))
125
126         self.update_cps()
127         metadata = ignore_case_get(self.vnfd_info, "metadata")
128         csar_id = ignore_case_get(metadata, "id")
129         version = ignore_case_get(metadata, "vnfdVersion")
130         vendor = ignore_case_get(metadata, "vendor")
131         netype = ignore_case_get(metadata, "type")
132         vnfsoftwareversion = ignore_case_get(metadata, "version")
133         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).\
134             update(package_id=csar_id,
135                    flavour_id=ignore_case_get(self.data, "flavourId"),
136                    version=version,
137                    vendor=vendor,
138                    netype=netype,
139                    vnfd_model=json.dumps(self.vnfd_info),
140                    status='NOT_INSTANTIATED',
141                    vnfdid=self.vnfd_id,
142                    localizationLanguage=ignore_case_get(self.data, 'localizationLanguage'),
143                    input_params=input_parameters,
144                    vnfSoftwareVersion=vnfsoftwareversion,
145                    lastuptime=now_time())
146
147         logger.info("VimId = %s" % self.vim_id)
148         '''
149         is_exist = NfvoRegInfoModel.objects.filter(nfvoid=self.nf_inst_id).exists()
150         if not is_exist:
151             NfvoRegInfoModel.objects.create(
152                 nfvoid=self.nf_inst_id,
153                 vnfminstid=ignore_case_get(self.data, "vnfmId"),
154                 apiurl=self.vim_id)
155         '''
156         JobUtil.add_job_status(self.job_id, 15, 'Nf instancing pre-check finish')
157         logger.info("Nf instancing pre-check finish")
158
159     def apply_grant(self):
160         vdus = ignore_case_get(self.vnfd_info, "vdus")
161         apply_result = grant_resource(data=self.data,
162                                       nf_inst_id=self.nf_inst_id,
163                                       job_id=self.job_id,
164                                       grant_type=self.grant_type,
165                                       vdus=vdus)
166         self.set_location(apply_result)
167
168         logger.info('VnfdInfo = %s' % self.vnfd_info)
169         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(
170             status='INSTANTIATED',
171             lastuptime=now_time()
172         )
173         JobUtil.add_job_status(self.job_id, 20, 'Nf instancing apply grant finish')
174         logger.info("Nf instancing apply grant finish")
175
176     def create_res(self):
177         logger.info("Create resource start")
178         vim_cache, res_cache = {}, {}
179         adaptor.create_vim_res(
180             self.vnfd_info,
181             self.do_notify,
182             vim_cache=vim_cache,
183             res_cache=res_cache
184         )
185         JobUtil.add_job_status(self.job_id, 70, '[NF instantiation] create resource finish')
186         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).\
187             update(vimInfo=json.dumps(vim_cache),
188                    resInfo=json.dumps(res_cache))
189         logger.info("Create resource finish")
190
191     def lcm_notify(self):
192         notification_content = prepare_notification_data(
193             self.nf_inst_id,
194             self.job_id,
195             CHANGE_TYPE.ADDED,
196             OPERATION_TYPE.INSTANTIATE
197         )
198         logger.info('Notify request data = %s' % notification_content)
199         try:
200             resp = notify_lcm_to_nfvo(json.dumps(notification_content))
201             logger.info('Lcm notify end, response %s' % resp)
202         except Exception as e:
203             logger.error("Lcm instantiate notify failed: %s", e.args[0])
204         NotificationsUtil().send_notification(notification_content)
205
206     def vnf_inst_failed_handle(self, error_msg):
207         logger.error('VNF instantiation failed, detail message: %s' % error_msg)
208         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(
209             status='NOT_INSTANTIATED',
210             lastuptime=now_time()
211         )
212         self.lcm_op_occ.notify_lcm(OPERATION_STATE_TYPE.FAILED, error_msg)
213         JobUtil.add_job_status(self.job_id, 255, error_msg)
214         self.lcm_op_occ.upd(
215             sub_operation=SUB_OPERATION_TASK.ERROR,
216             operation_state=OPERATION_STATE_TYPE.FAILED,
217             error={
218                 "status": 500,
219                 "detail": error_msg
220             }
221         )
222
223     def do_notify(self, res_type, ret):
224         logger.info('Creating [%s] resource' % res_type)
225         resource_save_method = getattr(common, res_type + '_save')
226         resource_save_method(self.job_id, self.nf_inst_id, ret)
227
228     def update_cps(self):
229         for extlink in ignore_case_get(self.data, "extVirtualLinks"):
230             for ext_cp in ignore_case_get(extlink, "extCps"):
231                 cpdid = ignore_case_get(ext_cp, "cpdId")
232                 for cp in ignore_case_get(self.vnfd_info, "cps"):
233                     if cpdid == ignore_case_get(cp, "cp_id"):
234                         cp["networkId"] = ignore_case_get(extlink, "resourceId")
235                         cp["subnetId"] = ignore_case_get(extlink, "resourceSubnetId")
236                         break
237
238     def set_location(self, apply_result):
239         vim_connections = ignore_case_get(apply_result, "vimConnections")
240         vnfid = ignore_case_get(apply_result, "vnfInstanceId")
241         vim_assets = ignore_case_get(apply_result, "vimAssets")
242         access_info = ignore_case_get(vim_connections[0], "accessInfo")
243         tenant = ignore_case_get(access_info, "tenant")
244         vimid = ignore_case_get(vim_connections[0], "vimId")
245         cloud_owner, cloud_regionid = vimid.split("_")
246         vdu_info = []
247
248         for flavor in ignore_case_get(vim_assets, "computeResourceFlavours"):
249             oof_vimid = flavor["vimConnectionId"]
250             if oof_vimid and oof_vimid != "none":
251                 vimid = oof_vimid
252             vdu_info.append({"vduName": flavor["resourceProviderId"],
253                              "flavorId": flavor["vimFlavourId"],
254                              "vimid": vimid})
255
256         for resource_type in ['vdus', 'vls', 'cps', 'volume_storages']:
257             for resource in ignore_case_get(self.vnfd_info, resource_type):
258                 if "location_info" in resource["properties"]:
259                     resource["properties"]["location_info"]["vimid"] = vimid
260                     resource["properties"]["location_info"]["tenant"] = tenant
261                     resource["properties"]["location_info"]["vnfId"] = vnfid
262                     resource["properties"]["location_info"]["cloudOwner"] = cloud_owner
263                     resource["properties"]["location_info"]["cloudRegionId"] = cloud_regionid
264                     resource["properties"]["location_info"]["vduInfo"] = vdu_info
265                 else:
266                     resource["properties"]["location_info"] = {
267                         "vimid": vimid,
268                         "tenant": tenant,
269                         "vnfId": vnfid,
270                         "cloudOwner": cloud_owner,
271                         "cloudRegionId": cloud_regionid,
272                         "vduInfo": vdu_info}
273
274     '''
275     def get_subnet_ids(self, ext_cp):
276         subnet_ids = []
277         for cp_conf in ignore_case_get(ext_cp, "cpConfig"):
278             for cp_protocol in ignore_case_get(ext_cp, "cpProtocolData"):
279                 ip_over_ethernet = ignore_case_get(cp_protocol, "ipOverEthernet")
280                 for ip_address in ignore_case_get(ip_over_ethernet, "ipAddresses"):
281                     subnet_ids.append(ignore_case_get(ip_address, "subnetId"))
282         return subnet_ids
283     '''