cf67a76e375c9e04448fcc606bef56379a6d30d9
[modeling/etsicatalog.git] / genericparser / packages / biz / vnf_package.py
1 # Copyright 2018 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 urllib
22 import uuid
23
24 from genericparser.packages.biz.common import parse_file_range, read, save
25 from genericparser.pub.config.config import GENERICPARSER_ROOT_PATH
26 from genericparser.pub.database.models import VnfPackageModel, NSPackageModel
27 from genericparser.pub.exceptions import GenericparserException, ResourceNotFoundException
28 from genericparser.pub.utils.values import ignore_case_get
29 from genericparser.pub.utils import fileutil, toscaparsers
30 from genericparser.packages.const import PKG_STATUS
31
32
33 logger = logging.getLogger(__name__)
34
35
36 class VnfPackage(object):
37
38     def __init__(self):
39         pass
40
41     def create_vnf_pkg(self, data):
42         user_defined_data = ignore_case_get(data, "userDefinedData", {})
43         vnf_pkg_id = str(uuid.uuid4())
44         VnfPackageModel.objects.create(
45             vnfPackageId=vnf_pkg_id,
46             onboardingState=PKG_STATUS.CREATED,
47             operationalState=PKG_STATUS.DISABLED,
48             usageState=PKG_STATUS.NOT_IN_USE,
49             userDefinedData=json.dumps(user_defined_data)
50         )
51         data = {
52             "id": vnf_pkg_id,
53             "onboardingState": PKG_STATUS.CREATED,
54             "operationalState": PKG_STATUS.DISABLED,
55             "usageState": PKG_STATUS.NOT_IN_USE,
56             "userDefinedData": user_defined_data,
57             "_links": None
58         }
59         return data
60
61     def query_multiple(self):
62         pkgs_info = []
63         nf_pkgs = VnfPackageModel.objects.filter()
64         for nf_pkg in nf_pkgs:
65             ret = fill_response_data(nf_pkg)
66             pkgs_info.append(ret)
67         return pkgs_info
68
69     def query_single(self, vnf_pkg_id):
70         nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
71         if not nf_pkg.exists():
72             logger.error('VNF package(%s) does not exist.' % vnf_pkg_id)
73             raise ResourceNotFoundException('VNF package(%s) does not exist.' % vnf_pkg_id)
74         return fill_response_data(nf_pkg[0])
75
76     def delete_vnf_pkg(self, vnf_pkg_id):
77         vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
78         if not vnf_pkg.exists():
79             logger.debug('VNF package(%s) has been deleted.' % vnf_pkg_id)
80             return
81         '''
82         if vnf_pkg[0].operationalState != PKG_STATUS.DISABLED:
83             raise GenericparserException("The VNF package (%s) is not disabled" % vnf_pkg_id)
84         if vnf_pkg[0].usageState != PKG_STATUS.NOT_IN_USE:
85             raise GenericparserException("The VNF package (%s) is in use" % vnf_pkg_id)
86         '''
87         del_vnfd_id = vnf_pkg[0].vnfdId
88         ns_pkgs = NSPackageModel.objects.all()
89         for ns_pkg in ns_pkgs:
90             nsd_model = None
91             if ns_pkg.nsdModel:
92                 nsd_model = json.JSONDecoder().decode(ns_pkg.nsdModel)
93             if not nsd_model:
94                 continue
95             for vnf in nsd_model['vnfs']:
96                 if del_vnfd_id == vnf["properties"]["descriptor_id"]:
97                     raise GenericparserException('VNFD(%s) is referenced.' % del_vnfd_id)
98         vnf_pkg.delete()
99         vnf_pkg_path = os.path.join(GENERICPARSER_ROOT_PATH, vnf_pkg_id)
100         fileutil.delete_dirs(vnf_pkg_path)
101         logger.info('VNF package(%s) has been deleted.' % vnf_pkg_id)
102
103     def upload(self, vnf_pkg_id, remote_file):
104         logger.info('Start to upload VNF package(%s)...' % vnf_pkg_id)
105         vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
106         # if vnf_pkg[0].onboardingState != PKG_STATUS.CREATED:
107         #     logger.error("VNF package(%s) is not CREATED" % vnf_pkg_id)
108         #     raise GenericparserException("VNF package(%s) is not CREATED" % vnf_pkg_id)
109         vnf_pkg.update(onboardingState=PKG_STATUS.UPLOADING)
110
111         local_file_name = save(remote_file, vnf_pkg_id)
112         logger.info('VNF package(%s) has been uploaded.' % vnf_pkg_id)
113         return local_file_name
114
115     def download(self, vnf_pkg_id, file_range):
116         logger.info('Start to download VNF package(%s)...' % vnf_pkg_id)
117         nf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
118         if not nf_pkg.exists():
119             logger.error('VNF package(%s) does not exist.' % vnf_pkg_id)
120             raise ResourceNotFoundException('VNF package(%s) does not exist.' % vnf_pkg_id)
121         if nf_pkg[0].onboardingState != PKG_STATUS.ONBOARDED:
122             raise GenericparserException("VNF package (%s) is not on-boarded" % vnf_pkg_id)
123
124         local_file_path = nf_pkg[0].localFilePath
125         start, end = parse_file_range(local_file_path, file_range)
126         logger.info('VNF package (%s) has been downloaded.' % vnf_pkg_id)
127         return read(local_file_path, start, end)
128
129
130 class VnfPkgUploadThread(threading.Thread):
131     def __init__(self, data, vnf_pkg_id):
132         threading.Thread.__init__(self)
133         self.vnf_pkg_id = vnf_pkg_id
134         self.data = data
135         self.upload_file_name = None
136
137     def run(self):
138         try:
139             self.upload_vnf_pkg_from_uri()
140             parse_vnfd_and_save(self.vnf_pkg_id, self.upload_file_name)
141         except GenericparserException as e:
142             logger.error(e.args[0])
143         except Exception as e:
144             logger.error(e.args[0])
145             logger.error(traceback.format_exc())
146             logger.error(str(sys.exc_info()))
147
148     def upload_vnf_pkg_from_uri(self):
149         logger.info("Start to upload VNF packge(%s) from URI..." % self.vnf_pkg_id)
150         vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=self.vnf_pkg_id)
151         if vnf_pkg[0].onboardingState != PKG_STATUS.CREATED:
152             logger.error("VNF package(%s) is not CREATED" % self.vnf_pkg_id)
153             raise GenericparserException("VNF package (%s) is not created" % self.vnf_pkg_id)
154         vnf_pkg.update(onboardingState=PKG_STATUS.UPLOADING)
155
156         uri = ignore_case_get(self.data, "addressInformation")
157         response = urllib.request.urlopen(uri)
158
159         local_file_dir = os.path.join(GENERICPARSER_ROOT_PATH, self.vnf_pkg_id)
160         self.upload_file_name = os.path.join(local_file_dir, os.path.basename(uri))
161         if not os.path.exists(local_file_dir):
162             fileutil.make_dirs(local_file_dir)
163         with open(self.upload_file_name, "wt") as local_file:
164             local_file.write(response.read())
165         response.close()
166         logger.info('VNF packge(%s) has been uploaded.' % self.vnf_pkg_id)
167
168
169 def fill_response_data(nf_pkg):
170     pkg_info = {}
171     pkg_info["id"] = nf_pkg.vnfPackageId
172     pkg_info["vnfdId"] = nf_pkg.vnfdId
173     pkg_info["vnfProductName"] = nf_pkg.vnfdProductName
174     pkg_info["vnfSoftwareVersion"] = nf_pkg.vnfSoftwareVersion
175     pkg_info["vnfdVersion"] = nf_pkg.vnfdVersion
176     if nf_pkg.checksum:
177         pkg_info["checksum"] = json.JSONDecoder().decode(nf_pkg.checksum)
178     pkg_info["softwareImages"] = None  # TODO
179     pkg_info["additionalArtifacts"] = None  # TODO
180     pkg_info["onboardingState"] = nf_pkg.onboardingState
181     pkg_info["operationalState"] = nf_pkg.operationalState
182     pkg_info["usageState"] = nf_pkg.usageState
183     if nf_pkg.userDefinedData:
184         pkg_info["userDefinedData"] = json.JSONDecoder().decode(nf_pkg.userDefinedData)
185     pkg_info["_links"] = None  # TODO
186     return pkg_info
187
188
189 def parse_vnfd_and_save(vnf_pkg_id, vnf_pkg_path):
190     logger.info('Start to process VNF package(%s)...' % vnf_pkg_id)
191     vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
192     vnf_pkg.update(onboardingState=PKG_STATUS.PROCESSING)
193     vnfd_json = toscaparsers.parse_vnfd(vnf_pkg_path)
194     vnfd = json.JSONDecoder().decode(vnfd_json)
195
196     if vnfd.get("vnf", "") != "":
197         vnfd_id = vnfd["vnf"]["properties"].get("descriptor_id", "")
198         other_pkg = VnfPackageModel.objects.filter(vnfdId=vnfd_id)
199         if other_pkg and other_pkg[0].vnfPackageId != vnf_pkg_id:
200             logger.error("VNF package(%s,%s) already exists.", other_pkg[0].vnfPackageId, vnfd_id)
201             raise GenericparserException("VNF package(%s) already exists." % vnfd_id)
202         vnf_provider = vnfd["vnf"]["properties"].get("provider", "")
203         vnfd_ver = vnfd["vnf"]["properties"].get("descriptor_version", "")
204         vnf_software_version = vnfd["vnf"]["properties"].get("software_version", "")
205         vnfd_product_name = vnfd["vnf"]["properties"].get("product_name", "")
206         vnf_pkg.update(
207             vnfPackageId=vnf_pkg_id,
208             vnfdId=vnfd_id,
209             vnfdProductName=vnfd_product_name,
210             vnfVendor=vnf_provider,
211             vnfdVersion=vnfd_ver,
212             vnfSoftwareVersion=vnf_software_version,
213             vnfdModel=vnfd_json,
214             onboardingState=PKG_STATUS.ONBOARDED,
215             operationalState=PKG_STATUS.ENABLED,
216             usageState=PKG_STATUS.NOT_IN_USE,
217             localFilePath=vnf_pkg_path,
218             vnfPackageUri=os.path.split(vnf_pkg_path)[-1]
219         )
220     else:
221         raise GenericparserException("VNF propeties and metadata in VNF Package(id=%s) are empty." % vnf_pkg_id)
222     logger.info('VNF package(%s) has been processed(done).' % vnf_pkg_id)
223
224
225 def handle_upload_failed(vnf_pkg_id):
226     vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
227     vnf_pkg.update(onboardingState=PKG_STATUS.CREATED)