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);
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();
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();
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));
178 artifactStorageManager.delete(artifactInfo);
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);
193 private ArtifactInfo handleArtifactStorage(final String vspId, final String versionId, final String filename,
194 final DataHandler artifactDataHandler) {
195 final Path tempArtifactPath;
197 final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration();
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);
206 } catch (final Exception e) {
207 throw new ArtifactStorageException(UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename));
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));
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));
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));
234 return Response.ok(uploadFileResponseDto).build();
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);
245 private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) {
246 final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto();
247 uploadFileResponseDto.setErrors(getErrorMap(errorMessages));
248 return uploadFileResponseDto;
252 public Response get(String vspId, String versionId, String user) throws IOException {
253 Optional<Pair<String, byte[]>> zipFile = candidateManager.get(vspId, new Version(versionId));
255 if (zipFile.isPresent()) {
256 fileName = "Candidate." + zipFile.get().getLeft();
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();
265 fileName = "Processed." + zipFile.get().getLeft();
267 Response.ResponseBuilder response = Response.ok(zipFile.get().getRight());
268 response.header("Content-Disposition", "attachment; filename=" + fileName);
269 return response.build();
273 public Response abort(String vspId, String versionId) {
274 candidateManager.abort(vspId, new Version(versionId));
275 return Response.ok().build();
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();
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))
296 return Response.ok(fileDataStructureDto).build();
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));
305 FileDataStructureDto fileDataStructureDto = filesDataStructure
306 .map(dataStructure -> new MapFilesDataStructureToDto().applyMapping(dataStructure, FileDataStructureDto.class))
307 .orElse(new FileDataStructureDto());
308 return Response.ok(fileDataStructureDto).build();
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());
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;