[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / openecomp-be / backend / openecomp-sdc-vendor-software-product-manager / src / main / java / org / openecomp / sdc / vendorsoftwareproduct / impl / OrchestrationTemplateCandidateManagerImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.vendorsoftwareproduct.impl;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.model.dao.ServiceModelDao;
26 import org.openecomp.core.model.types.ServiceElement;
27 import org.openecomp.core.utilities.file.FileContentHandler;
28 import org.openecomp.core.utilities.file.FileUtils;
29 import org.openecomp.core.utilities.json.JsonUtil;
30 import org.openecomp.sdc.activityLog.ActivityLogManager;
31 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
32 import org.openecomp.sdc.common.errors.CoreException;
33 import org.openecomp.sdc.common.errors.Messages;
34 import org.openecomp.sdc.common.utils.CommonUtil;
35 import org.openecomp.sdc.common.utils.SdcCommon;
36 import org.openecomp.sdc.datatypes.error.ErrorLevel;
37 import org.openecomp.sdc.datatypes.error.ErrorMessage;
38 import org.openecomp.sdc.healing.api.HealingManager;
39 import org.openecomp.sdc.healing.types.HealCode;
40 import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
41 import org.openecomp.sdc.heat.datatypes.structure.ValidationStructureList;
42 import org.openecomp.sdc.heat.services.tree.HeatTreeManager;
43 import org.openecomp.sdc.heat.services.tree.HeatTreeManagerUtil;
44 import org.openecomp.sdc.logging.api.Logger;
45 import org.openecomp.sdc.logging.api.LoggerFactory;
46 import org.openecomp.sdc.logging.api.annotations.Metrics;
47 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
48 import org.openecomp.sdc.logging.types.LoggerServiceName;
49 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
50 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
51 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
52 import org.openecomp.sdc.validation.util.ValidationManagerUtil;
53 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
54 import org.openecomp.sdc.vendorsoftwareproduct.dao.OrchestrationTemplateDao;
55 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductDao;
56 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
57 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
58 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.UploadData;
59 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
60 import org.openecomp.sdc.vendorsoftwareproduct.errors.OrchestrationTemplateNotFoundErrorBuilder;
61 import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionDataExtractor;
62 import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionEntityDataManager;
63 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.CandidateService;
64 import org.openecomp.sdc.vendorsoftwareproduct.services.utils.CandidateEntityBuilder;
65 import org.openecomp.sdc.vendorsoftwareproduct.types.OrchestrationTemplateActionResponse;
66 import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse;
67 import org.openecomp.sdc.vendorsoftwareproduct.types.ValidationResponse;
68 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
69 import org.openecomp.sdc.vendorsoftwareproduct.utils.VendorSoftwareProductUtils;
70 import org.openecomp.sdc.versioning.dao.types.Version;
71 import org.openecomp.sdcrests.activitylog.types.ActivityType;
72
73 import java.io.ByteArrayInputStream;
74 import java.io.IOException;
75 import java.io.InputStream;
76 import java.nio.ByteBuffer;
77 import java.util.HashMap;
78 import java.util.List;
79 import java.util.Map;
80 import java.util.Optional;
81
82 public class OrchestrationTemplateCandidateManagerImpl
83     implements OrchestrationTemplateCandidateManager {
84   private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
85   private static final Logger logger =
86       LoggerFactory.getLogger(OrchestrationTemplateCandidateManagerImpl.class);
87
88   private VendorSoftwareProductDao vendorSoftwareProductDao;
89   private VendorSoftwareProductInfoDao vspInfoDao;
90   private OrchestrationTemplateDao orchestrationTemplateDataDao;
91   private CandidateService candidateService;
92   private HealingManager healingManager;
93   private CompositionDataExtractor compositionDataExtractor;
94   private ServiceModelDao<ToscaServiceModel, ServiceElement> serviceModelDao;
95   private CompositionEntityDataManager compositionEntityDataManager;
96   private ActivityLogManager activityLogManager;
97
98   public OrchestrationTemplateCandidateManagerImpl(
99       VendorSoftwareProductDao vendorSoftwareProductDao, VendorSoftwareProductInfoDao
100       vspInfoDao,
101       OrchestrationTemplateDao orchestrationTemplateDataDao,
102       CandidateService candidateService, HealingManager healingManager,
103       CompositionDataExtractor compositionDataExtractor,
104       ServiceModelDao<ToscaServiceModel, ServiceElement> serviceModelDao,
105       CompositionEntityDataManager compositionEntityDataManager,
106       ActivityLogManager activityLogManager) {
107     this.vendorSoftwareProductDao = vendorSoftwareProductDao;
108     this.vspInfoDao = vspInfoDao;
109     this.orchestrationTemplateDataDao = orchestrationTemplateDataDao;
110     this.candidateService = candidateService;
111     this.healingManager = healingManager;
112     this.compositionDataExtractor = compositionDataExtractor;
113     this.serviceModelDao = serviceModelDao;
114     this.compositionEntityDataManager = compositionEntityDataManager;
115     this.activityLogManager = activityLogManager;
116   }
117
118   @Override
119   @Metrics
120   public UploadFileResponse upload(String vspId, Version version, InputStream heatFileToUpload,
121                                    String user) {
122     mdcDataDebugMessage.debugEntryMessage("VSP id", vspId);
123
124     VspDetails vspDetails = getVspDetails(vspId, version);
125
126     UploadFileResponse uploadFileResponse = new UploadFileResponse();
127     if (isNotEmptyFileToUpload(heatFileToUpload, uploadFileResponse)) {
128       return uploadFileResponse;
129     }
130
131     byte[] uploadedFileData = FileUtils.toByteArray(heatFileToUpload);
132     if (isInvalidRawZipData(uploadFileResponse, uploadedFileData)) {
133       return uploadFileResponse;
134     }
135
136     Optional<FileContentHandler> optionalContentMap =
137         getZipContentMap(uploadFileResponse, uploadedFileData);
138     if (!optionalContentMap.isPresent()) {
139       logger.error(Messages.ZIP_CONTENT_MAP.getErrorMessage());
140       uploadFileResponse
141           .addStructureError(
142               SdcCommon.UPLOAD_FILE,
143               new ErrorMessage(ErrorLevel.ERROR, Messages.ZIP_CONTENT_MAP.getErrorMessage()));
144
145       mdcDataDebugMessage.debugExitMessage("VSP id", vspId);
146       return uploadFileResponse;
147     }
148
149     if (!MapUtils.isEmpty(uploadFileResponse.getErrors())) {
150
151       mdcDataDebugMessage.debugExitMessage("VSP id", vspId);
152       return uploadFileResponse;
153     }
154     try {
155       OrchestrationTemplateCandidateData candidateData =
156           new CandidateEntityBuilder(candidateService)
157               .buildCandidateEntityFromZip(vspDetails, uploadedFileData, optionalContentMap.get(),
158                   uploadFileResponse.getErrors(), user);
159       candidateService.updateCandidateUploadData(candidateData, vspDetails.getId());
160     } catch (Exception exception) {
161       logger.error(Messages.ZIP_CONTENT_MAP.getErrorMessage());
162       uploadFileResponse
163           .addStructureError(
164               SdcCommon.UPLOAD_FILE,
165               new ErrorMessage(ErrorLevel.ERROR, exception.getMessage()));
166
167       mdcDataDebugMessage.debugExitMessage("VSP id", vspId);
168       return uploadFileResponse;
169     }
170
171     mdcDataDebugMessage.debugExitMessage("VSP id", vspId);
172     return uploadFileResponse;
173   }
174
175   @Override
176   public OrchestrationTemplateActionResponse process(String vspId,
177                                                      Version version, String user) {
178     mdcDataDebugMessage.debugEntryMessage("VSP id", vspId);
179
180     Optional<OrchestrationTemplateCandidateData> candidate =
181         fetchCandidateDataEntity(vspId, version);
182     if (!candidate.isPresent()) {
183       throw new CoreException(new OrchestrationTemplateNotFoundErrorBuilder(vspId).build());
184     }
185
186     OrchestrationTemplateActionResponse response = new OrchestrationTemplateActionResponse();
187     UploadFileResponse uploadFileResponse = new UploadFileResponse();
188     OrchestrationTemplateCandidateData candidateDataEntity = candidate.get();
189     Optional<FileContentHandler> fileContent =
190         getZipContentMap(uploadFileResponse, candidateDataEntity.getContentData().array());
191     if (!fileContent.isPresent()) {
192       response.addStructureErrors(uploadFileResponse.getErrors());
193       mdcDataDebugMessage.debugExitMessage("VSP id", vspId);
194       return response;
195     }
196
197     Map<String, List<ErrorMessage>> uploadErrors = uploadFileResponse.getErrors();
198     FileContentHandler fileContentMap = fileContent.get();
199     FilesDataStructure structure =
200         JsonUtil.json2Object(candidateDataEntity.getFilesDataStructure(), FilesDataStructure.class);
201
202     if (CollectionUtils.isNotEmpty(structure.getUnassigned())) {
203       response.addErrorMessageToMap(SdcCommon.UPLOAD_FILE,
204           Messages.FOUND_UNASSIGNED_FILES.getErrorMessage(), ErrorLevel.ERROR);
205
206       mdcDataDebugMessage.debugExitMessage("VSP id", vspId);
207       return response;
208     }
209
210     VspDetails vspDetails =
211         getVspDetails(vspId, version);
212
213     String manifest = candidateService.createManifest(vspDetails, structure);
214     fileContentMap.addFile(SdcCommon.MANIFEST_NAME, manifest.getBytes());
215
216     HeatStructureTree tree = createAndValidateHeatTree(response, fileContentMap);
217
218     Optional<ByteArrayInputStream> zipByteArrayInputStream = candidateService
219         .fetchZipFileByteArrayInputStream(vspId, candidateDataEntity, manifest, uploadErrors);
220     if (!zipByteArrayInputStream.isPresent()) {
221       return response;
222     }
223     deleteUploadDataAndContent(vspId, version);
224     saveHotData(vspId, version, zipByteArrayInputStream.get(), fileContentMap, tree);
225
226     ToscaServiceModel toscaServiceModel =
227         HeatToToscaUtil.loadAndTranslateTemplateData(fileContentMap)
228             .getToscaServiceModel();
229     if (toscaServiceModel != null) {
230       serviceModelDao.storeServiceModel(vspId, version, toscaServiceModel);
231       compositionEntityDataManager.saveCompositionData(vspId, version,
232           compositionDataExtractor.extractServiceCompositionData(toscaServiceModel));
233     }
234     uploadFileResponse.addStructureErrors(uploadErrors);
235
236     ActivityLogEntity activityLogEntity = new ActivityLogEntity(vspId,  String.valueOf(version.getMajor()+1),
237             ActivityType.UPLOAD_HEAT.toString(), user, true, "", "");
238     activityLogManager.addActionLog(activityLogEntity, user);
239
240     mdcDataDebugMessage.debugExitMessage("VSP id", vspId);
241     return response;
242   }
243
244
245   @Override
246   public Optional<FilesDataStructure> getFilesDataStructure(
247       String vspId, Version version, String user) {
248     mdcDataDebugMessage.debugEntryMessage("VSP id", vspId);
249
250     Optional<FilesDataStructure> candidateFileDataStructure =
251         candidateService.getOrchestrationTemplateCandidateFileDataStructure(vspId, version);
252     if (candidateFileDataStructure.isPresent()) {
253       return candidateFileDataStructure;
254     } else {
255       Map<String, Object> healingParams = getHealingParamsAsMap(vspId, version, user);
256
257       mdcDataDebugMessage
258           .debugExitMessage("VSP id", vspId);
259       return (Optional<FilesDataStructure>) healingManager
260           .heal(HealCode.FILE_DATA_STRUCTURE_HEALER, healingParams);
261     }
262   }
263
264   @Override
265
266   public ValidationResponse updateFilesDataStructure(String vspId,
267                                                      Version version, String user,
268                                                      FilesDataStructure fileDataStructure) {
269     mdcDataDebugMessage.debugEntryMessage("VSP id", vspId);
270
271     ValidationResponse response = new ValidationResponse();
272     Optional<List<ErrorMessage>> validateErrors =
273         candidateService.validateFileDataStructure(fileDataStructure);
274     if (validateErrors.isPresent()) {
275       List<ErrorMessage> errorMessages = validateErrors.get();
276       if (CollectionUtils.isNotEmpty(errorMessages)) {
277         Map<String, List<ErrorMessage>> errorsMap = new HashMap<>();
278         errorsMap.put(SdcCommon.UPLOAD_FILE, errorMessages);
279         response.setUploadDataErrors(errorsMap, LoggerServiceName.Update_Manifest,
280             LoggerTragetServiceName.VALIDATE_FILE_DATA_STRUCTURE);
281
282         mdcDataDebugMessage
283             .debugExitMessage("VSP id", vspId);
284         return response;
285       }
286     }
287     candidateService.updateOrchestrationTemplateCandidateFileDataStructure(vspId, version,
288         fileDataStructure);
289
290     mdcDataDebugMessage
291         .debugExitMessage("VSP id", vspId);
292     return response;
293   }
294
295   @Override
296
297   public Optional<byte[]> get(String vspId, Version version, String user)
298       throws IOException {
299     mdcDataDebugMessage.debugEntryMessage("VSP id", vspId);
300
301     VspDetails vspDetails =
302         getVspDetails(vspId, version);
303
304     Optional<OrchestrationTemplateCandidateData> candidateDataEntity =
305         fetchCandidateDataEntity(vspId, version);
306
307     if (!candidateDataEntity.isPresent()) {
308       ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR,
309           Messages.NO_ZIP_FILE_WAS_UPLOADED_OR_ZIP_NOT_EXIST.getErrorMessage());
310       logger.error(errorMessage.getMessage());
311
312       mdcDataDebugMessage
313           .debugExitMessage("VSP id", vspId);
314       return Optional.empty();
315     }
316
317     FilesDataStructure structure = JsonUtil
318         .json2Object(candidateDataEntity.get().getFilesDataStructure(), FilesDataStructure.class);
319     String manifest = candidateService.createManifest(vspDetails, structure);
320
321     mdcDataDebugMessage
322         .debugExitMessage("VSP id", vspId);
323     return Optional.ofNullable(candidateService
324         .replaceManifestInZip(candidateDataEntity.get().getContentData(), manifest, vspId));
325   }
326
327   private Optional<OrchestrationTemplateCandidateData> fetchCandidateDataEntity(
328       String vspId, Version version) {
329     return Optional
330         .ofNullable(candidateService.getOrchestrationTemplateCandidate(vspId, version));
331   }
332
333   private HeatStructureTree createAndValidateHeatTree(OrchestrationTemplateActionResponse response,
334                                                       FileContentHandler fileContentMap) {
335     VendorSoftwareProductUtils.addFileNamesToUploadFileResponse(fileContentMap, response);
336     Map<String, List<ErrorMessage>> validationErrors =
337         ValidationManagerUtil.initValidationManager(fileContentMap).validate();
338     response.getErrors().putAll(validationErrors);
339
340     HeatTreeManager heatTreeManager = HeatTreeManagerUtil.initHeatTreeManager(fileContentMap);
341     heatTreeManager.createTree();
342     heatTreeManager.addErrors(validationErrors);
343     return heatTreeManager.getTree();
344   }
345
346   private void saveHotData(String vspId, Version activeVersion, InputStream uploadedFileData,
347                            FileContentHandler fileContentMap, HeatStructureTree tree) {
348     Map<String, Object> manifestAsMap =
349         (Map<String, Object>) JsonUtil.json2Object(fileContentMap.getFileContent(
350             SdcCommon.MANIFEST_NAME), Map.class);
351
352     UploadData uploadData = new UploadData();
353     uploadData.setPackageName((String) manifestAsMap.get("name"));
354     uploadData.setPackageVersion((String) manifestAsMap.get("version"));
355     uploadData.setContentData(ByteBuffer.wrap(FileUtils.toByteArray(uploadedFileData)));
356     uploadData.setValidationDataStructure(new ValidationStructureList(tree));
357     orchestrationTemplateDataDao.updateOrchestrationTemplateData(vspId, uploadData);
358   }
359
360   private void deleteUploadDataAndContent(String vspId, Version version) {
361     //fixme change this when more tables are zusammenized
362     vendorSoftwareProductDao.deleteUploadData(vspId, version);
363   }
364
365   private boolean isInvalidRawZipData(UploadFileResponse uploadFileResponse,
366                                       byte[] uploadedFileData) {
367     Optional<ErrorMessage> errorMessage;
368     errorMessage = candidateService.validateRawZipData(uploadedFileData);
369     if (errorMessage.isPresent()) {
370       uploadFileResponse.addStructureError(SdcCommon.UPLOAD_FILE, errorMessage.get());
371       return true;
372     }
373     return false;
374   }
375
376   private boolean isNotEmptyFileToUpload(InputStream heatFileToUpload,
377                                          UploadFileResponse uploadFileResponse) {
378     Optional<ErrorMessage> errorMessage =
379         candidateService.validateNonEmptyFileToUpload(heatFileToUpload);
380     if (errorMessage.isPresent()) {
381       uploadFileResponse.addStructureError(SdcCommon.UPLOAD_FILE, errorMessage.get());
382       return true;
383     }
384     return false;
385   }
386
387   private Optional<FileContentHandler> getZipContentMap(UploadFileResponse uploadFileResponse,
388                                                         byte[] uploadedFileData) {
389     FileContentHandler contentMap = null;
390     try {
391       contentMap = CommonUtil.loadUploadFileContent(uploadedFileData);
392     } catch (IOException exception) {
393       uploadFileResponse.addStructureError(
394           SdcCommon.UPLOAD_FILE,
395           new ErrorMessage(ErrorLevel.ERROR, Messages.INVALID_ZIP_FILE.getErrorMessage()));
396     } catch (CoreException coreException) {
397       uploadFileResponse.addStructureError(
398           SdcCommon.UPLOAD_FILE, new ErrorMessage(ErrorLevel.ERROR, coreException.getMessage()));
399     }
400     return Optional.ofNullable(contentMap);
401   }
402
403   // todo *************************** move to reusable place! *************************
404
405   private Map<String, Object> getHealingParamsAsMap(String vspId, Version version, String user) {
406     Map<String, Object> healingParams = new HashMap<>();
407
408     healingParams.put(SdcCommon.VSP_ID, vspId);
409     healingParams.put(SdcCommon.VERSION, version);
410     healingParams.put(SdcCommon.USER, user);
411
412     return healingParams;
413   }
414
415   public VspDetails getVspDetails(String vspId, Version version) {
416     VspDetails vspDetails = vspInfoDao.get(new VspDetails(vspId, version));
417     vspDetails.setValidationData(orchestrationTemplateDataDao.getValidationData(vspId, version));
418     return vspDetails;
419   }
420
421 }