update the errorCode in job information
[modeling/etsicatalog.git] / catalog / packages / biz / sdc_vnf_package.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 os
18 import sys
19 import threading
20 import traceback
21 import zipfile
22
23 from catalog.packages.biz.vnf_package import VnfPackage
24 from catalog.packages.const import PKG_STATUS
25 from catalog.pub.config.config import CATALOG_ROOT_PATH, CATALOG_URL_PATH
26 from catalog.pub.config.config import REG_TO_MSB_REG_PARAM
27 from catalog.pub.database.models import VnfPackageModel
28 from catalog.pub.exceptions import CatalogException, PackageHasExistsException
29 from catalog.pub.msapi import sdc
30 from catalog.pub.utils import fileutil
31 from catalog.pub.utils import toscaparser
32 from catalog.pub.utils.jobutil import JobUtil, JOB_ERROR_CODE
33
34 logger = logging.getLogger(__name__)
35
36 JOB_ERROR = 255
37
38
39 def nf_get_csars():
40     ret = None
41     try:
42         ret = NfPackage().get_csars()
43     except CatalogException as e:
44         return [1, e.args[0]]
45     except Exception as e:
46         logger.error(e.args[0])
47         logger.error(traceback.format_exc())
48         return [1, str(sys.exc_info())]
49     return ret
50
51
52 def nf_get_csar(csar_id):
53     ret = None
54     try:
55         ret = NfPackage().get_csar(csar_id)
56     except CatalogException as e:
57         return [1, e.args[0]]
58     except Exception as e:
59         logger.error(e.args[0])
60         logger.error(traceback.format_exc())
61         return [1, str(sys.exc_info())]
62     return ret
63
64
65 def parse_vnfd(csar_id, inputs):
66     ret = None
67     try:
68         nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=csar_id)
69         if not nf_pkg:
70             raise CatalogException("VNF CSAR(%s) does not exist." % csar_id)
71         csar_path = nf_pkg[0].localFilePath
72         ret = {"model": toscaparser.parse_vnfd(csar_path, inputs)}
73     except CatalogException as e:
74         return [1, e.args[0]]
75     except Exception as e:
76         logger.error(e.args[0])
77         logger.error(traceback.format_exc())
78         return [1, str(sys.exc_info())]
79     return [0, ret]
80
81
82 class NfDistributeThread(threading.Thread):
83     """
84     Sdc NF Package Distribute
85     """
86
87     def __init__(self, csar_id, vim_ids, lab_vim_id, job_id):
88         threading.Thread.__init__(self)
89         self.csar_id = csar_id
90         self.vim_ids = vim_ids
91         self.lab_vim_id = lab_vim_id
92         self.job_id = job_id
93
94         self.csar_save_path = os.path.join(CATALOG_ROOT_PATH, csar_id)
95
96     def run(self):
97         try:
98             self.on_distribute()
99         except PackageHasExistsException as e:
100             self.rollback_distribute()
101             JobUtil.add_job_status(self.job_id, JOB_ERROR, e.args[0], error_code=JOB_ERROR_CODE.PACKAGE_EXIST)
102         except CatalogException as e:
103             self.rollback_distribute()
104             JobUtil.add_job_status(self.job_id, JOB_ERROR, e.args[0], error_code=JOB_ERROR_CODE.CATALOG_EXCEPTION)
105         except Exception as e:
106             logger.error(e.args[0])
107             logger.error(traceback.format_exc())
108             logger.error(str(sys.exc_info()))
109             self.rollback_distribute()
110             JobUtil.add_job_status(self.job_id, JOB_ERROR, "Failed to distribute CSAR(%s)" % self.csar_id,
111                                    error_code=JOB_ERROR_CODE.SYSTEM_ERROR)
112
113     def on_distribute(self):
114         JobUtil.create_job(
115             inst_type='nf',
116             jobaction='on_distribute',
117             inst_id=self.csar_id,
118             job_id=self.job_id)
119         JobUtil.add_job_status(self.job_id, 5, "Start CSAR(%s) distribute." % self.csar_id)
120
121         if VnfPackageModel.objects.filter(vnfPackageId=self.csar_id):
122             err_msg = "NF CSAR(%s) already exists." % self.csar_id
123             JobUtil.add_job_status(self.job_id, JOB_ERROR, err_msg, error_code=JOB_ERROR_CODE.PACKAGE_EXIST)
124             return
125
126         artifact = sdc.get_artifact(sdc.ASSETTYPE_RESOURCES, self.csar_id)
127         local_path = os.path.join(CATALOG_ROOT_PATH, self.csar_id)
128         csar_name = "%s.csar" % artifact.get("name", self.csar_id)
129         local_file_name = sdc.download_artifacts(artifact["toscaModelURL"], local_path, csar_name)
130         if local_file_name.endswith(".csar") or local_file_name.endswith(".zip"):
131             fileutil.unzip_csar(local_file_name, local_path)
132             vendor_vnf_file = ''
133             # find original vendor ETSI package under the ONBOARDING_PACKAGE directory
134             onboarding_package_dir = os.path.join(local_path, "Artifacts/Deployment/ONBOARDED_PACKAGE")
135             if os.path.exists(onboarding_package_dir):
136                 files = os.listdir(onboarding_package_dir)
137                 for file_name in files:
138                     a_file = os.path.join(onboarding_package_dir, file_name)
139                     if os.path.isfile(a_file) & file_name.endswith(".csar"):
140                         vendor_vnf_file = a_file
141                         break
142
143             # find original vendor ETSI package under Artifacts/Deployment/OTHER directory
144             if vendor_vnf_file.strip() == '':
145                 vendor_vnf_file = os.path.join(local_path, "Artifacts/Deployment/OTHER/vnf.csar")
146                 if os.path.exists(vendor_vnf_file):
147                     local_file_name = vendor_vnf_file
148             else:
149                 local_file_name = vendor_vnf_file
150
151         # create VNFD zip file
152         self.create_vnfd_zip(self.csar_id, vendor_vnf_file)
153
154         vnfd_json = toscaparser.parse_vnfd(local_file_name)
155         vnfd = json.JSONDecoder().decode(vnfd_json)
156
157         if not vnfd.get("vnf"):
158             raise CatalogException("VNF properties and metadata in VNF Package(id=%s) are empty." % self.csar_id)
159
160         vnfd_id = vnfd["vnf"]["properties"].get("descriptor_id", "")
161         if VnfPackageModel.objects.filter(vnfdId=vnfd_id):
162             logger.error("VNF package(%s) already exists.", vnfd_id)
163             raise PackageHasExistsException("VNF package(%s) already exists." % vnfd_id)
164         JobUtil.add_job_status(self.job_id, 30, "Save CSAR(%s) to database." % self.csar_id)
165         vnfd_ver = vnfd["vnf"]["properties"].get("descriptor_version", "")
166         vnf_provider = vnfd["vnf"]["properties"].get("provider", "")
167         vnf_software_version = vnfd["vnf"]["properties"].get("software_version", "")
168         vnfd_product_name = vnfd["vnf"]["properties"].get("product_name", "")
169         VnfPackageModel(
170             vnfPackageId=self.csar_id,
171             vnfdId=vnfd_id,
172             vnfVendor=vnf_provider,
173             vnfdProductName=vnfd_product_name,
174             vnfdVersion=vnfd_ver,
175             vnfSoftwareVersion=vnf_software_version,
176             vnfdModel=vnfd_json,
177             localFilePath=local_file_name,
178             vnfPackageUri=csar_name,
179             onboardingState=PKG_STATUS.ONBOARDED,
180             operationalState=PKG_STATUS.ENABLED,
181             usageState=PKG_STATUS.NOT_IN_USE
182         ).save()
183         JobUtil.add_job_status(self.job_id, 100, "CSAR(%s) distribute successfully." % self.csar_id)
184
185     def create_vnfd_zip(self, csar_id, vendor_vnf_file):
186         """
187         Create VNFD zip file.
188         :param csar_id: CSAR Id
189         :param vendor_vnf_file: the vendor original package(csar)
190         :return:
191         """
192         if os.path.exists(vendor_vnf_file):
193             # create VNFD from vendor original package
194             VnfPackage().creat_vnfd(csar_id, vendor_vnf_file)
195         else:
196             try:
197                 vnf_package_path = os.path.join(CATALOG_ROOT_PATH, self.csar_id)
198                 vnfd_zip_file = os.path.join(vnf_package_path, 'VNFD.zip')
199                 with zipfile.ZipFile(vnfd_zip_file, 'w', zipfile.ZIP_DEFLATED) as vnfd_zip:
200                     def_path = os.path.join(vnf_package_path, "Definitions")
201                     if os.path.exists(def_path):
202                         def_files = os.listdir(def_path)
203                         for def_file in def_files:
204                             full_path = os.path.join(def_path, def_file)
205                             vnfd_zip.write(full_path, def_file)
206             except Exception as e:
207                 logger.error(e)
208                 if os.path.exists(vnfd_zip_file):
209                     os.remove(vnfd_zip_file)
210
211     def rollback_distribute(self):
212         try:
213             VnfPackageModel.objects.filter(vnfPackageId=self.csar_id).delete()
214             fileutil.delete_dirs(self.csar_save_path)
215         except Exception as e:
216             logger.error(e.args[0])
217             logger.error(traceback.format_exc())
218             logger.error(str(sys.exc_info()))
219
220
221 class NfPkgDeleteThread(threading.Thread):
222     """
223     Sdc NF Package Deleting
224     """
225
226     def __init__(self, csar_id, job_id):
227         threading.Thread.__init__(self)
228         self.csar_id = csar_id
229         self.job_id = job_id
230
231     def run(self):
232         try:
233             self.delete_csar()
234         except CatalogException as e:
235             JobUtil.add_job_status(self.job_id, JOB_ERROR, e.args[0])
236         except Exception as e:
237             logger.error(e.args[0])
238             logger.error(traceback.format_exc())
239             logger.error(str(sys.exc_info()))
240             JobUtil.add_job_status(self.job_id, JOB_ERROR, "Failed to delete CSAR(%s)" % self.csar_id)
241
242     def delete_csar(self):
243         JobUtil.create_job(
244             inst_type='nf',
245             jobaction='delete',
246             inst_id=self.csar_id,
247             job_id=self.job_id)
248         JobUtil.add_job_status(self.job_id, 5, "Start to delete CSAR(%s)." % self.csar_id)
249
250         VnfPackageModel.objects.filter(vnfPackageId=self.csar_id).delete()
251
252         JobUtil.add_job_status(self.job_id, 50, "Delete local CSAR(%s) file." % self.csar_id)
253
254         csar_save_path = os.path.join(CATALOG_ROOT_PATH, self.csar_id)
255         fileutil.delete_dirs(csar_save_path)
256
257         JobUtil.add_job_status(self.job_id, 100, "Delete CSAR(%s) successfully." % self.csar_id)
258
259
260 class NfPackage(object):
261     """
262     Actions for sdc nf package.
263     """
264
265     def __init__(self):
266         pass
267
268     def get_csars(self):
269         csars = []
270         nf_pkgs = VnfPackageModel.objects.filter()
271         for nf_pkg in nf_pkgs:
272             ret = self.get_csar(nf_pkg.vnfPackageId)
273             csars.append(ret[1])
274         return [0, csars]
275
276     def get_csar(self, csar_id):
277         pkg_info = {}
278         nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=csar_id)
279         if not nf_pkg:
280             nf_pkg = VnfPackageModel.objects.filter(vnfdId=csar_id)
281
282         if nf_pkg:
283             db_csar_id = nf_pkg[0].vnfPackageId
284             pkg_info["vnfdId"] = nf_pkg[0].vnfdId
285             pkg_info["vnfPackageId"] = nf_pkg[0].vnfPackageId
286             pkg_info["vnfdProvider"] = nf_pkg[0].vnfVendor
287             pkg_info["vnfdVersion"] = nf_pkg[0].vnfdVersion
288             pkg_info["vnfVersion"] = nf_pkg[0].vnfSoftwareVersion
289             pkg_info["csarName"] = nf_pkg[0].vnfPackageUri
290             pkg_info["vnfdModel"] = nf_pkg[0].vnfdModel
291             pkg_info["downloadUrl"] = "http://%s:%s/%s/%s/%s" % (
292                 REG_TO_MSB_REG_PARAM[0]["nodes"][0]["ip"],
293                 REG_TO_MSB_REG_PARAM[0]["nodes"][0]["port"],
294                 CATALOG_URL_PATH,
295                 db_csar_id,
296                 nf_pkg[0].vnfPackageUri)
297         else:
298             raise CatalogException("Vnf package[%s] not Found." % csar_id)
299
300         csar_info = {
301             "csarId": db_csar_id,
302             "packageInfo": pkg_info,
303             "imageInfo": []
304         }
305         return [0, csar_info]