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 final var onboardingPackageProcessor =
156 new OnboardingPackageProcessor(filename, fileToUploadBytes, new CnfPackageValidator(), artifactInfo);
157 final ErrorMessage[] errorMessages = onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]);
158 if (onboardingPackageProcessor.hasErrors()) {
159 return Response.status(NOT_ACCEPTABLE).entity(buildUploadResponseWithError(errorMessages)).build();
161 final var onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
162 if (onboardPackageInfo == null) {
163 final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError(
164 new ErrorMessage(ErrorLevel.ERROR, PACKAGE_PROCESS_ERROR.formatMessage(filename)));
165 return Response.ok(uploadFileResponseDto).build();
167 final var version = new Version(versionId);
168 final var vspDetails = vendorSoftwareProductManager.getVsp(vspId, version);
169 response = processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages);
170 final UploadFileResponseDto entity = (UploadFileResponseDto) response.getEntity();
171 if (artifactStorageManager.isEnabled()) {
172 if (!entity.getErrors().isEmpty()) {
173 artifactStorageManager.delete(artifactInfo);
175 artifactStorageManager.put(vspId, versionId + ".reduced", new ByteArrayInputStream(fileToUploadBytes));
178 orchestrationTemplateCandidateUploadManager
179 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.SUCCESS, user);
180 } catch (final Exception ex) {
181 if (vspUploadStatus != null) {
182 orchestrationTemplateCandidateUploadManager
183 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
190 private ArtifactInfo handleArtifactStorage(final String vspId, final String versionId, final String filename,
191 final DataHandler artifactDataHandler) {
192 final Path tempArtifactPath;
194 final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration();
196 final Path folder = Path.of(storageConfiguration.getTempPath()).resolve(vspId).resolve(versionId);
197 tempArtifactPath = folder.resolve(UUID.randomUUID().toString());
198 Files.createDirectories(folder);
199 try (final InputStream packageInputStream = artifactDataHandler.getInputStream();
200 final var fileOutputStream = new FileOutputStream(tempArtifactPath.toFile())) {
201 packageInputStream.transferTo(fileOutputStream);
203 } catch (final Exception e) {
204 throw new ArtifactStorageException(UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename));
206 final ArtifactInfo artifactInfo;
207 try (final InputStream inputStream = Files.newInputStream(tempArtifactPath)) {
208 artifactInfo = artifactStorageManager.upload(vspId, versionId, inputStream);
209 } catch (final Exception e) {
210 LOGGER.error("Package Size Reducer not configured", e);
211 throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT.formatMessage(filename));
214 artifactInfo.setBytes(packageSizeReducer.reduce(tempArtifactPath));
215 Files.delete(tempArtifactPath);
216 } catch (final Exception e) {
217 LOGGER.error("Package Size Reducer not configured", e);
218 throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(filename));
223 private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails,
224 final ErrorMessage... errorMessages) {
225 final UploadFileResponse uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo);
226 final UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto()
227 .applyMapping(uploadFileResponse, UploadFileResponseDto.class);
228 if (errorMessages.length > 0) {
229 uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
231 return Response.ok(uploadFileResponseDto).build();
234 private Map<String, List<ErrorMessage>> getErrorMap(ErrorMessage[] errorMessages) {
235 final Map<String, List<ErrorMessage>> errorMap = new HashMap<>();
236 final List<ErrorMessage> errorMessageList = new ArrayList<>();
237 Collections.addAll(errorMessageList, errorMessages);
238 errorMap.put(SdcCommon.UPLOAD_FILE, errorMessageList);
242 private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) {
243 final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto();
244 uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
245 return uploadFileResponseDto;
249 public Response get(String vspId, String versionId, String user) throws IOException {
250 Optional<Pair<String, byte[]>> zipFile = candidateManager.get(vspId, new Version(versionId));
252 if (zipFile.isPresent()) {
253 fileName = "Candidate." + zipFile.get().getLeft();
255 zipFile = vendorSoftwareProductManager.get(vspId, new Version((versionId)));
256 if (zipFile.isEmpty()) {
257 ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR,
258 getErrorWithParameters(NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(), ""));
259 LOGGER.error(errorMessage.getMessage());
260 return Response.status(NOT_FOUND).build();
262 fileName = "Processed." + zipFile.get().getLeft();
264 Response.ResponseBuilder response = Response.ok(zipFile.get().getRight());
265 response.header("Content-Disposition", "attachment; filename=" + fileName);
266 return response.build();
270 public Response abort(String vspId, String versionId) {
271 candidateManager.abort(vspId, new Version(versionId));
272 return Response.ok().build();
276 public Response process(String vspId, String versionId, String user) {
277 Version version = new Version(versionId);
278 OrchestrationTemplateActionResponse response = candidateManager.process(vspId, version);
279 activityLogManager.logActivity(new ActivityLogEntity(vspId, version, ActivityType.Upload_Network_Package, user, true, "", ""));
280 OrchestrationTemplateActionResponseDto responseDto = copyOrchestrationTemplateActionResponseToDto(response);
281 return Response.ok(responseDto).build();
285 public Response updateFilesDataStructure(String vspId, String versionId, FileDataStructureDto fileDataStructureDto, String user) {
286 FilesDataStructure fileDataStructure = copyFilesDataStructureDtoToFilesDataStructure(fileDataStructureDto);
287 ValidationResponse response = candidateManager.updateFilesDataStructure(vspId, new Version(versionId), fileDataStructure);
288 if (!response.isValid()) {
289 return Response.status(EXPECTATION_FAILED)
290 .entity(new MapValidationResponseToDto().applyMapping(response, ValidationResponseDto.class))
293 return Response.ok(fileDataStructureDto).build();
297 public Response getFilesDataStructure(String vspId, String versionId, String user) {
298 Optional<FilesDataStructure> filesDataStructure = candidateManager.getFilesDataStructure(vspId, new Version(versionId));
299 if (filesDataStructure.isEmpty()) {
300 filesDataStructure = vendorSoftwareProductManager.getOrchestrationTemplateStructure(vspId, new Version(versionId));
302 FileDataStructureDto fileDataStructureDto = filesDataStructure
303 .map(dataStructure -> new MapFilesDataStructureToDto().applyMapping(dataStructure, FileDataStructureDto.class))
304 .orElse(new FileDataStructureDto());
305 return Response.ok(fileDataStructureDto).build();
308 private OrchestrationTemplateActionResponseDto copyOrchestrationTemplateActionResponseToDto(OrchestrationTemplateActionResponse response) {
309 OrchestrationTemplateActionResponseDto result = new OrchestrationTemplateActionResponseDto();
310 result.setErrors(response.getErrors());
311 result.setFileNames(response.getFileNames());
312 result.setStatus(response.getStatus());
316 private FilesDataStructure copyFilesDataStructureDtoToFilesDataStructure(FileDataStructureDto fileDataStructureDto) {
317 FilesDataStructure filesDataStructure = new FilesDataStructure();
318 filesDataStructure.setArtifacts(fileDataStructureDto.getArtifacts());
319 filesDataStructure.setModules(fileDataStructureDto.getModules());
320 filesDataStructure.setNested(fileDataStructureDto.getNested());
321 filesDataStructure.setUnassigned(fileDataStructureDto.getUnassigned());
322 return filesDataStructure;