1 # Copyright 2017 ZTE Corporation.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
23 from catalog.packages.biz.vnf_package import VnfPackage
24 from catalog.packages import const
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 from catalog.packages.biz.notificationsutil import PkgNotifications
35 logger = logging.getLogger(__name__)
47 ret = NfPackage().get_csars()
48 except CatalogException as e:
50 except Exception as e:
51 logger.error(e.args[0])
52 logger.error(traceback.format_exc())
53 return [1, str(sys.exc_info())]
57 def nf_get_csar(csar_id):
65 ret = NfPackage().get_csar(csar_id)
66 except CatalogException as e:
68 except Exception as e:
69 logger.error(e.args[0])
70 logger.error(traceback.format_exc())
71 return [1, str(sys.exc_info())]
75 def parse_vnfd(csar_id, inputs):
84 nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=csar_id)
86 raise CatalogException("VNF CSAR(%s) does not exist." % csar_id)
87 csar_path = nf_pkg[0].localFilePath
88 ret = {"model": toscaparser.parse_vnfd(csar_path, inputs)}
89 except CatalogException as e:
91 except Exception as e:
92 logger.error(e.args[0])
93 logger.error(traceback.format_exc())
94 return [1, str(sys.exc_info())]
98 class NfDistributeThread(threading.Thread):
100 Sdc NF Package Distribute
103 def __init__(self, csar_id, vim_ids, lab_vim_id, job_id):
104 threading.Thread.__init__(self)
105 self.csar_id = csar_id
106 self.vim_ids = vim_ids
107 self.lab_vim_id = lab_vim_id
110 self.csar_save_path = os.path.join(CATALOG_ROOT_PATH, csar_id)
115 except PackageHasExistsException as e:
116 self.rollback_distribute()
117 JobUtil.add_job_status(self.job_id, JOB_ERROR, e.args[0], error_code=JOB_ERROR_CODE.PACKAGE_EXIST)
118 except CatalogException as e:
119 self.rollback_distribute()
120 JobUtil.add_job_status(self.job_id, JOB_ERROR, e.args[0], error_code=JOB_ERROR_CODE.CATALOG_EXCEPTION)
121 except Exception as e:
122 logger.error(e.args[0])
123 logger.error(traceback.format_exc())
124 logger.error(str(sys.exc_info()))
125 self.rollback_distribute()
126 JobUtil.add_job_status(self.job_id, JOB_ERROR, "Failed to distribute CSAR(%s)" % self.csar_id,
127 error_code=JOB_ERROR_CODE.SYSTEM_ERROR)
129 def on_distribute(self):
132 jobaction='on_distribute',
133 inst_id=self.csar_id,
135 JobUtil.add_job_status(self.job_id, 5, "Start CSAR(%s) distribute." % self.csar_id)
137 if VnfPackageModel.objects.filter(vnfPackageId=self.csar_id):
138 err_msg = "NF CSAR(%s) already exists." % self.csar_id
139 JobUtil.add_job_status(self.job_id, JOB_ERROR, err_msg, error_code=JOB_ERROR_CODE.PACKAGE_EXIST)
142 artifact = sdc.get_artifact(sdc.ASSETTYPE_RESOURCES, self.csar_id)
143 local_path = os.path.join(CATALOG_ROOT_PATH, self.csar_id)
144 csar_name = "%s.csar" % artifact.get("name", self.csar_id)
145 local_file_name = sdc.download_artifacts(artifact["toscaModelURL"], local_path, csar_name)
146 if local_file_name.endswith(".csar") or local_file_name.endswith(".zip"):
147 fileutil.unzip_csar(local_file_name, local_path)
149 # find original vendor ETSI package under the ETSI_PACKAGE directory
150 etsi_package_dir = os.path.join(local_path, "Artifacts/Deployment/ETSI_PACKAGE")
151 if os.path.exists(etsi_package_dir):
152 files = os.listdir(etsi_package_dir)
153 for file_name in files:
154 a_file = os.path.join(etsi_package_dir, file_name)
155 if os.path.isfile(a_file) & file_name.endswith(".csar"):
156 vendor_vnf_file = a_file
159 # find original vendor ETSI package under Artifacts/Deployment/OTHER directory
160 if vendor_vnf_file.strip() == '':
161 vendor_vnf_file = os.path.join(local_path, "Artifacts/Deployment/OTHER/vnf.csar")
162 if os.path.exists(vendor_vnf_file):
163 local_file_name = vendor_vnf_file
165 local_file_name = vendor_vnf_file
167 # create VNFD zip file
168 self.create_vnfd_zip(self.csar_id, vendor_vnf_file)
170 vnfd_json = toscaparser.parse_vnfd(local_file_name)
171 vnfd = json.JSONDecoder().decode(vnfd_json)
173 if not vnfd.get("vnf"):
174 raise CatalogException("VNF properties and metadata in VNF Package(id=%s) are empty." % self.csar_id)
176 vnfd_id = vnfd["vnf"]["properties"].get("descriptor_id", "")
177 if VnfPackageModel.objects.filter(vnfdId=vnfd_id):
178 logger.error("VNF package(%s) already exists.", vnfd_id)
179 raise PackageHasExistsException("VNF package(%s) already exists." % vnfd_id)
180 JobUtil.add_job_status(self.job_id, 30, "Save CSAR(%s) to database." % self.csar_id)
181 vnfd_ver = vnfd["vnf"]["properties"].get("descriptor_version", "")
182 vnf_provider = vnfd["vnf"]["properties"].get("provider", "")
183 vnf_software_version = vnfd["vnf"]["properties"].get("software_version", "")
184 vnfd_product_name = vnfd["vnf"]["properties"].get("product_name", "")
185 # Update VNF package Model to DB
187 vnfPackageId=self.csar_id,
189 vnfVendor=vnf_provider,
190 vnfdProductName=vnfd_product_name,
191 vnfdVersion=vnfd_ver,
192 vnfSoftwareVersion=vnf_software_version,
194 localFilePath=local_file_name,
195 vnfPackageUri=csar_name,
196 onboardingState=const.PKG_STATUS.ONBOARDED,
197 operationalState=const.PKG_STATUS.ENABLED,
198 usageState=const.PKG_STATUS.NOT_IN_USE
200 JobUtil.add_job_status(self.job_id, 100, "CSAR(%s) distribute successfully." % self.csar_id)
201 send_notification(self.csar_id, const.PKG_NOTIFICATION_TYPE.ONBOARDING,
202 const.PKG_CHANGE_TYPE.OP_STATE_CHANGE)
204 def create_vnfd_zip(self, csar_id, vendor_vnf_file):
206 Create VNFD zip file.
207 :param csar_id: CSAR Id
208 :param vendor_vnf_file: the vendor original package(csar)
211 if os.path.exists(vendor_vnf_file):
212 # create VNFD from vendor original package
213 VnfPackage().creat_vnfd(csar_id, vendor_vnf_file)
216 vnf_package_path = os.path.join(CATALOG_ROOT_PATH, self.csar_id)
217 vnfd_zip_file = os.path.join(vnf_package_path, 'VNFD.zip')
218 with zipfile.ZipFile(vnfd_zip_file, 'w', zipfile.ZIP_DEFLATED) as vnfd_zip:
219 def_path = os.path.join(vnf_package_path, "Definitions")
220 if os.path.exists(def_path):
221 def_files = os.listdir(def_path)
222 for def_file in def_files:
223 full_path = os.path.join(def_path, def_file)
224 vnfd_zip.write(full_path, def_file)
225 except Exception as e:
227 if os.path.exists(vnfd_zip_file):
228 os.remove(vnfd_zip_file)
230 def rollback_distribute(self):
232 VnfPackageModel.objects.filter(vnfPackageId=self.csar_id).delete()
233 fileutil.delete_dirs(self.csar_save_path)
234 except Exception as e:
235 logger.error(e.args[0])
236 logger.error(traceback.format_exc())
237 logger.error(str(sys.exc_info()))
240 class NfPkgDeleteThread(threading.Thread):
242 Sdc NF Package Deleting
245 def __init__(self, csar_id, job_id):
246 threading.Thread.__init__(self)
247 self.csar_id = csar_id
253 except CatalogException as e:
254 JobUtil.add_job_status(self.job_id, JOB_ERROR, e.args[0])
255 except Exception as e:
256 logger.error(e.args[0])
257 logger.error(traceback.format_exc())
258 logger.error(str(sys.exc_info()))
259 JobUtil.add_job_status(self.job_id, JOB_ERROR, "Failed to delete CSAR(%s)" % self.csar_id)
261 def delete_csar(self):
265 inst_id=self.csar_id,
267 JobUtil.add_job_status(self.job_id, 5, "Start to delete CSAR(%s)." % self.csar_id)
268 send_notification(self.csar_id, const.PKG_NOTIFICATION_TYPE.CHANGE,
269 const.PKG_CHANGE_TYPE.PKG_DELETE)
270 VnfPackageModel.objects.filter(vnfPackageId=self.csar_id).delete()
272 JobUtil.add_job_status(self.job_id, 50, "Delete local CSAR(%s) file." % self.csar_id)
274 csar_save_path = os.path.join(CATALOG_ROOT_PATH, self.csar_id)
275 fileutil.delete_dirs(csar_save_path)
277 JobUtil.add_job_status(self.job_id, 100, "Delete CSAR(%s) successfully." % self.csar_id)
280 class NfPackage(object):
282 Actions for sdc nf package.
290 nf_pkgs = VnfPackageModel.objects.filter()
291 for nf_pkg in nf_pkgs:
292 ret = self.get_csar(nf_pkg.vnfPackageId)
296 def get_csar(self, csar_id):
298 nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=csar_id)
300 nf_pkg = VnfPackageModel.objects.filter(vnfdId=csar_id)
303 db_csar_id = nf_pkg[0].vnfPackageId
304 pkg_info["vnfdId"] = nf_pkg[0].vnfdId
305 pkg_info["vnfPackageId"] = nf_pkg[0].vnfPackageId
306 pkg_info["vnfdProvider"] = nf_pkg[0].vnfVendor
307 pkg_info["vnfdVersion"] = nf_pkg[0].vnfdVersion
308 pkg_info["vnfVersion"] = nf_pkg[0].vnfSoftwareVersion
309 pkg_info["csarName"] = nf_pkg[0].vnfPackageUri
310 pkg_info["vnfdModel"] = nf_pkg[0].vnfdModel
311 pkg_info["downloadUrl"] = "http://%s:%s/%s/%s/%s" % (
312 REG_TO_MSB_REG_PARAM[0]["nodes"][0]["ip"],
313 REG_TO_MSB_REG_PARAM[0]["nodes"][0]["port"],
316 nf_pkg[0].vnfPackageUri)
318 raise CatalogException("Vnf package[%s] not Found." % csar_id)
321 "csarId": db_csar_id,
322 "packageInfo": pkg_info,
325 return [0, csar_info]
328 def send_notification(pkg_id, type, pkg_change_type, operational_state=None):
329 notify = PkgNotifications(type, pkg_id, change_type=pkg_change_type,
330 operational_state=operational_state)
331 notify.send_notification()