diff options
Diffstat (limited to 'openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest')
7 files changed, 579 insertions, 59 deletions
diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/OrchestrationTemplateCandidateUploadManagerController.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/OrchestrationTemplateCandidateUploadManagerController.java new file mode 100644 index 0000000000..971a1c42b5 --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/OrchestrationTemplateCandidateUploadManagerController.java @@ -0,0 +1,65 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdcrests.vsp.rest; + +import static org.openecomp.sdcrests.common.RestConstants.USER_ID_HEADER_PARAM; +import static org.openecomp.sdcrests.common.RestConstants.USER_MISSING_ERROR_MSG; +import static org.openecomp.sdcrests.vsp.rest.OrchestrationTemplateCandidateUploadManagerController.URL; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.springframework.validation.annotation.Validated; + +@Path(URL) +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@Tag(name = "SDCE-1 APIs") +@Tag(name = "Package Upload Manager") +@Validated +public interface OrchestrationTemplateCandidateUploadManagerController extends VspEntities { + + String URL = "/v1.0/vendor-software-products/{vspId}/versions/{versionId}/orchestration-template-candidate/upload"; + + /** + * Gets the latest package upload status for a Vendor Software Product version. + * + * @param vspId the vsp id + * @param versionId the vsp version id + * @param user the username accessing the API + * @return if successful, an OK response with the latest VspUploadStatus information + */ + @GET + @Path("/") + Response getLatestStatus(@Parameter(description = "Vendor Software Product id") @PathParam("vspId") String vspId, + @Parameter(description = "Vendor Software Product version id") @PathParam("versionId") String versionId, + @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user); + +} diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/controllers/OrchestrationTemplateCandidateUploadManagerControllerImpl.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/controllers/OrchestrationTemplateCandidateUploadManagerControllerImpl.java new file mode 100644 index 0000000000..f96522aa75 --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/controllers/OrchestrationTemplateCandidateUploadManagerControllerImpl.java @@ -0,0 +1,71 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdcrests.vsp.rest.controllers; + +import java.util.Optional; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import org.openecomp.sdc.common.util.ValidationUtils; +import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspUploadStatusDto; +import org.openecomp.sdcrests.vsp.rest.OrchestrationTemplateCandidateUploadManagerController; +import org.openecomp.sdcrests.vsp.rest.services.OrchestrationTemplateCandidateUploadManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +@Controller("packageUploadManagerController") +public class OrchestrationTemplateCandidateUploadManagerControllerImpl implements OrchestrationTemplateCandidateUploadManagerController { + + private final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager; + + @Autowired + public OrchestrationTemplateCandidateUploadManagerControllerImpl(final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager) { + this.orchestrationTemplateCandidateUploadManager = orchestrationTemplateCandidateUploadManager; + } + + @Override + public Response getLatestStatus(String vspId, String versionId, String user) { + vspId = ValidationUtils.sanitizeInputString(vspId); + versionId = ValidationUtils.sanitizeInputString(versionId); + user = ValidationUtils.sanitizeInputString(user); + + final Optional<VspUploadStatusDto> vspUploadStatus = orchestrationTemplateCandidateUploadManager.findLatestStatus(vspId, versionId, user); + if (vspUploadStatus.isEmpty()) { + return Response.status(Status.NOT_FOUND).build(); + } + + return Response.ok(vspUploadStatus.get()).build(); + } + + /** + * Builds the string representing the get API url. + * + * @param vspId the vsp id + * @param vspVersionId the vsp version id + * @return the string representing the get API url + */ + public static String buildGetUrl(final String vspId, final String vspVersionId) { + return OrchestrationTemplateCandidateUploadManagerController.URL + .replace("{vspId}", vspId) + .replace("{versionId}", vspVersionId); + } + +} diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/exception/OrchestrationTemplateCandidateUploadManagerExceptionSupplier.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/exception/OrchestrationTemplateCandidateUploadManagerExceptionSupplier.java new file mode 100644 index 0000000000..2eb0261a1b --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/exception/OrchestrationTemplateCandidateUploadManagerExceptionSupplier.java @@ -0,0 +1,84 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdcrests.vsp.rest.exception; + +import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductErrorCodes.VSP_CREATE_UPLOAD_LOCK_ERROR; +import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductErrorCodes.VSP_PROCESSING_IN_PROGRESS; +import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductErrorCodes.VSP_UPDATE_UPLOAD_LOCK_ERROR; +import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductErrorCodes.VSP_UPLOAD_ALREADY_FINISHED_ERROR; +import static org.openecomp.sdc.vendorsoftwareproduct.errors.VendorSoftwareProductErrorCodes.VSP_UPLOAD_LOCK_NOT_FOUND_ERROR; + +import java.util.UUID; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import org.openecomp.sdc.common.errors.CoreException; +import org.openecomp.sdc.common.errors.ErrorCode; +import org.openecomp.sdc.common.errors.ErrorCode.ErrorCodeBuilder; +import org.openecomp.sdc.vendorsoftwareproduct.dao.errors.VendorSoftwareProductNotFoundErrorBuilder; +import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatus; + +public class OrchestrationTemplateCandidateUploadManagerExceptionSupplier { + + private OrchestrationTemplateCandidateUploadManagerExceptionSupplier() { + } + + public static Supplier<CoreException> vspUploadAlreadyInProgress(final String vspId, final String vspVersionId) { + final String errorMsg = String.format("There is a processing in progress for the VSP %s, version %s", vspId, vspVersionId); + return () -> new CoreException(new ErrorCodeBuilder().withId(VSP_PROCESSING_IN_PROGRESS).withMessage(errorMsg).build()); + } + + public static Supplier<CoreException> couldNotCreateLock(final String vspId, final String vspVersionId, final Exception exception) { + final String errorMsg = String.format("Could not create a lock for the VSP %s, version %s", vspId, vspVersionId); + final ErrorCode errorCode = new ErrorCodeBuilder().withId(VSP_CREATE_UPLOAD_LOCK_ERROR).withMessage(errorMsg).build(); + return () -> new CoreException(errorCode, exception); + } + + public static Supplier<CoreException> couldNotUpdateLock(final UUID lockId, final String vspId, final String vspVersionId, final Exception exception) { + final String errorMsg = String.format("Could not update the lock %s for the VSP %s, version %s", lockId, vspId, vspVersionId); + final ErrorCode errorCode = new ErrorCodeBuilder().withId(VSP_UPDATE_UPLOAD_LOCK_ERROR).withMessage(errorMsg).build(); + return () -> new CoreException(errorCode, exception); + } + + public static Supplier<CoreException> couldNotFindLock(final UUID lockId, final String vspId, final String vspVersionId) { + final String errorMsg = String.format("Could not find lock '%s' for the VSP %s, version %s", lockId, vspId, vspVersionId); + final ErrorCode errorCode = new ErrorCodeBuilder().withId(VSP_UPLOAD_LOCK_NOT_FOUND_ERROR).withMessage(errorMsg).build(); + return () -> new CoreException(errorCode); + } + + public static Supplier<CoreException> uploadAlreadyFinished(final UUID lockId, final String vspId, final String vspVersionId) { + final String errorMsg = String.format("The upload was already finished for lock '%s', VSP '%s', version '%s'", lockId, vspId, vspVersionId); + final ErrorCode errorCode = new ErrorCodeBuilder().withId(VSP_UPLOAD_ALREADY_FINISHED_ERROR).withMessage(errorMsg).build(); + return () -> new CoreException(errorCode); + } + + public static Supplier<CoreException> vspNotFound(final String vspId, final String vspVersionId) { + return () -> new CoreException(new VendorSoftwareProductNotFoundErrorBuilder(vspId, vspVersionId).build()); + } + + public static Supplier<IllegalArgumentException> invalidCompleteStatus(final VspUploadStatus status) { + String errorMsg = String.format("Invalid complete status '%s'. Expecting one of: %s", + status, + VspUploadStatus.getCompleteStatus().stream().map(Enum::name).collect(Collectors.joining(", ")) + ); + return () -> new IllegalArgumentException(errorMsg); + } +} diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/mapping/VspUploadStatusRecordMapper.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/mapping/VspUploadStatusRecordMapper.java new file mode 100644 index 0000000000..9cc3b591aa --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/mapping/VspUploadStatusRecordMapper.java @@ -0,0 +1,40 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdcrests.vsp.rest.mapping; + +import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatusRecord; +import org.openecomp.sdcrests.mapping.MappingBase; +import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspUploadStatusDto; + +public class VspUploadStatusRecordMapper extends MappingBase<VspUploadStatusRecord, VspUploadStatusDto> { + + @Override + public void doMapping(final VspUploadStatusRecord source, final VspUploadStatusDto target) { + target.setVspId(source.getVspId()); + target.setVspVersionId(source.getVspVersionId()); + target.setStatus(source.getStatus()); + target.setLockId(source.getLockId()); + target.setComplete(source.getIsComplete()); + target.setCreated(source.getCreated()); + target.setUpdated(source.getUpdated()); + } +} diff --git a/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 b/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 index e8ee6b3c4b..1477ce1414 100644 --- a/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 +++ b/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 @@ -22,7 +22,6 @@ package org.openecomp.sdcrests.vsp.rest.services; import static javax.ws.rs.core.Response.Status.EXPECTATION_FAILED; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters; @@ -59,6 +58,7 @@ import org.openecomp.sdc.be.csar.storage.ArtifactStorageConfig; import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager; import org.openecomp.sdc.be.csar.storage.PackageSizeReducer; import org.openecomp.sdc.be.csar.storage.StorageFactory; +import org.openecomp.sdc.be.csar.storage.exception.ArtifactStorageException; import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.common.utils.SdcCommon; import org.openecomp.sdc.datatypes.error.ErrorLevel; @@ -70,6 +70,7 @@ import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateMan import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails; +import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatus; import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor; import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator; import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo; @@ -82,10 +83,12 @@ import org.openecomp.sdcrests.vendorsoftwareproducts.types.FileDataStructureDto; import org.openecomp.sdcrests.vendorsoftwareproducts.types.OrchestrationTemplateActionResponseDto; import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto; import org.openecomp.sdcrests.vendorsoftwareproducts.types.ValidationResponseDto; +import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspUploadStatusDto; import org.openecomp.sdcrests.vsp.rest.OrchestrationTemplateCandidate; import org.openecomp.sdcrests.vsp.rest.mapping.MapFilesDataStructureToDto; import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFileResponseDto; import org.openecomp.sdcrests.vsp.rest.mapping.MapValidationResponseToDto; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @@ -100,8 +103,10 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate private final ActivityLogManager activityLogManager; private final ArtifactStorageManager artifactStorageManager; private final PackageSizeReducer packageSizeReducer; + private final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager; - public OrchestrationTemplateCandidateImpl() { + @Autowired + public OrchestrationTemplateCandidateImpl(final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager) { this.candidateManager = OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface(); this.vendorSoftwareProductManager = VspManagerFactory.getInstance().createInterface(); this.activityLogManager = ActivityLogManagerFactory.getInstance().createInterface(); @@ -110,6 +115,7 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate this.artifactStorageManager = storageFactory.createArtifactStorageManager(); LOGGER.info("Instantiating packageSizeReducer"); this.packageSizeReducer = storageFactory.createPackageSizeReducer().orElse(null); + this.orchestrationTemplateCandidateUploadManager = orchestrationTemplateCandidateUploadManager; } // Constructor used in test to avoid mock static @@ -117,81 +123,101 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate final VendorSoftwareProductManager vendorSoftwareProductManager, final ActivityLogManager activityLogManager, final ArtifactStorageManager artifactStorageManager, - final PackageSizeReducer packageSizeReducer) { + final PackageSizeReducer packageSizeReducer, + final OrchestrationTemplateCandidateUploadManager orchestrationTemplateCandidateUploadManager) { this.candidateManager = candidateManager; this.vendorSoftwareProductManager = vendorSoftwareProductManager; this.activityLogManager = activityLogManager; this.artifactStorageManager = artifactStorageManager; this.packageSizeReducer = packageSizeReducer; + this.orchestrationTemplateCandidateUploadManager = orchestrationTemplateCandidateUploadManager; } @Override public Response upload(String vspId, String versionId, final Attachment fileToUpload, final String user) { vspId = ValidationUtils.sanitizeInputString(vspId); versionId = ValidationUtils.sanitizeInputString(versionId); - final byte[] fileToUploadBytes; - final DataHandler dataHandler = fileToUpload.getDataHandler(); - final var filename = ValidationUtils.sanitizeInputString(dataHandler.getName()); - ArtifactInfo artifactInfo = null; - if (artifactStorageManager.isEnabled()) { - final Path tempArtifactPath; - try { - final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration(); + final Response response; + VspUploadStatusDto vspUploadStatus = null; + try { + vspUploadStatus = orchestrationTemplateCandidateUploadManager.putUploadInProgress(vspId, versionId, user); + final byte[] fileToUploadBytes; + final DataHandler dataHandler = fileToUpload.getDataHandler(); + final var filename = ValidationUtils.sanitizeInputString(dataHandler.getName()); + ArtifactInfo artifactInfo = null; + if (artifactStorageManager.isEnabled()) { + artifactInfo = handleArtifactStorage(vspId, versionId, filename, dataHandler); + fileToUploadBytes = artifactInfo.getBytes(); + } else { + fileToUploadBytes = fileToUpload.getObject(byte[].class); + } - final Path folder = Path.of(storageConfiguration.getTempPath()).resolve(vspId).resolve(versionId); - tempArtifactPath = folder.resolve(UUID.randomUUID().toString()); - Files.createDirectories(folder); - try (final InputStream packageInputStream = dataHandler.getInputStream(); - final var fileOutputStream = new FileOutputStream(tempArtifactPath.toFile())) { - packageInputStream.transferTo(fileOutputStream); - } - } catch (final Exception e) { - return Response.status(INTERNAL_SERVER_ERROR).entity(buildUploadResponseWithError( - new ErrorMessage(ErrorLevel.ERROR, UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename)))).build(); + final var onboardingPackageProcessor = + new OnboardingPackageProcessor(filename, fileToUploadBytes, new CnfPackageValidator(), artifactInfo); + final ErrorMessage[] errorMessages = onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]); + if (onboardingPackageProcessor.hasErrors()) { + return Response.status(NOT_ACCEPTABLE).entity(buildUploadResponseWithError(errorMessages)).build(); } - try (final InputStream inputStream = Files.newInputStream(tempArtifactPath)) { - artifactInfo = artifactStorageManager.upload(vspId, versionId, inputStream); - } catch (final Exception e) { - LOGGER.error("Package Size Reducer not configured", e); - return Response.status(INTERNAL_SERVER_ERROR).entity(buildUploadResponseWithError( - new ErrorMessage(ErrorLevel.ERROR, ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT.formatMessage(filename)))).build(); + final var onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null); + if (onboardPackageInfo == null) { + final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError( + new ErrorMessage(ErrorLevel.ERROR, PACKAGE_PROCESS_ERROR.formatMessage(filename))); + return Response.ok(uploadFileResponseDto).build(); } - try { - fileToUploadBytes = packageSizeReducer.reduce(tempArtifactPath); - Files.delete(tempArtifactPath); - } catch (final Exception e) { - LOGGER.error("Package Size Reducer not configured", e); - return Response.status(INTERNAL_SERVER_ERROR).entity(buildUploadResponseWithError( - new ErrorMessage(ErrorLevel.ERROR, - ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(tempArtifactPath.toString())))).build(); + final var version = new Version(versionId); + final var vspDetails = vendorSoftwareProductManager.getVsp(vspId, version); + response = processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages); + final UploadFileResponseDto entity = (UploadFileResponseDto) response.getEntity(); + if (artifactStorageManager.isEnabled()) { + if (!entity.getErrors().isEmpty()) { + artifactStorageManager.delete(artifactInfo); + } else { + artifactStorageManager.put(vspId, versionId + ".reduced", new ByteArrayInputStream(fileToUploadBytes)); + } } - } else { - fileToUploadBytes = fileToUpload.getObject(byte[].class); + orchestrationTemplateCandidateUploadManager + .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.SUCCESS, user); + } catch (final Exception ex) { + if (vspUploadStatus != null) { + orchestrationTemplateCandidateUploadManager + .putUploadAsFinished(vspId, versionId, vspUploadStatus.getLockId(), VspUploadStatus.ERROR, user); + } + throw ex; } + return response; + } + + private ArtifactInfo handleArtifactStorage(final String vspId, final String versionId, final String filename, + final DataHandler artifactDataHandler) { + final Path tempArtifactPath; + try { + final ArtifactStorageConfig storageConfiguration = artifactStorageManager.getStorageConfiguration(); - final var onboardingPackageProcessor = new OnboardingPackageProcessor(filename, fileToUploadBytes, new CnfPackageValidator(), artifactInfo); - final ErrorMessage[] errorMessages = onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]); - if (onboardingPackageProcessor.hasErrors()) { - return Response.status(NOT_ACCEPTABLE).entity(buildUploadResponseWithError(errorMessages)).build(); + final Path folder = Path.of(storageConfiguration.getTempPath()).resolve(vspId).resolve(versionId); + tempArtifactPath = folder.resolve(UUID.randomUUID().toString()); + Files.createDirectories(folder); + try (final InputStream packageInputStream = artifactDataHandler.getInputStream(); + final var fileOutputStream = new FileOutputStream(tempArtifactPath.toFile())) { + packageInputStream.transferTo(fileOutputStream); + } + } catch (final Exception e) { + throw new ArtifactStorageException(UNEXPECTED_PROBLEM_HAPPENED_WHILE_GETTING.formatMessage(filename)); } - final var onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null); - if (onboardPackageInfo == null) { - final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError( - new ErrorMessage(ErrorLevel.ERROR, PACKAGE_PROCESS_ERROR.formatMessage(filename))); - return Response.ok(uploadFileResponseDto).build(); + final ArtifactInfo artifactInfo; + try (final InputStream inputStream = Files.newInputStream(tempArtifactPath)) { + artifactInfo = artifactStorageManager.upload(vspId, versionId, inputStream); + } catch (final Exception e) { + LOGGER.error("Package Size Reducer not configured", e); + throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_PERSISTING_THE_ARTIFACT.formatMessage(filename)); } - final var version = new Version(versionId); - final var vspDetails = vendorSoftwareProductManager.getVsp(vspId, version); - final Response response = processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages); - final UploadFileResponseDto entity = (UploadFileResponseDto) response.getEntity(); - if (artifactStorageManager.isEnabled()) { - if (!entity.getErrors().isEmpty()) { - artifactStorageManager.delete(artifactInfo); - } else { - artifactStorageManager.put(vspId, versionId + ".reduced", new ByteArrayInputStream(fileToUploadBytes)); - } + try { + artifactInfo.setBytes(packageSizeReducer.reduce(tempArtifactPath)); + Files.delete(tempArtifactPath); + } catch (final Exception e) { + LOGGER.error("Package Size Reducer not configured", e); + throw new ArtifactStorageException(ERROR_HAS_OCCURRED_WHILE_REDUCING_THE_ARTIFACT_SIZE.formatMessage(filename)); } - return response; + return artifactInfo; } private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails, @@ -227,7 +253,7 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate fileName = "Candidate." + zipFile.get().getLeft(); } else { zipFile = vendorSoftwareProductManager.get(vspId, new Version((versionId))); - if (!zipFile.isPresent()) { + if (zipFile.isEmpty()) { ErrorMessage errorMessage = new ErrorMessage(ErrorLevel.ERROR, getErrorWithParameters(NO_FILE_WAS_UPLOADED_OR_FILE_NOT_EXIST.getErrorMessage(), "")); LOGGER.error(errorMessage.getMessage()); @@ -270,7 +296,7 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate @Override public Response getFilesDataStructure(String vspId, String versionId, String user) { Optional<FilesDataStructure> filesDataStructure = candidateManager.getFilesDataStructure(vspId, new Version(versionId)); - if (!filesDataStructure.isPresent()) { + if (filesDataStructure.isEmpty()) { filesDataStructure = vendorSoftwareProductManager.getOrchestrationTemplateStructure(vspId, new Version(versionId)); } FileDataStructureDto fileDataStructureDto = filesDataStructure diff --git a/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/OrchestrationTemplateCandidateUploadManager.java b/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/OrchestrationTemplateCandidateUploadManager.java new file mode 100644 index 0000000000..0f33580099 --- /dev/null +++ b/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/OrchestrationTemplateCandidateUploadManager.java @@ -0,0 +1,63 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdcrests.vsp.rest.services; + +import java.util.Optional; +import java.util.UUID; +import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatus; +import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspUploadStatusDto; + +public interface OrchestrationTemplateCandidateUploadManager { + + /** + * Creates a lock to start uploading a package. + * + * @param vspId the Vendor Software Product id + * @param vspVersionId the Vendor Software Product version id + * @param user the current user + * @return a new upload status containing the lock + */ + VspUploadStatusDto putUploadInProgress(String vspId, String vspVersionId, String user); + + /** + * Finishes the upload process, applying the given VspUploadStatusType completion status. + * + * @param vspId the Vendor Software Product id + * @param vspVersionId the Vendor Software Product version id + * @param lockId the upload lock id + * @param completionStatus any status that represents a completion + * @param user the current user + * @return the updated status + */ + VspUploadStatusDto putUploadAsFinished(final String vspId, final String vspVersionId, final UUID lockId, final VspUploadStatus completionStatus, + final String user); + + /** + * Finds the latest upload status for a given Vendor Software Product version. + * + * @param vspId the Vendor Software Product id + * @param vspVersionId the Vendor Software Product version id + * @param user the current user + * @return the latest upload status for the requested Vendor Software Product version + */ + Optional<VspUploadStatusDto> findLatestStatus(String vspId, String vspVersionId, String user); +} diff --git a/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/OrchestrationTemplateCandidateUploadManagerImpl.java b/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/OrchestrationTemplateCandidateUploadManagerImpl.java new file mode 100644 index 0000000000..d7cfe041c2 --- /dev/null +++ b/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/OrchestrationTemplateCandidateUploadManagerImpl.java @@ -0,0 +1,171 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdcrests.vsp.rest.services; + +import static org.openecomp.sdcrests.vsp.rest.exception.OrchestrationTemplateCandidateUploadManagerExceptionSupplier.couldNotCreateLock; +import static org.openecomp.sdcrests.vsp.rest.exception.OrchestrationTemplateCandidateUploadManagerExceptionSupplier.couldNotFindLock; +import static org.openecomp.sdcrests.vsp.rest.exception.OrchestrationTemplateCandidateUploadManagerExceptionSupplier.couldNotUpdateLock; +import static org.openecomp.sdcrests.vsp.rest.exception.OrchestrationTemplateCandidateUploadManagerExceptionSupplier.uploadAlreadyFinished; +import static org.openecomp.sdcrests.vsp.rest.exception.OrchestrationTemplateCandidateUploadManagerExceptionSupplier.vspUploadAlreadyInProgress; + +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import org.openecomp.sdc.common.errors.CoreException; +import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; +import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; +import org.openecomp.sdc.vendorsoftwareproduct.dao.VspUploadStatusRecordDao; +import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails; +import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatus; +import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspUploadStatusRecord; +import org.openecomp.sdc.versioning.dao.types.Version; +import org.openecomp.sdcrests.vendorsoftwareproducts.types.VspUploadStatusDto; +import org.openecomp.sdcrests.vsp.rest.exception.OrchestrationTemplateCandidateUploadManagerExceptionSupplier; +import org.openecomp.sdcrests.vsp.rest.mapping.VspUploadStatusRecordMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +/** + * Manages the package upload process status. + */ +@Service +public class OrchestrationTemplateCandidateUploadManagerImpl implements OrchestrationTemplateCandidateUploadManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(OrchestrationTemplateCandidateUploadManagerImpl.class); + + private final VspUploadStatusRecordDao uploadManagerDao; + private final VspUploadStatusRecordMapper vspUploadStatusRecordMapper; + private final VendorSoftwareProductManager vendorSoftwareProductManager; + private final Lock startUploadLock; + + @Autowired + public OrchestrationTemplateCandidateUploadManagerImpl( + @Qualifier("vsp-upload-status-record-dao-impl") final VspUploadStatusRecordDao uploadManagerDao) { + + this.uploadManagerDao = uploadManagerDao; + this.vendorSoftwareProductManager = VspManagerFactory.getInstance().createInterface(); + this.vspUploadStatusRecordMapper = new VspUploadStatusRecordMapper(); + startUploadLock = new ReentrantLock(); + } + + //for tests purpose + OrchestrationTemplateCandidateUploadManagerImpl(final VspUploadStatusRecordDao uploadManagerDao, + final VendorSoftwareProductManager vendorSoftwareProductManager) { + this.uploadManagerDao = uploadManagerDao; + this.vendorSoftwareProductManager = vendorSoftwareProductManager; + this.vspUploadStatusRecordMapper = new VspUploadStatusRecordMapper(); + startUploadLock = new ReentrantLock(); + } + + @Override + public VspUploadStatusDto putUploadInProgress(final String vspId, final String vspVersionId, final String user) { + checkVspExists(vspId, vspVersionId); + LOGGER.debug("Start uploading for VSP id '{}', version '{}', triggered by user '{}'", vspId, vspVersionId, user); + + final VspUploadStatusRecord vspUploadStatusRecord; + startUploadLock.lock(); + try { + final List<VspUploadStatusRecord> uploadInProgressList = uploadManagerDao.findAllInProgress(vspId, vspVersionId); + if (!uploadInProgressList.isEmpty()) { + throw vspUploadAlreadyInProgress(vspId, vspVersionId).get(); + } + + vspUploadStatusRecord = new VspUploadStatusRecord(); + vspUploadStatusRecord.setStatus(VspUploadStatus.UPLOADING); + vspUploadStatusRecord.setVspId(vspId); + vspUploadStatusRecord.setVspVersionId(vspVersionId); + vspUploadStatusRecord.setLockId(UUID.randomUUID()); + vspUploadStatusRecord.setCreated(new Date()); + + uploadManagerDao.create(vspUploadStatusRecord); + LOGGER.debug("Upload lock '{}' created for VSP id '{}', version '{}'", vspUploadStatusRecord.getLockId(), vspId, vspVersionId); + } catch (final CoreException e) { + throw e; + } catch (final Exception e) { + throw couldNotCreateLock(vspId, vspVersionId, e).get(); + } finally { + startUploadLock.unlock(); + } + + return vspUploadStatusRecordMapper.applyMapping(vspUploadStatusRecord, VspUploadStatusDto.class); + } + + @Override + public VspUploadStatusDto putUploadAsFinished(final String vspId, final String vspVersionId, final UUID lockId, final VspUploadStatus completionStatus, + final String user) { + + if (!completionStatus.isCompleteStatus()) { + throw OrchestrationTemplateCandidateUploadManagerExceptionSupplier.invalidCompleteStatus(completionStatus).get(); + } + final Optional<VspUploadStatusRecord> vspUploadStatusOptional = + uploadManagerDao.findByVspIdAndVersionIdAndLockId(vspId, vspVersionId, lockId); + if (vspUploadStatusOptional.isEmpty()) { + throw couldNotFindLock(lockId, vspId, vspVersionId).get(); + } + final VspUploadStatusRecord vspUploadStatusRecord = vspUploadStatusOptional.get(); + if (vspUploadStatusRecord.getIsComplete()) { + throw uploadAlreadyFinished(lockId, vspId, vspVersionId).get(); + } + LOGGER.debug("Finishing the upload for VSP id '{}', version '{}', lock '{}', triggered by user '{}'", + vspUploadStatusRecord.getVspId(), vspUploadStatusRecord.getVspVersionId(), vspUploadStatusRecord.getLockId(), user); + vspUploadStatusRecord.setStatus(completionStatus); + vspUploadStatusRecord.setUpdated(new Date()); + vspUploadStatusRecord.setIsComplete(true); + + try { + uploadManagerDao.update(vspUploadStatusRecord); + LOGGER.debug("Upload complete for VSP '{}', version '{}', lock '{}'", + vspUploadStatusRecord.getLockId(), vspUploadStatusRecord.getVspId(), vspUploadStatusRecord.getVspVersionId()); + } catch (final Exception e) { + throw couldNotUpdateLock(vspUploadStatusRecord.getLockId(), vspUploadStatusRecord.getVspId(), vspUploadStatusRecord.getVspVersionId(), e) + .get(); + } + + return vspUploadStatusRecordMapper.applyMapping(vspUploadStatusRecord, VspUploadStatusDto.class); + } + + private void checkVspExists(final String vspId, final String vspVersionId) { + final VspDetails vspDetails = vendorSoftwareProductManager.getVsp(vspId, new Version(vspVersionId)); + if (vspDetails == null) { + throw OrchestrationTemplateCandidateUploadManagerExceptionSupplier.vspNotFound(vspId, vspVersionId).get(); + } + } + + @Override + public Optional<VspUploadStatusDto> findLatestStatus(final String vspId, final String vspVersionId, final String user) { + checkVspExists(vspId, vspVersionId); + + final Optional<VspUploadStatusRecord> vspUploadStatus = uploadManagerDao.findLatest(vspId, vspVersionId); + if (vspUploadStatus.isEmpty()) { + return Optional.empty(); + } + + return Optional.of(vspUploadStatusRecordMapper.applyMapping(vspUploadStatus.get(), VspUploadStatusDto.class)); + } + +} |