Add Heal Api in GVNFM
[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         # resp = notify_lcm_to_nfvo(json.dumps(notification_content))
140         # logger.info('Lcm notify end, response %s' % resp)
141         NotificationsUtil().send_notification(notification_content)
142
143     def vnf_inst_failed_handle(self, error_msg):
144         logger.error('VNF instantiation failed, detail message: %s' % error_msg)
145         NfInstModel.objects.filter(nfinstid=self.nf_inst_id).update(status='NOT_INSTANTIATED', lastuptime=now_time())
146         JobUtil.add_job_status(self.job_id, 255, error_msg)
147
148     def do_notify(self, res_type, ret):
149         logger.info('Creating [%s] resource' % res_type)
150         resource_save_method = getattr(common, res_type + '_save')
151         resource_save_method(self.job_id, self.nf_inst_id, ret)
152
153     def update_cps(self):
154         for extlink in ignore_case_get(self.data, "extVirtualLinks"):
155             for ext_cp in ignore_case_get(extlink, "extCps"):
156                 cpdid = ignore_case_get(ext_cp, "cpdId")
157                 for cp in ignore_case_get(self.vnfd_info, "cps"):
158                     if cpdid == ignore_case_get(cp, "cp_id"):
159                         cp["networkId"] = ignore_case_get(extlink, "resourceId")
160                         cp["subnetId"] = ignore_case_get(extlink, "resourceSubnetId")
161                         break
162
163     def set_location(self, apply_result):
164         vim_connections = ignore_case_get(apply_result, "vimConnections")
165         vnfid = ignore_case_get(apply_result, "vnfInstanceId")
166         directive = ignore_case_get(apply_result, "directive")
167         vim_assets = ignore_case_get(apply_result, "vimAssets")
168         access_info = ignore_case_get(vim_connections[0], "accessInfo")
169         tenant = ignore_case_get(access_info, "tenant")
170         vimid = ignore_case_get(vim_connections[0], "vimId")
171         cloud_owner, cloud_regionid = vimid.split("_")
172         vdu_info = []
173
174         for flavor in ignore_case_get(vim_assets, "vimComputeResourceFlavour"):
175             vdu_info.append({"vduName": flavor["resourceProviderId"],
176                              "flavorName": flavor["vimFlavourId"],
177                              "directive": directive})
178
179         for resource_type in ['vdus', 'vls']:
180             for resource in ignore_case_get(self.vnfd_info, resource_type):
181                 if "location_info" in resource["properties"]:
182                     resource["properties"]["location_info"]["vimid"] = vimid
183                     resource["properties"]["location_info"]["tenant"] = tenant
184                     resource["properties"]["location_info"]["vnfId"] = vnfid
185                     resource["properties"]["location_info"]["cloudOwner"] = cloud_owner
186                     resource["properties"]["location_info"]["cloudRegionId"] = cloud_regionid
187                     resource["properties"]["location_info"]["vduInfo"] = vdu_info
188                 else:
189                     resource["properties"]["location_info"] = {
190                         "vimid": vimid,
191                         "tenant": tenant,
192                         "vnfId": vnfid,
193                         "cloudOwner": cloud_owner,
194                         "cloudRegionId": cloud_regionid,
195                         "vduInfo": vdu_info}
196
197     '''
198     def get_subnet_ids(self, ext_cp):
199         subnet_ids = []
200         for cp_conf in ignore_case_get(ext_cp, "cpConfig"):
201             for cp_protocol in ignore_case_get(ext_cp, "cpProtocolData"):
202                 ip_over_ethernet = ignore_case_get(cp_protocol, "ipOverEthernet")
203                 for ip_address in ignore_case_get(ip_over_ethernet, "ipAddresses"):
204                     subnet_ids.append(ignore_case_get(ip_address, "subnetId"))
205         return subnet_ids
206     '''