genericparser seed code
[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 urllib2
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.message)
143         except Exception as e:
144             logger.error(e.message)
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         request = urllib2.Request(uri)
158         response = urllib2.urlopen(request)
159
160         local_file_dir = os.path.join(GENERICPARSER_ROOT_PATH, self.vnf_pkg_id)
161         self.upload_file_name = os.path.join(local_file_dir, os.path.basename(uri))
162         if not os.path.exists(local_file_dir):
163             fileutil.make_dirs(local_file_dir)
164         with open(self.upload_file_name, "wb") as local_file:
165             local_file.write(response.read())
166         response.close()
167         logger.info('VNF packge(%s) has been uploaded.' % self.vnf_pkg_id)
168
169
170 def fill_response_data(nf_pkg):
171     pkg_info = {}
172     pkg_info["id"] = nf_pkg.vnfPackageId
173     pkg_info["vnfdId"] = nf_pkg.vnfdId
174     pkg_info["vnfProductName"] = nf_pkg.vnfdProductName
175     pkg_info["vnfSoftwareVersion"] = nf_pkg.vnfSoftwareVersion
176     pkg_info["vnfdVersion"] = nf_pkg.vnfdVersion
177     if nf_pkg.checksum:
178         pkg_info["checksum"] = json.JSONDecoder().decode(nf_pkg.checksum)
179     pkg_info["softwareImages"] = None  # TODO
180     pkg_info["additionalArtifacts"] = None  # TODO
181     pkg_info["onboardingState"] = nf_pkg.onboardingState
182     pkg_info["operationalState"] = nf_pkg.operationalState
183     pkg_info["usageState"] = nf_pkg.usageState
184     if nf_pkg.userDefinedData:
185         pkg_info["userDefinedData"] = json.JSONDecoder().decode(nf_pkg.userDefinedData)
186     pkg_info["_links"] = None  # TODO
187     return pkg_info
188
189
190 def parse_vnfd_and_save(vnf_pkg_id, vnf_pkg_path):
191     logger.info('Start to process VNF package(%s)...' % vnf_pkg_id)
192     vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
193     vnf_pkg.update(onboardingState=PKG_STATUS.PROCESSING)
194     vnfd_json = toscaparsers.parse_vnfd(vnf_pkg_path)
195     vnfd = json.JSONDecoder().decode(vnfd_json)
196
197     if vnfd.get("vnf", "") != "":
198         vnfd_id = vnfd["vnf"]["properties"].get("descriptor_id", "")
199         other_pkg = VnfPackageModel.objects.filter(vnfdId=vnfd_id)
200         if other_pkg and other_pkg[0].vnfPackageId != vnf_pkg_id:
201             logger.error("VNF package(%s,%s) already exists.", other_pkg[0].vnfPackageId, vnfd_id)
202             raise GenericparserException("VNF package(%s) already exists." % vnfd_id)
203         vnf_provider = vnfd["vnf"]["properties"].get("provider", "")
204         vnfd_ver = vnfd["vnf"]["properties"].get("descriptor_verison", "")
205         vnf_software_version = vnfd["vnf"]["properties"].get("software_version", "")
206         vnfd_product_name = vnfd["vnf"]["properties"].get("product_name", "")
207         vnf_pkg.update(
208             vnfPackageId=vnf_pkg_id,
209             vnfdId=vnfd_id,
210             vnfdProductName=vnfd_product_name,
211             vnfVendor=vnf_provider,
212             vnfdVersion=vnfd_ver,
213             vnfSoftwareVersion=vnf_software_version,
214             vnfdModel=vnfd_json,
215             onboardingState=PKG_STATUS.ONBOARDED,
216             operationalState=PKG_STATUS.ENABLED,
217             usageState=PKG_STATUS.NOT_IN_USE,
218             localFilePath=vnf_pkg_path,
219             vnfPackageUri=os.path.split(vnf_pkg_path)[-1]
220         )
221     else:
222         raise GenericparserException("VNF propeties and metadata in VNF Package(id=%s) are empty." % vnf_pkg_id)
223     logger.info('VNF package(%s) has been processed(done).' % vnf_pkg_id)
224
225
226 def handle_upload_failed(vnf_pkg_id):
227     vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=vnf_pkg_id)
228     vnf_pkg.update(onboardingState=PKG_STATUS.CREATED)