dd6a236971051c1fb9cd10c5120cf4fd9e18b177
[modeling/etsicatalog.git] / catalog / packages / biz / pnf_descriptor.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
16 import json
17 import logging
18 import os
19 import uuid
20
21 from catalog.packages.biz.common import read, save
22 from catalog.packages.const import PKG_STATUS
23 from catalog.pub.config.config import CATALOG_ROOT_PATH
24 from catalog.pub.database.models import NSPackageModel, PnfPackageModel
25 from catalog.pub.exceptions import CatalogException, ResourceNotFoundException
26 from catalog.pub.utils import fileutil, toscaparser
27 from catalog.pub.utils.values import ignore_case_get
28 from catalog.packages.biz.notificationsutil import PnfNotifications
29 from catalog.packages import const
30
31 logger = logging.getLogger(__name__)
32
33
34 class PnfDescriptor(object):
35
36     def __init__(self):
37         pass
38
39     def create(self, data):
40         logger.info('Start to create a PNFD...')
41         user_defined_data = ignore_case_get(data, 'userDefinedData', {})
42         data = {
43             'id': str(uuid.uuid4()),
44             'pnfdOnboardingState': PKG_STATUS.CREATED,
45             'pnfdUsageState': PKG_STATUS.NOT_IN_USE,
46             'userDefinedData': user_defined_data,
47             '_links': None  # TODO
48         }
49         PnfPackageModel.objects.create(
50             pnfPackageId=data['id'],
51             onboardingState=data['pnfdOnboardingState'],
52             usageState=data['pnfdUsageState'],
53             userDefinedData=json.dumps(user_defined_data)
54         )
55         logger.info('A PNFD(%s) has been created.' % data['id'])
56         return data
57
58     def query_multiple(self, request):
59         pnfdId = request.query_params.get('pnfdId')
60         if pnfdId:
61             pnf_pkgs = PnfPackageModel.objects.filter(pnfdId=pnfdId)
62         else:
63             pnf_pkgs = PnfPackageModel.objects.all()
64         response_data = []
65         for pnf_pkg in pnf_pkgs:
66             data = self.fill_response_data(pnf_pkg)
67             response_data.append(data)
68         return response_data
69
70     def query_single(self, pnfd_info_id):
71         pnf_pkgs = PnfPackageModel.objects.filter(pnfPackageId=pnfd_info_id)
72         if not pnf_pkgs.exists():
73             logger.error('PNFD(%s) does not exist.' % pnfd_info_id)
74             raise ResourceNotFoundException('PNFD(%s) does not exist.' % pnfd_info_id)
75         return self.fill_response_data(pnf_pkgs[0])
76
77     def upload(self, remote_file, pnfd_info_id):
78         logger.info('Start to upload PNFD(%s)...' % pnfd_info_id)
79         pnf_pkgs = PnfPackageModel.objects.filter(pnfPackageId=pnfd_info_id)
80         if not pnf_pkgs.exists():
81             details = 'PNFD(%s) is not CREATED.' % pnfd_info_id
82             logger.info(details)
83             send_notification(
84                 type=const.NSD_NOTIFICATION_TYPE.PNFD_ONBOARDING_FAILURE,
85                 pnfd_info_id=pnfd_info_id,
86                 failure_details=details
87             )
88             raise CatalogException(details)
89         pnf_pkgs.update(onboardingState=PKG_STATUS.UPLOADING)
90
91         local_file_name = save(remote_file, pnfd_info_id)
92         logger.info('PNFD(%s) content has been uploaded.' % pnfd_info_id)
93         return local_file_name
94
95     def delete_single(self, pnfd_info_id):
96         logger.info('Start to delete PNFD(%s)...' % pnfd_info_id)
97         pnf_pkgs = PnfPackageModel.objects.filter(pnfPackageId=pnfd_info_id)
98         if not pnf_pkgs.exists():
99             logger.info('PNFD(%s) has been deleted.' % pnfd_info_id)
100             return
101         '''
102         if pnf_pkgs[0].usageState != PKG_STATUS.NOT_IN_USE:
103             logger.info('PNFD(%s) shall be NOT_IN_USE.' % pnfd_info_id)
104             raise CatalogException('PNFD(%s) shall be NOT_IN_USE.' % pnfd_info_id)
105         '''
106         del_pnfd_id = pnf_pkgs[0].pnfdId
107         ns_pkgs = NSPackageModel.objects.all()
108         for ns_pkg in ns_pkgs:
109             nsd_model = None
110             if ns_pkg.nsdModel:
111                 nsd_model = json.JSONDecoder().decode(ns_pkg.nsdModel)
112             if not nsd_model:
113                 continue
114             for pnf in nsd_model['pnfs']:
115                 if del_pnfd_id == pnf["properties"]["id"]:
116                     logger.warn("PNFD(%s) is referenced in NSD", del_pnfd_id)
117                     raise CatalogException('PNFD(%s) is referenced.' % pnfd_info_id)
118         pnf_pkgs.delete()
119         pnf_pkg_path = os.path.join(CATALOG_ROOT_PATH, pnfd_info_id)
120         fileutil.delete_dirs(pnf_pkg_path)
121         send_notification(const.NSD_NOTIFICATION_TYPE.PNFD_DELETION, pnfd_info_id, del_pnfd_id)
122         logger.debug('PNFD(%s) has been deleted.' % pnfd_info_id)
123
124     def download(self, pnfd_info_id):
125         logger.info('Start to download PNFD(%s)...' % pnfd_info_id)
126         pnf_pkgs = PnfPackageModel.objects.filter(pnfPackageId=pnfd_info_id)
127         if not pnf_pkgs.exists():
128             logger.error('PNFD(%s) does not exist.' % pnfd_info_id)
129             raise ResourceNotFoundException('PNFD(%s) does not exist.' % pnfd_info_id)
130         if pnf_pkgs[0].onboardingState != PKG_STATUS.ONBOARDED:
131             logger.error('PNFD(%s) is not ONBOARDED.' % pnfd_info_id)
132             raise CatalogException('PNFD(%s) is not ONBOARDED.' % pnfd_info_id)
133
134         local_file_path = pnf_pkgs[0].localFilePath
135         start, end = 0, os.path.getsize(local_file_path)
136         logger.info('PNFD(%s) has been downloaded.' % pnfd_info_id)
137         return read(local_file_path, start, end)
138
139     def parse_pnfd_and_save(self, pnfd_info_id, local_file_name):
140         logger.info('Start to process PNFD(%s)...' % pnfd_info_id)
141         pnf_pkgs = PnfPackageModel.objects.filter(pnfPackageId=pnfd_info_id)
142         pnf_pkgs.update(onboardingState=PKG_STATUS.PROCESSING)
143         pnfd_json = toscaparser.parse_pnfd(local_file_name)
144         pnfd = json.JSONDecoder().decode(pnfd_json)
145
146         logger.debug("pnfd_json is %s" % pnfd_json)
147         pnfd_id = ""
148         pnfdVersion = ""
149         pnfdProvider = ""
150         pnfdName = ""
151         if pnfd.get("pnf", "") != "":
152             if pnfd["pnf"].get("properties", "") != "":
153                 pnfd_id = pnfd["pnf"].get("properties", {}).get("descriptor_id", "")
154                 pnfdVersion = pnfd["pnf"].get("properties", {}).get("version", "")
155                 pnfdProvider = pnfd["pnf"].get("properties", {}).get("provider", "")
156                 pnfdName = pnfd["pnf"].get("properties", {}).get("name", "")
157         if pnfd_id == "":
158             pnfd_id = pnfd["metadata"].get("descriptor_id", "")
159             if pnfd_id == "":
160                 pnfd_id = pnfd["metadata"].get("id", "")
161             if pnfd_id == "":
162                 pnfd_id = pnfd["metadata"].get("UUID", "")
163             if pnfd_id == "":
164                 raise CatalogException('pnfd_id is Null.')
165
166         if pnfdVersion == "":
167             pnfdVersion = pnfd["metadata"].get("template_version", "")
168             if pnfdVersion == "":
169                 pnfdVersion = pnfd["metadata"].get("version", "")
170
171         if pnfdProvider == "":
172             pnfdProvider = pnfd["metadata"].get("template_author", "")
173             if pnfdVersion == "":
174                 pnfdVersion = pnfd["metadata"].get("provider", "")
175
176         if pnfdName == "":
177             pnfdName = pnfd["metadata"].get("template_name", "")
178             if pnfdVersion == "":
179                 pnfdName = pnfd["metadata"].get("name", "")
180
181         other_pnf = PnfPackageModel.objects.filter(pnfdId=pnfd_id)
182         if other_pnf and other_pnf[0].pnfPackageId != pnfd_info_id:
183             logger.info('PNFD(%s) already exists.' % pnfd_id)
184             raise CatalogException("PNFD(%s) already exists." % pnfd_id)
185
186         pnf_pkgs.update(
187             pnfdId=pnfd_id,
188             pnfdName=pnfdName,
189             pnfdVersion=pnfdVersion,
190             pnfVendor=pnfdProvider,
191             pnfPackageUri=local_file_name,
192             onboardingState=PKG_STATUS.ONBOARDED,
193             usageState=PKG_STATUS.NOT_IN_USE,
194             localFilePath=local_file_name,
195             pnfdModel=pnfd_json
196         )
197         send_notification(const.NSD_NOTIFICATION_TYPE.PNFD_ONBOARDING, pnfd_info_id, pnfd_id)
198         logger.info('PNFD(%s) has been processed.' % pnfd_info_id)
199
200     def fill_response_data(self, pnf_pkg):
201         data = {
202             'id': pnf_pkg.pnfPackageId,
203             'pnfdId': pnf_pkg.pnfdId,
204             'pnfdName': pnf_pkg.pnfdName,
205             'pnfdVersion': pnf_pkg.pnfdVersion,
206             'pnfdProvider': pnf_pkg.pnfVendor,
207             'pnfdInvariantId': None,  # TODO
208             'pnfdOnboardingState': pnf_pkg.onboardingState,
209             'onboardingFailureDetails': None,  # TODO
210             'pnfdUsageState': pnf_pkg.usageState,
211             'userDefinedData': {},
212             '_links': None  # TODO
213         }
214         if pnf_pkg.userDefinedData:
215             user_defined_data = json.JSONDecoder().decode(pnf_pkg.userDefinedData)
216             data['userDefinedData'] = user_defined_data
217
218         return data
219
220     def handle_upload_failed(self, pnf_pkg_id):
221         pnf_pkg = PnfPackageModel.objects.filter(pnfPackageId=pnf_pkg_id)
222         pnf_pkg.update(onboardingState=PKG_STATUS.CREATED)
223
224     def parse_pnfd(self, csar_id, inputs):
225         try:
226             pnf_pkg = PnfPackageModel.objects.filter(pnfPackageId=csar_id)
227             if not pnf_pkg:
228                 raise CatalogException("PNF CSAR(%s) does not exist." % csar_id)
229             csar_path = pnf_pkg[0].localFilePath
230             ret = {"model": toscaparser.parse_pnfd(csar_path, inputs)}
231         except CatalogException as e:
232             return [1, e.args[0]]
233         except Exception as e:
234             logger.error(e.args[0])
235             return [1, e.args[0]]
236         return [0, ret]
237
238
239 def send_notification(type, pnfd_info_id, pnfd_id=None, failure_details=None):
240     notify = PnfNotifications(type, pnfd_info_id, pnfd_id, failure_details=failure_details)
241     notify.send_notification()