2 * Copyright © 2016-2018 European Support Limited
3 * Copyright © 2021 Nokia
4 * Copyright © 2021 Nordix Foundation
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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 * ================================================================================
22 package org.openecomp.sdcrests.vsp.rest.services;
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;
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;
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;
96 @Service("orchestrationTemplateCandidate")
97 @Scope(value = "prototype")
98 public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplateCandidate {
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;
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;
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;
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;
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();
152 fileToUploadBytes = fileToUpload.getObject(byte[].class);
155 vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInValidation(vspId, versionId, user);
156 final var onboardingPackageProcessor =
157 new OnboardingPackageProcessor(filename, fileToUploadBytes, new CnfPackageValidator(), artifactInfo);
158 final ErrorMessage[] errorMessages = onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]);
159 if (onboardingPackageProcessor.hasErrors()) {
160 orchestrationTemplateCandidateUploadManager
161 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
162 return Response.status(NOT_ACCEPTABLE).entity(buildUploadResponseWithError(errorMessages)).build();
164 final var onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
165 if (onboardPackageInfo == null) {
166 final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError(
167 new ErrorMessage(ErrorLevel.ERROR, PACKAGE_PROCESS_ERROR.formatMessage(filename)));
168 orchestrationTemplateCandidateUploadManager
169 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
170 return Response.ok(uploadFileResponseDto).build();
172 final var version = new Version(versionId);
173 final var vspDetails = vendorSoftwareProductManager.getVsp(vspId, version);
174 vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInProcessing(vspId, versionId, user);
175 response = processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages);
176 final UploadFileResponseDto entity = (UploadFileResponseDto) response.getEntity();
177 if (artifactStorageManager.isEnabled()) {
178 if (entity.getErrors().isEmpty()) {
179 artifactStorageManager.put(vspId, versionId + ".reduced", new ByteArrayInputStream(fileToUploadBytes));
181 artifactStorageManager.delete(artifactInfo);
184 orchestrationTemplateCandidateUploadManager
185 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.SUCCESS, user);
186 } catch (final Exception ex) {
187 if (vspUploadStatus != null) {
188 orchestrationTemplateCandidateUploadManager
189 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
196 private ArtifactInfo handleArtifactStorage(final String vspId, final String versionId, final String filename,
197 final DataHandler artifactDataHandler) {
198 final Path tempArtifactPath;
200 final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration();
202 final Path folder = Path.of(storageConfiguration.getTempPath()).resolve(vspId).resolve(versionId);
203 tempArtifactPath = folder.resolve(UUID.randomUUID().toString());
204 Files.createDirectories(folder);
205 try (final InputStream packageInputStream = artifactDataHandler.getInputStream();
206 final var fileOutputStream = new FileOutputStream(tempArtifactPath.toFile())) {
207 packageInputStream.transferTo(fileOutputStream);
209 } catch (final Exception e) {
210 throw new ArtifactStorageException(UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename));
212 final ArtifactInfo artifactInfo;
213 try (final InputStream inputStream = Files.newInputStream(tempArtifactPath)) {
214 artifactInfo = artifactStorageManager.upload(vspId, versionId, inputStream);
215 } catch (final Exception e) {
216 LOGGER.error("Package Size Reducer not configured", e);
217 throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT.formatMessage(filename));
220 artifactInfo.setBytes(packageSizeReducer.reduce(tempArtifactPath));
221 Files.delete(tempArtifactPath);
222 } catch (final Exception e) {
223 LOGGER.error("Package Size Reducer not configured", e);
224 throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(filename));
229 private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails,
230 final ErrorMessage... errorMessages) {
231 final UploadFileResponse uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo);
232 final UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto()
233 .applyMapping(uploadFileResponse, UploadFileResponseDto.class);
234 if (errorMessages.length > 0) {
235 uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
237 return Response.ok(uploadFileResponseDto).build();
240 private Map<String, List<ErrorMessage>> getErrorMap(ErrorMessage[] errorMessages) {
241 final Map<String, List<ErrorMessage>> errorMap = new HashMap<>();
242 final List<ErrorMessage> errorMessageList = new ArrayList<>();
243 Collections.addAll(errorMessageList, errorMessages);
244 errorMap.put(SdcCommon.UPLOAD_FILE, errorMessageList);
248 private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) {
249 final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto();
250 uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
251 return uploadFileResponseDto;
255 public Response get(String vspId, String versionId, String user) throws IOException {
256 Optional<Pair<String, byte[]>> zipFile = candidateManager.get(vspId, new Version(versionId));
258 if (zipFile.isPresent()) {
259 fileName = "Candidate." + zipFile.get().getLeft();
261 zipFile = vendorSoftwareProductManager.get(vspId, new Version((versionId)));
262 if (zipFile.isEmpty()) {
263 ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR,
264 getErrorWithParameters(NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(), ""));
265 LOGGER.error(errorMessage.getMessage());
266 return Response.status(NOT_FOUND).build();
268 fileName = "Processed." + zipFile.get().getLeft();
270 Response.ResponseBuilder response = Response.ok(zipFile.get().getRight());
271 response.header("Content-Disposition", "attachment; filename=" + fileName);
272 return response.build();
276 public Response abort(String vspId, String versionId) {
277 candidateManager.abort(vspId, new Version(versionId));
278 return Response.ok().build();
282 public Response process(String vspId, String versionId, String user) {
283 Version version = new Version(versionId);
284 OrchestrationTemplateActionResponse response = candidateManager.process(vspId, version);
285 activityLogManager.logActivity(new ActivityLogEntity(vspId, version, ActivityType.Upload_Network_Package, user, true, "", ""));
286 OrchestrationTemplateActionResponseDto responseDto = copyOrchestrationTemplateActionResponseToDto(response);
287 return Response.ok(responseDto).build();
291 public Response updateFilesDataStructure(String vspId, String versionId, FileDataStructureDto fileDataStructureDto, String user) {
292 FilesDataStructure fileDataStructure = copyFilesDataStructureDtoToFilesDataStructure(fileDataStructureDto);
293 ValidationResponse response = candidateManager.updateFilesDataStructure(vspId, new Version(versionId), fileDataStructure);
294 if (!response.isValid()) {
295 return Response.status(EXPECTATION_FAILED)
296 .entity(new MapValidationResponseToDto().applyMapping(response, ValidationResponseDto.class))
299 return Response.ok(fileDataStructureDto).build();
303 public Response getFilesDataStructure(String vspId, String versionId, String user) {
304 Optional<FilesDataStructure> filesDataStructure = candidateManager.getFilesDataStructure(vspId, new Version(versionId));
305 if (filesDataStructure.isEmpty()) {
306 filesDataStructure = vendorSoftwareProductManager.getOrchestrationTemplateStructure(vspId, new Version(versionId));
308 FileDataStructureDto fileDataStructureDto = filesDataStructure
309 .map(dataStructure -> new MapFilesDataStructureToDto().applyMapping(dataStructure, FileDataStructureDto.class))
310 .orElse(new FileDataStructureDto());
311 return Response.ok(fileDataStructureDto).build();
314 private OrchestrationTemplateActionResponseDto copyOrchestrationTemplateActionResponseToDto(OrchestrationTemplateActionResponse response) {
315 OrchestrationTemplateActionResponseDto result = new OrchestrationTemplateActionResponseDto();
316 result.setErrors(response.getErrors());
317 result.setFileNames(response.getFileNames());
318 result.setStatus(response.getStatus());
322 private FilesDataStructure copyFilesDataStructureDtoToFilesDataStructure(FileDataStructureDto fileDataStructureDto) {
323 FilesDataStructure filesDataStructure = new FilesDataStructure();
324 filesDataStructure.setArtifacts(fileDataStructureDto.getArtifacts());
325 filesDataStructure.setModules(fileDataStructureDto.getModules());
326 filesDataStructure.setNested(fileDataStructureDto.getNested());
327 filesDataStructure.setUnassigned(fileDataStructureDto.getUnassigned());
328 return filesDataStructure;