6615447c6f5a42782b224198ff444f9e3da24daa
[sdc.git] / openecomp-be / api / openecomp-sdc-rest-webapp / vendor-software-products-rest / vendor-software-products-rest-services / src / main / java / org / openecomp / sdcrests / vsp / rest / services / OrchestrationTemplateCandidateImpl.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  * Copyright © 2021 Nokia
4  * Copyright © 2021 Nordix Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  * ============LICENSE_END=========================================================
18  * Modifications copyright (c) 2019 Nokia
19  * Modifications copyright (c) 2021 Nordix Foundation
20  * ================================================================================
21  */
22 package org.openecomp.sdcrests.vsp.rest.services;
23
24 import static javax.ws.rs.core.Response.Status.EXPECTATION_FAILED;
25 import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE;
26 import static javax.ws.rs.core.Response.Status.NOT_FOUND;
27 import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters;
28 import static org.openecomp.sdc.common.errors.Messages.ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT;
29 import static org.openecomp.sdc.common.errors.Messages.ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE;
30 import static org.openecomp.sdc.common.errors.Messages.NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST;
31 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_PROCESS_ERROR;
32 import static org.openecomp.sdc.common.errors.Messages.UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING;
33
34 import java.io.ByteArrayInputStream;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.nio.file.Files;
39 import java.nio.file.Path;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Optional;
46 import java.util.UUID;
47 import javax.activation.DataHandler;
48 import javax.inject.Named;
49 import javax.ws.rs.core.Response;
50 import org.apache.commons.lang3.tuple.Pair;
51 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
52 import org.openecomp.sdc.activitylog.ActivityLogManager;
53 import org.openecomp.sdc.activitylog.ActivityLogManagerFactory;
54 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
55 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
56 import org.openecomp.sdc.be.csar.storage.ArtifactInfo;
57 import org.openecomp.sdc.be.csar.storage.ArtifactStorageConfig;
58 import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager;
59 import org.openecomp.sdc.be.csar.storage.PackageSizeReducer;
60 import org.openecomp.sdc.be.csar.storage.StorageFactory;
61 import org.openecomp.sdc.be.csar.storage.exception.ArtifactStorageException;
62 import org.openecomp.sdc.common.util.ValidationUtils;
63 import org.openecomp.sdc.common.utils.SdcCommon;
64 import org.openecomp.sdc.datatypes.error.ErrorLevel;
65 import org.openecomp.sdc.datatypes.error.ErrorMessage;
66 import org.openecomp.sdc.logging.api.Logger;
67 import org.openecomp.sdc.logging.api.LoggerFactory;
68 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
69 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory;
70 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager;
71 import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory;
72 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
73 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatus;
74 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor;
75 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator;
76 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
77 import org.openecomp.sdc.vendorsoftwareproduct.types.OrchestrationTemplateActionResponse;
78 import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse;
79 import org.openecomp.sdc.vendorsoftwareproduct.types.ValidationResponse;
80 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
81 import org.openecomp.sdc.versioning.dao.types.Version;
82 import org.openecomp.sdcrests.vendorsoftwareproducts.types.FileDataStructureDto;
83 import org.openecomp.sdcrests.vendorsoftwareproducts.types.OrchestrationTemplateActionResponseDto;
84 import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto;
85 import org.openecomp.sdcrests.vendorsoftwareproducts.types.ValidationResponseDto;
86 import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspUploadStatusDto;
87 import org.openecomp.sdcrests.vsp.rest.OrchestrationTemplateCandidate;
88 import org.openecomp.sdcrests.vsp.rest.mapping.MapFilesDataStructureToDto;
89 import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFileResponseDto;
90 import org.openecomp.sdcrests.vsp.rest.mapping.MapValidationResponseToDto;
91 import org.springframework.beans.factory.annotation.Autowired;
92 import org.springframework.context.annotation.Scope;
93 import org.springframework.stereotype.Service;
94
95 @Named
96 @Service("orchestrationTemplateCandidate")
97 @Scope(value = "prototype")
98 public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplateCandidate {
99
100     private static final Logger LOGGER = LoggerFactory.getLogger(OrchestrationTemplateCandidateImpl.class);
101     private final OrchestrationTemplateCandidateManager candidateManager;
102     private final VendorSoftwareProductManager vendorSoftwareProductManager;
103     private final ActivityLogManager activityLogManager;
104     private final ArtifactStorageManager artifactStorageManager;
105     private final PackageSizeReducer packageSizeReducer;
106     private final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager;
107
108     @Autowired
109     public OrchestrationTemplateCandidateImpl(final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager) {
110         this.candidateManager = OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface();
111         this.vendorSoftwareProductManager = VspManagerFactory.getInstance().createInterface();
112         this.activityLogManager = ActivityLogManagerFactory.getInstance().createInterface();
113         LOGGER.info("Instantiating artifactStorageManager");
114         final StorageFactory storageFactory = new StorageFactory();
115         this.artifactStorageManager = storageFactory.createArtifactStorageManager();
116         LOGGER.info("Instantiating packageSizeReducer");
117         this.packageSizeReducer = storageFactory.createPackageSizeReducer().orElse(null);
118         this.orchestrationTemplateCandidateUploadManager = orchestrationTemplateCandidateUploadManager;
119     }
120
121     // Constructor used in test to avoid mock static
122     public OrchestrationTemplateCandidateImpl(final OrchestrationTemplateCandidateManager candidateManager,
123                                               final VendorSoftwareProductManager vendorSoftwareProductManager,
124                                               final ActivityLogManager activityLogManager,
125                                               final ArtifactStorageManager artifactStorageManager,
126                                               final PackageSizeReducer packageSizeReducer,
127                                               final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager) {
128         this.candidateManager = candidateManager;
129         this.vendorSoftwareProductManager = vendorSoftwareProductManager;
130         this.activityLogManager = activityLogManager;
131         this.artifactStorageManager = artifactStorageManager;
132         this.packageSizeReducer = packageSizeReducer;
133         this.orchestrationTemplateCandidateUploadManager = orchestrationTemplateCandidateUploadManager;
134     }
135
136     @Override
137     public Response upload(String vspId, String versionId, final Attachment fileToUpload, final String user) {
138         vspId = ValidationUtils.sanitizeInputString(vspId);
139         versionId = ValidationUtils.sanitizeInputString(versionId);
140         final Response response;
141         VspUploadStatusDto vspUploadStatus = null;
142         try {
143             vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInProgress(vspId, versionId, user);
144             final byte[] fileToUploadBytes;
145             final DataHandler dataHandler = fileToUpload.getDataHandler();
146             final var filename = ValidationUtils.sanitizeInputString(dataHandler.getName());
147             ArtifactInfo artifactInfo = null;
148             if (artifactStorageManager.isEnabled()) {
149                 artifactInfo = handleArtifactStorage(vspId, versionId, filename, dataHandler);
150                 fileToUploadBytes = artifactInfo.getBytes();
151             } else {
152                 fileToUploadBytes = fileToUpload.getObject(byte[].class);
153             }
154
155
156             vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInValidation(vspId, versionId, user);
157             final var onboardingPackageProcessor =
158                 new OnboardingPackageProcessor(filename, fileToUploadBytes, new CnfPackageValidator(), artifactInfo);
159             final ErrorMessage[] errorMessages = onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]);
160             if (onboardingPackageProcessor.hasErrors()) {
161                 return Response.status(NOT_ACCEPTABLE).entity(buildUploadResponseWithError(errorMessages)).build();
162             }
163             final var onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
164             if (onboardPackageInfo == null) {
165                 final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError(
166                     new ErrorMessage(ErrorLevel.ERROR, PACKAGE_PROCESS_ERROR.formatMessage(filename)));
167                 return Response.ok(uploadFileResponseDto).build();
168             }
169             final var version = new Version(versionId);
170             final var vspDetails = vendorSoftwareProductManager.getVsp(vspId, version);
171             vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInProcessing(vspId, versionId, user);
172             response = processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages);
173             final UploadFileResponseDto entity = (UploadFileResponseDto) response.getEntity();
174             if (artifactStorageManager.isEnabled()) {
175                 if (entity.getErrors().isEmpty()) {
176                     artifactStorageManager.put(vspId, versionId + ".reduced", new ByteArrayInputStream(fileToUploadBytes));
177                 } else {
178                     artifactStorageManager.delete(artifactInfo);
179                 }
180             }
181             orchestrationTemplateCandidateUploadManager
182                 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.SUCCESS, user);
183         } catch (final Exception ex) {
184             if (vspUploadStatus != null) {
185                 orchestrationTemplateCandidateUploadManager
186                     .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
187             }
188             throw ex;
189         }
190         return response;
191     }
192
193     private ArtifactInfo handleArtifactStorage(final String vspId, final String versionId, final String filename,
194                                                final DataHandler artifactDataHandler) {
195         final Path tempArtifactPath;
196         try {
197             final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration();
198
199             final Path folder = Path.of(storageConfiguration.getTempPath()).resolve(vspId).resolve(versionId);
200             tempArtifactPath = folder.resolve(UUID.randomUUID().toString());
201             Files.createDirectories(folder);
202             try (final InputStream packageInputStream = artifactDataHandler.getInputStream();
203                 final var fileOutputStream = new FileOutputStream(tempArtifactPath.toFile())) {
204                 packageInputStream.transferTo(fileOutputStream);
205             }
206         } catch (final Exception e) {
207             throw new ArtifactStorageException(UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename));
208         }
209         final ArtifactInfo artifactInfo;
210         try (final InputStream inputStream = Files.newInputStream(tempArtifactPath)) {
211             artifactInfo = artifactStorageManager.upload(vspId, versionId, inputStream);
212         } catch (final Exception e) {
213             LOGGER.error("Package Size Reducer not configured", e);
214             throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT.formatMessage(filename));
215         }
216         try {
217             artifactInfo.setBytes(packageSizeReducer.reduce(tempArtifactPath));
218             Files.delete(tempArtifactPath);
219         } catch (final Exception e) {
220             LOGGER.error("Package Size Reducer not configured", e);
221             throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(filename));
222         }
223         return artifactInfo;
224     }
225
226     private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails,
227                                            final ErrorMessage... errorMessages) {
228         final UploadFileResponse uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo);
229         final UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto()
230             .applyMapping(uploadFileResponse, UploadFileResponseDto.class);
231         if (errorMessages.length > 0) {
232             uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
233         }
234         return Response.ok(uploadFileResponseDto).build();
235     }
236
237     private Map<String, List<ErrorMessage>> getErrorMap(ErrorMessage[] errorMessages) {
238         final Map<String, List<ErrorMessage>> errorMap = new HashMap<>();
239         final List<ErrorMessage> errorMessageList = new ArrayList<>();
240         Collections.addAll(errorMessageList, errorMessages);
241         errorMap.put(SdcCommon.UPLOAD_FILE, errorMessageList);
242         return errorMap;
243     }
244
245     private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) {
246         final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto();
247         uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
248         return uploadFileResponseDto;
249     }
250
251     @Override
252     public Response get(String vspId, String versionId, String user) throws IOException {
253         Optional<Pair<String, byte[]>> zipFile = candidateManager.get(vspId, new Version(versionId));
254         String fileName;
255         if (zipFile.isPresent()) {
256             fileName = "Candidate." + zipFile.get().getLeft();
257         } else {
258             zipFile = vendorSoftwareProductManager.get(vspId, new Version((versionId)));
259             if (zipFile.isEmpty()) {
260                 ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR,
261                     getErrorWithParameters(NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(), ""));
262                 LOGGER.error(errorMessage.getMessage());
263                 return Response.status(NOT_FOUND).build();
264             }
265             fileName = "Processed." + zipFile.get().getLeft();
266         }
267         Response.ResponseBuilder response = Response.ok(zipFile.get().getRight());
268         response.header("Content-Disposition", "attachment; filename=" + fileName);
269         return response.build();
270     }
271
272     @Override
273     public Response abort(String vspId, String versionId) {
274         candidateManager.abort(vspId, new Version(versionId));
275         return Response.ok().build();
276     }
277
278     @Override
279     public Response process(String vspId, String versionId, String user) {
280         Version version = new Version(versionId);
281         OrchestrationTemplateActionResponse response = candidateManager.process(vspId, version);
282         activityLogManager.logActivity(new ActivityLogEntity(vspId, version, ActivityType.Upload_Network_Package, user, true, "", ""));
283         OrchestrationTemplateActionResponseDto responseDto = copyOrchestrationTemplateActionResponseToDto(response);
284         return Response.ok(responseDto).build();
285     }
286
287     @Override
288     public Response updateFilesDataStructure(String vspId, String versionId, FileDataStructureDto fileDataStructureDto, String user) {
289         FilesDataStructure fileDataStructure = copyFilesDataStructureDtoToFilesDataStructure(fileDataStructureDto);
290         ValidationResponse response = candidateManager.updateFilesDataStructure(vspId, new Version(versionId), fileDataStructure);
291         if (!response.isValid()) {
292             return Response.status(EXPECTATION_FAILED)
293                 .entity(new MapValidationResponseToDto().applyMapping(response, ValidationResponseDto.class))
294                 .build();
295         }
296         return Response.ok(fileDataStructureDto).build();
297     }
298
299     @Override
300     public Response getFilesDataStructure(String vspId, String versionId, String user) {
301         Optional<FilesDataStructure> filesDataStructure = candidateManager.getFilesDataStructure(vspId, new Version(versionId));
302         if (filesDataStructure.isEmpty()) {
303             filesDataStructure = vendorSoftwareProductManager.getOrchestrationTemplateStructure(vspId, new Version(versionId));
304         }
305         FileDataStructureDto fileDataStructureDto = filesDataStructure
306             .map(dataStructure -> new MapFilesDataStructureToDto().applyMapping(dataStructure, FileDataStructureDto.class))
307             .orElse(new FileDataStructureDto());
308         return Response.ok(fileDataStructureDto).build();
309     }
310
311     private OrchestrationTemplateActionResponseDto copyOrchestrationTemplateActionResponseToDto(OrchestrationTemplateActionResponse response) {
312         OrchestrationTemplateActionResponseDto result = new OrchestrationTemplateActionResponseDto();
313         result.setErrors(response.getErrors());
314         result.setFileNames(response.getFileNames());
315         result.setStatus(response.getStatus());
316         return result;
317     }
318
319     private FilesDataStructure copyFilesDataStructureDtoToFilesDataStructure(FileDataStructureDto fileDataStructureDto) {
320         FilesDataStructure filesDataStructure = new FilesDataStructure();
321         filesDataStructure.setArtifacts(fileDataStructureDto.getArtifacts());
322         filesDataStructure.setModules(fileDataStructureDto.getModules());
323         filesDataStructure.setNested(fileDataStructureDto.getNested());
324         filesDataStructure.setUnassigned(fileDataStructureDto.getUnassigned());
325         return filesDataStructure;
326     }
327 }