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