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.FileInputStream;
36 import java.io.FileOutputStream;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.nio.file.Files;
40 import java.nio.file.Path;
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.List;
46 import java.util.Optional;
47 import java.util.UUID;
48 import javax.activation.DataHandler;
49 import javax.inject.Named;
50 import javax.ws.rs.core.Response;
51 import org.apache.commons.lang3.tuple.Pair;
52 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
53 import org.openecomp.sdc.activitylog.ActivityLogManager;
54 import org.openecomp.sdc.activitylog.ActivityLogManagerFactory;
55 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
56 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
57 import org.openecomp.sdc.be.csar.storage.ArtifactInfo;
58 import org.openecomp.sdc.be.csar.storage.ArtifactStorageConfig;
59 import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager;
60 import org.openecomp.sdc.be.csar.storage.PackageSizeReducer;
61 import org.openecomp.sdc.be.csar.storage.StorageFactory;
62 import org.openecomp.sdc.be.csar.storage.exception.ArtifactStorageException;
63 import org.openecomp.sdc.common.util.ValidationUtils;
64 import org.openecomp.sdc.common.utils.SdcCommon;
65 import org.openecomp.sdc.datatypes.error.ErrorLevel;
66 import org.openecomp.sdc.datatypes.error.ErrorMessage;
67 import org.openecomp.sdc.logging.api.Logger;
68 import org.openecomp.sdc.logging.api.LoggerFactory;
69 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
70 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory;
71 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager;
72 import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory;
73 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
74 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatus;
75 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor;
76 import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator;
77 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
78 import org.openecomp.sdc.vendorsoftwareproduct.types.OrchestrationTemplateActionResponse;
79 import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse;
80 import org.openecomp.sdc.vendorsoftwareproduct.types.ValidationResponse;
81 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
82 import org.openecomp.sdc.versioning.dao.types.Version;
83 import org.openecomp.sdcrests.vendorsoftwareproducts.types.FileDataStructureDto;
84 import org.openecomp.sdcrests.vendorsoftwareproducts.types.OrchestrationTemplateActionResponseDto;
85 import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto;
86 import org.openecomp.sdcrests.vendorsoftwareproducts.types.ValidationResponseDto;
87 import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspUploadStatusDto;
88 import org.openecomp.sdcrests.vsp.rest.OrchestrationTemplateCandidate;
89 import org.openecomp.sdcrests.vsp.rest.mapping.MapFilesDataStructureToDto;
90 import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFileResponseDto;
91 import org.openecomp.sdcrests.vsp.rest.mapping.MapValidationResponseToDto;
92 import org.springframework.beans.factory.annotation.Autowired;
93 import org.springframework.context.annotation.Scope;
94 import org.springframework.stereotype.Service;
97 @Service("orchestrationTemplateCandidate")
98 @Scope(value = "prototype")
99 public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplateCandidate {
101 private static final Logger LOGGER = LoggerFactory.getLogger(OrchestrationTemplateCandidateImpl.class);
102 private final OrchestrationTemplateCandidateManager candidateManager;
103 private final VendorSoftwareProductManager vendorSoftwareProductManager;
104 private final ActivityLogManager activityLogManager;
105 private final ArtifactStorageManager artifactStorageManager;
106 private final StorageFactory storageFactory;
107 private final PackageSizeReducer packageSizeReducer;
108 private final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager;
111 public OrchestrationTemplateCandidateImpl(final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager) {
112 this.candidateManager = OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface();
113 this.vendorSoftwareProductManager = VspManagerFactory.getInstance().createInterface();
114 this.activityLogManager = ActivityLogManagerFactory.getInstance().createInterface();
115 LOGGER.info("Instantiating artifactStorageManager");
116 this.storageFactory = new StorageFactory();
117 this.artifactStorageManager = storageFactory.createArtifactStorageManager();
118 LOGGER.info("Instantiating packageSizeReducer");
119 this.packageSizeReducer = storageFactory.createPackageSizeReducer().orElse(null);
120 this.orchestrationTemplateCandidateUploadManager = orchestrationTemplateCandidateUploadManager;
123 // Constructor used in test to avoid mock static
124 public OrchestrationTemplateCandidateImpl(final OrchestrationTemplateCandidateManager candidateManager,
125 final VendorSoftwareProductManager vendorSoftwareProductManager,
126 final ActivityLogManager activityLogManager,
127 final ArtifactStorageManager artifactStorageManager,
128 final PackageSizeReducer packageSizeReducer,
129 final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager) {
130 this.candidateManager = candidateManager;
131 this.vendorSoftwareProductManager = vendorSoftwareProductManager;
132 this.activityLogManager = activityLogManager;
133 this.artifactStorageManager = artifactStorageManager;
134 this.storageFactory = new StorageFactory();
135 this.packageSizeReducer = packageSizeReducer;
136 this.orchestrationTemplateCandidateUploadManager = orchestrationTemplateCandidateUploadManager;
140 public Response upload(String vspId, String versionId, final Attachment fileToUpload, final String user) {
141 LOGGER.debug("STARTED -> OrchestrationTemplateCandidateImpl.upload");
142 vspId = ValidationUtils.sanitizeInputString(vspId);
143 versionId = ValidationUtils.sanitizeInputString(versionId);
144 final Response response;
145 VspUploadStatusDto vspUploadStatus = null;
147 vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInProgress(vspId, versionId, user);
148 final byte[] fileToUploadBytes;
149 final DataHandler dataHandler = fileToUpload.getDataHandler();
150 final var filename = ValidationUtils.sanitizeInputString(dataHandler.getName());
151 ArtifactInfo artifactInfo = null;
152 final ArtifactStorageManager artifactStorageManager = storageFactory.createArtifactStorageManager();
153 if (artifactStorageManager.isEnabled()) {
154 artifactInfo = handleArtifactStorage(vspId, versionId, filename, dataHandler);
155 fileToUploadBytes = artifactInfo.getBytes();
157 fileToUploadBytes = fileToUpload.getObject(byte[].class);
160 vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInValidation(vspId, versionId, user);
161 final var onboardingPackageProcessor =
162 new OnboardingPackageProcessor(filename, fileToUploadBytes, new CnfPackageValidator(), artifactInfo);
163 final ErrorMessage[] errorMessages = onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]);
164 if (onboardingPackageProcessor.hasErrors()) {
165 orchestrationTemplateCandidateUploadManager
166 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
167 return Response.status(NOT_ACCEPTABLE).entity(buildUploadResponseWithError(errorMessages)).build();
169 final var onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
170 if (onboardPackageInfo == null) {
171 final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError(
172 new ErrorMessage(ErrorLevel.ERROR, PACKAGE_PROCESS_ERROR.formatMessage(filename)));
173 orchestrationTemplateCandidateUploadManager
174 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
175 return Response.ok(uploadFileResponseDto).build();
177 final var version = new Version(versionId);
178 final var vspDetails = vendorSoftwareProductManager.getVsp(vspId, version);
179 vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInProcessing(vspId, versionId, user);
180 response = processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages);
181 final UploadFileResponseDto entity = (UploadFileResponseDto) response.getEntity();
182 if (artifactStorageManager.isEnabled()) {
183 if (entity.getErrors().isEmpty()) {
184 artifactStorageManager.put(vspId, versionId + ".reduced", new ByteArrayInputStream(fileToUploadBytes));
186 artifactStorageManager.delete(artifactInfo);
189 orchestrationTemplateCandidateUploadManager
190 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.SUCCESS, user);
191 } catch (final Exception ex) {
192 if (vspUploadStatus != null) {
193 orchestrationTemplateCandidateUploadManager
194 .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user);
198 LOGGER.debug("FINISHED -> OrchestrationTemplateCandidateImpl.upload");
202 private ArtifactInfo handleArtifactStorage(final String vspId, final String versionId, final String filename,
203 final DataHandler artifactDataHandler) {
204 final Path tempArtifactPath;
206 final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration();
208 final Path folder = Path.of(storageConfiguration.getTempPath()).resolve(vspId).resolve(versionId);
209 tempArtifactPath = folder.resolve(UUID.randomUUID().toString());
210 Files.createDirectories(folder);
211 LOGGER.debug("STARTED -> Transfer to '{}'", tempArtifactPath.toString());
212 try (final InputStream packageInputStream = artifactDataHandler.getInputStream();
213 final var fileOutputStream = new FileOutputStream(tempArtifactPath.toFile())) {
214 packageInputStream.transferTo(fileOutputStream);
216 LOGGER.debug("FINISHED -> Transfer to '{}'", tempArtifactPath.toString());
217 } catch (final Exception e) {
218 throw new ArtifactStorageException(UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename));
220 final ArtifactInfo artifactInfo;
221 try (final InputStream inputStream = new FileInputStream(tempArtifactPath.toFile())) {
222 artifactInfo = artifactStorageManager.upload(vspId, versionId, inputStream);
223 } catch (final Exception e) {
224 LOGGER.error("Package Size Reducer not configured", e);
225 throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT.formatMessage(filename));
228 LOGGER.debug("STARTED -> reducing '{}'", tempArtifactPath.toString());
229 artifactInfo.setBytes(packageSizeReducer.reduce(tempArtifactPath));
230 LOGGER.debug("FINISHED -> reducing '{}'", tempArtifactPath.toString());
231 Files.delete(tempArtifactPath);
232 } catch (final Exception e) {
233 LOGGER.error("Package Size Reducer not configured", e);
234 throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(filename));
239 private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails,
240 final ErrorMessage... errorMessages) {
241 final UploadFileResponse uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo);
242 final UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto()
243 .applyMapping(uploadFileResponse, UploadFileResponseDto.class);
244 if (errorMessages.length > 0) {
245 uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
247 return Response.ok(uploadFileResponseDto).build();
250 private Map<String, List<ErrorMessage>> getErrorMap(ErrorMessage[] errorMessages) {
251 final Map<String, List<ErrorMessage>> errorMap = new HashMap<>();
252 final List<ErrorMessage> errorMessageList = new ArrayList<>();
253 Collections.addAll(errorMessageList, errorMessages);
254 errorMap.put(SdcCommon.UPLOAD_FILE, errorMessageList);
258 private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) {
259 final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto();
260 uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
261 return uploadFileResponseDto;
265 public Response get(String vspId, String versionId, String user) throws IOException {
266 Optional<Pair<String, byte[]>> zipFile = candidateManager.get(vspId, new Version(versionId));
268 if (zipFile.isPresent()) {
269 fileName = "Candidate." + zipFile.get().getLeft();
271 zipFile = vendorSoftwareProductManager.get(vspId, new Version((versionId)));
272 if (zipFile.isEmpty()) {
273 ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR,
274 getErrorWithParameters(NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(), ""));
275 LOGGER.error(errorMessage.getMessage());
276 return Response.status(NOT_FOUND).build();
278 fileName = "Processed." + zipFile.get().getLeft();
280 Response.ResponseBuilder response = Response.ok(zipFile.get().getRight());
281 response.header("Content-Disposition", "attachment; filename=" + fileName);
282 return response.build();
286 public Response abort(String vspId, String versionId) {
287 candidateManager.abort(vspId, new Version(versionId));
288 return Response.ok().build();
292 public Response process(String vspId, String versionId, String user) {
293 Version version = new Version(versionId);
294 OrchestrationTemplateActionResponse response = candidateManager.process(vspId, version);
295 activityLogManager.logActivity(new ActivityLogEntity(vspId, version, ActivityType.Upload_Network_Package, user, true, "", ""));
296 OrchestrationTemplateActionResponseDto responseDto = copyOrchestrationTemplateActionResponseToDto(response);
297 return Response.ok(responseDto).build();
301 public Response updateFilesDataStructure(String vspId, String versionId, FileDataStructureDto fileDataStructureDto, String user) {
302 FilesDataStructure fileDataStructure = copyFilesDataStructureDtoToFilesDataStructure(fileDataStructureDto);
303 ValidationResponse response = candidateManager.updateFilesDataStructure(vspId, new Version(versionId), fileDataStructure);
304 if (!response.isValid()) {
305 return Response.status(EXPECTATION_FAILED)
306 .entity(new MapValidationResponseToDto().applyMapping(response, ValidationResponseDto.class))
309 return Response.ok(fileDataStructureDto).build();
313 public Response getFilesDataStructure(String vspId, String versionId, String user) {
314 Optional<FilesDataStructure> filesDataStructure = candidateManager.getFilesDataStructure(vspId, new Version(versionId));
315 if (filesDataStructure.isEmpty()) {
316 filesDataStructure = vendorSoftwareProductManager.getOrchestrationTemplateStructure(vspId, new Version(versionId));
318 FileDataStructureDto fileDataStructureDto = filesDataStructure
319 .map(dataStructure -> new MapFilesDataStructureToDto().applyMapping(dataStructure, FileDataStructureDto.class))
320 .orElse(new FileDataStructureDto());
321 return Response.ok(fileDataStructureDto).build();
324 private OrchestrationTemplateActionResponseDto copyOrchestrationTemplateActionResponseToDto(OrchestrationTemplateActionResponse response) {
325 OrchestrationTemplateActionResponseDto result = new OrchestrationTemplateActionResponseDto();
326 result.setErrors(response.getErrors());
327 result.setFileNames(response.getFileNames());
328 result.setStatus(response.getStatus());
332 private FilesDataStructure copyFilesDataStructureDtoToFilesDataStructure(FileDataStructureDto fileDataStructureDto) {
333 FilesDataStructure filesDataStructure = new FilesDataStructure();
334 filesDataStructure.setArtifacts(fileDataStructureDto.getArtifacts());
335 filesDataStructure.setModules(fileDataStructureDto.getModules());
336 filesDataStructure.setNested(fileDataStructureDto.getNested());
337 filesDataStructure.setUnassigned(fileDataStructureDto.getUnassigned());
338 return filesDataStructure;