diff options
author | 2023-01-23 14:59:18 +0000 | |
---|---|---|
committer | 2023-01-23 14:59:29 +0000 | |
commit | 9783df1b5660ee0e0460cfd8dc5477a7edcb1d94 (patch) | |
tree | e3ffe3209ff38f839cd1af60a4f0dffd341dd1ee /so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows | |
parent | bd591af78a4ab97af4f65d6b7094d9c60f7879c4 (diff) |
Adding Create AS support
Change-Id: I4b1d417c7f20d67d5fb0d05718819186f8dd3bea
Issue-ID: SO-4068
Signed-off-by: waqas.ikram <waqas.ikram@est.tech>
Diffstat (limited to 'so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows')
8 files changed, 1271 insertions, 1 deletions
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/AbstractServiceTask.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/AbstractServiceTask.java new file mode 100644 index 0000000..45d7806 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/AbstractServiceTask.java @@ -0,0 +1,208 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_INSTANCE_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.JOB_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.OCC_ID_PARAM_NAME; + +import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.IN_PROGRESS; + +import java.time.LocalDateTime; +import java.util.Optional; +import org.camunda.bpm.engine.delegate.BpmnError; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.cnfm.lcm.database.beans.AsInst; +import org.onap.so.cnfm.lcm.database.beans.Job; +import org.onap.so.cnfm.lcm.database.beans.JobStatus; +import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum; +import org.onap.so.cnfm.lcm.database.beans.OperationStateEnum; +import org.onap.so.cnfm.lcm.database.beans.State; +import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider; +import org.onap.so.cnfm.lcm.model.ErrorDetails; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public abstract class AbstractServiceTask { + private final Logger logger = LoggerFactory.getLogger(getClass()); + protected final DatabaseServiceProvider databaseServiceProvider; + + protected AbstractServiceTask(final DatabaseServiceProvider databaseServiceProvider) { + this.databaseServiceProvider = databaseServiceProvider; + } + + public void addJobStatus(final DelegateExecution execution, final JobStatusEnum jobStatusEnum, + final String description) { + final JobStatus jobStatus = + new JobStatus().status(jobStatusEnum).description(description).updatedTime(LocalDateTime.now()); + logger.info("Adding JobStatus {}", jobStatus); + final Job job = getJob(execution); + job.jobStatus(jobStatus); + databaseServiceProvider.addJob(job); + } + + public void setJobStatus(final DelegateExecution execution, final JobStatusEnum jobStatus, + final String description) { + logger.info("Setting Job Status to {}", jobStatus); + final Job job = getJob(execution); + job.status(jobStatus); + if (JobStatusEnum.STARTED.equals(jobStatus)) { + job.processInstanceId(execution.getProcessInstanceId()); + } + + if (JobStatusEnum.FINISHED.equals(jobStatus)) { + job.endTime(LocalDateTime.now()); + } + + job.jobStatus(new JobStatus().status(jobStatus).description(description).updatedTime(LocalDateTime.now())); + databaseServiceProvider.addJob(job); + + } + + public void setAsInstanceStatusToFailed(final DelegateExecution execution) { + logger.info("Setting As Instance Status to {}", State.FAILED); + updateAsInstanceStatus(execution, State.FAILED); + } + + public void setJobStatusToError(final DelegateExecution execution, final String description) { + logger.info("Setting Job Status to {}", JobStatusEnum.ERROR); + + final String jobId = (String) execution.getVariable(JOB_ID_PARAM_NAME); + final Optional<Job> optional = databaseServiceProvider.getJob(jobId); + if (optional.isPresent()) { + final ErrorDetails errorDetails = + (ErrorDetails) execution.getVariable(AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME); + + final Job job = optional.get(); + job.status(JobStatusEnum.ERROR).endTime(LocalDateTime.now()); + + if (errorDetails != null) { + logger.error("Found failed reason: {}", errorDetails); + job.jobStatus(new JobStatus().status(JobStatusEnum.ERROR).description(errorDetails.getDetail()) + .updatedTime(LocalDateTime.now())); + } + job.jobStatus(new JobStatus().status(JobStatusEnum.ERROR).description(description) + .updatedTime(LocalDateTime.now())); + + databaseServiceProvider.addJob(job); + } + logger.info("Finished setting Job Status to {}", JobStatusEnum.ERROR); + + } + + protected void abortOperation(final DelegateExecution execution, final String message) { + abortOperation(execution, message, new ErrorDetails().detail(message)); + } + + protected void abortOperation(final DelegateExecution execution, final String message, + final ErrorDetails problemDetails) { + logger.error(message); + execution.setVariable(AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, problemDetails); + throw new BpmnError("WORKFLOW_FAILED", message); + } + + private Job getJob(final DelegateExecution execution) { + final String jobId = (String) execution.getVariable(JOB_ID_PARAM_NAME); + final Optional<Job> optional = databaseServiceProvider.getJob(jobId); + if (optional.isEmpty()) { + final String message = "Unable to find job using job id: " + jobId; + logger.error(message); + abortOperation(execution, message); + } + + return optional.get(); + } + + protected void updateAsInstanceStatus(final DelegateExecution execution, final State nsStatus) { + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + + logger.info("Updating AsInst Status to {} and saving to DB", nsStatus); + databaseServiceProvider.updateAsInstState(asInstId, nsStatus); + } + + protected AsInst getAsInst(final DelegateExecution execution) { + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + return getAsInst(execution, asInstId); + } + + protected AsInst getAsInst(final DelegateExecution execution, final String asInstId) { + logger.info("Getting AsInst to update with asInstId: {}", asInstId); + final Optional<AsInst> optionalAsInst = databaseServiceProvider.getAsInst(asInstId); + + if (optionalAsInst.isEmpty()) { + final String message = "Unable to find AS Instance in database using id: " + asInstId; + abortOperation(execution, message); + } + + return optionalAsInst.get(); + } + + public void updateAsLcmOpOccStatusToCompleted(final DelegateExecution execution) { + logger.info("Executing updateAsLcmOpOccStatusToCompleted ..."); + + addJobStatus(execution, IN_PROGRESS, "Updating AsLcmOpOcc Status to " + OperationStateEnum.COMPLETED); + updateAsLcmOpOccOperationState(execution, OperationStateEnum.COMPLETED); + + logger.info("Finished executing updateAsLcmOpOccStatusToCompleted ..."); + + } + + public void updateAsLcmOpOccStatusToFailed(final DelegateExecution execution) { + logger.info("Executing updateAsLcmOpOccStatusToFailed ..."); + + updateAsLcmOpOccOperationState(execution, OperationStateEnum.FAILED); + + logger.info("Finished executing updateAsLcmOpOccStatusToFailed ..."); + + } + + private void updateAsLcmOpOccOperationState(final DelegateExecution execution, + final OperationStateEnum operationState) { + final String occId = (String) execution.getVariable(OCC_ID_PARAM_NAME); + + final boolean isSuccessful = databaseServiceProvider.updateAsLcmOpOccOperationState(occId, operationState); + if (!isSuccessful) { + final String message = + "Unable to update AsLcmOpOcc " + occId + " operationState to" + operationState + " in database"; + logger.error(message); + abortOperation(execution, message); + } + } + + + public void updateDeploymentItemStatus(final DelegateExecution execution, final String asDeploymentItemInstId, + final State state) { + logger.debug("updateDeploymentItemStatus to status: {}", state); + final boolean isSuccessful = databaseServiceProvider.updateAsDeploymentItemState(asDeploymentItemInstId, state); + if (!isSuccessful) { + final String message = "Unable to update AsDeploymentItem " + asDeploymentItemInstId + " status to" + state + + " in database"; + logger.error(message); + abortOperation(execution, message); + } + } + +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/CreateAsTask.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/CreateAsTask.java new file mode 100644 index 0000000..85af369 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/CreateAsTask.java @@ -0,0 +1,342 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_INSTANCE_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_AS_REQUEST_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_AS_RESPONSE_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.APPLICATION_NAME_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.APPLICATION_VERSION_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DEPLOYMENT_ITEMS_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DESCRIPTOR_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DESCRIPTOR_INVARIANT_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.PROVIDER_PARAM_NAME; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.CLOUD_OWNER_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.CLOUD_REGION_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.RESOURCE_ID_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.SERVICE_INSTANCE_ID_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.SERVICE_INSTANCE_NAME_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.TENANT_ID_PARAM_KEY; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.time.LocalDateTime; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai.AaiServiceProvider; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.DeploymentItem; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPackageParser; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcPackageProvider; +import org.onap.so.cnfm.lcm.database.beans.AsDeploymentItem; +import org.onap.so.cnfm.lcm.database.beans.AsInst; +import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum; +import org.onap.so.cnfm.lcm.database.beans.State; +import org.onap.so.cnfm.lcm.database.beans.AsLifecycleParam; +import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider; +import org.onap.so.cnfm.lcm.model.AsInstance; +import org.onap.so.cnfm.lcm.model.AsInstance.InstantiationStateEnum; +import org.onap.so.cnfm.lcm.model.CreateAsRequest; +import org.onap.so.cnfm.lcm.model.ErrorDetails; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Component +public class CreateAsTask extends AbstractServiceTask { + private static final String ASD_PROPERTIES_PARAM_NAME = "asdProperties"; + private static final String DOES_AS_PACKAGE_EXISTS_PARAM_NAME = "doesAsPackageExists"; + private static final String DOES_AS_INSTANCE_EXISTS_PARAM_NAME = "doesAsInstanceExists"; + private static final Logger logger = LoggerFactory.getLogger(CreateAsTask.class); + + private final AaiServiceProvider aaiServiceProvider; + private final SdcPackageProvider sdcPackageProvider; + private final SdcCsarPackageParser sdcParser; + + + @Autowired + public CreateAsTask(final DatabaseServiceProvider databaseServiceProvider, + final AaiServiceProvider aaiServiceProvider, final SdcPackageProvider sdcPackageProvider, + final SdcCsarPackageParser sdcParser) { + super(databaseServiceProvider); + this.aaiServiceProvider = aaiServiceProvider; + this.sdcPackageProvider = sdcPackageProvider; + this.sdcParser = sdcParser; + } + + public void setJobStatusToStarted(final DelegateExecution execution) { + setJobStatus(execution, JobStatusEnum.STARTED, "Create AS workflow process started"); + } + + public void setJobStatusToFinished(final DelegateExecution execution) { + setJobStatus(execution, JobStatusEnum.FINISHED, "Create AS workflow process finished"); + } + + public void setJobStatusToError(final DelegateExecution execution) { + setJobStatusToError(execution, "Create AS workflow process failed"); + } + + public void getAsPackage(final DelegateExecution execution) { + logger.info("Retrieving AS package from SDC ..."); + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Retrieving AS package from SDC"); + + final CreateAsRequest createAsRequest = (CreateAsRequest) execution.getVariable(CREATE_AS_REQUEST_PARAM_NAME); + + logger.info("Retrieving AS package from SDC using asdId: {}", createAsRequest.getAsdId()); + + try { + + final Optional<byte[]> optional = sdcPackageProvider.getSdcResourcePackage(createAsRequest.getAsdId()); + + if (optional.isPresent()) { + logger.info("ASD Package exists for asdId {}", createAsRequest.getAsdId()); + + final Map<String, Object> asdProperties = sdcParser.getAsdProperties(optional.get()); + logger.info("ASD Package properties fields {}", asdProperties); + + execution.setVariable(ASD_PROPERTIES_PARAM_NAME, asdProperties); + execution.setVariable(DOES_AS_PACKAGE_EXISTS_PARAM_NAME, true); + } else { + + final String message = "Unable to find ASD package using asdId: " + createAsRequest.getAsdId(); + logger.error(message); + execution.setVariable(DOES_AS_PACKAGE_EXISTS_PARAM_NAME, false); + abortOperation(execution, message); + } + } catch (final Exception failureException) { + final String message = + "Unexpected exception occured while getting asd package using asdId: " + createAsRequest.getAsdId(); + logger.error(message, failureException); + + execution.setVariable(DOES_AS_PACKAGE_EXISTS_PARAM_NAME, false); + execution.setVariable(AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, + new ErrorDetails().title(message).detail(message)); + } + + } + + public void doesAsInstanceExistsInDb(final DelegateExecution execution) { + logger.info("Executing doesAsInstanceExistsInDb ..."); + + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Checking if AS Instance exists in database"); + + final CreateAsRequest createAsRequest = + (CreateAsRequest) execution.getVariables().get(CREATE_AS_REQUEST_PARAM_NAME); + + final boolean exists = databaseServiceProvider.isAsInstExists(createAsRequest.getAsInstanceName()); + logger.info("As Instance entry {} exists in database", exists ? "does" : "doesn't"); + execution.setVariable(DOES_AS_INSTANCE_EXISTS_PARAM_NAME, exists); + + if (exists) { + final Optional<AsInst> optional = + databaseServiceProvider.getAsInstByName(createAsRequest.getAsInstanceName()); + final AsInst asInst = optional.get(); + execution.setVariable(AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, + new ErrorDetails().detail("As Instance already exists in database : " + asInst.toString())); + } + + logger.info("Finished executing doesAsInstanceExistsInDb ..."); + + } + + public void createAsInstanceInDb(final DelegateExecution execution) { + try { + logger.info("Executing createAsInstanceInDb ..."); + + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Creating AS Instance entry in database"); + + final CreateAsRequest createAsRequest = + (CreateAsRequest) execution.getVariable(CREATE_AS_REQUEST_PARAM_NAME); + + final Map<String, Object> additionalParams = createAsRequest.getAdditionalParams(); + + if (additionalParams == null) { + abortOperation(execution, "Missing 'additionalParams' mandatory field"); + } + + final String cloudOwner = getMandatoryValue(additionalParams, CLOUD_OWNER_PARAM_KEY, execution); + final String cloudRegion = getMandatoryValue(additionalParams, CLOUD_REGION_PARAM_KEY, execution); + final String tenantId = getMandatoryValue(additionalParams, TENANT_ID_PARAM_KEY, execution); + final String resourceId = (String) additionalParams.get(RESOURCE_ID_KEY); + + final String serviceInstanceName = + getMandatoryValue(additionalParams, SERVICE_INSTANCE_NAME_PARAM_KEY, execution); + final String serviceInstanceId = + getMandatoryValue(additionalParams, SERVICE_INSTANCE_ID_PARAM_KEY, execution); + + final String asInstId = getAsInstId(resourceId); + execution.setVariable(AS_INSTANCE_ID_PARAM_NAME, asInstId); + + @SuppressWarnings("unchecked") + final Map<String, Object> asdProperties = + (Map<String, Object>) execution.getVariable(ASD_PROPERTIES_PARAM_NAME); + + final AsInst asInst = new AsInst().asInstId(asInstId).name(createAsRequest.getAsInstanceName()) + .asdId(createAsRequest.getAsdId()) + .asPackageId(getParamValue(asdProperties, DESCRIPTOR_ID_PARAM_NAME)) + .asdInvariantId(getParamValue(asdProperties, DESCRIPTOR_INVARIANT_ID_PARAM_NAME)) + .asProvider(getParamValue(asdProperties, PROVIDER_PARAM_NAME)) + .asApplicationName(getParamValue(asdProperties, APPLICATION_NAME_PARAM_NAME)) + .asApplicationVersion(getParamValue(asdProperties, APPLICATION_VERSION_PARAM_NAME)) + .description(createAsRequest.getAsInstanceDescription()).serviceInstanceId(serviceInstanceId) + .serviceInstanceName(serviceInstanceName).cloudOwner(cloudOwner).cloudRegion(cloudRegion) + .tenantId(tenantId).status(State.NOT_INSTANTIATED).statusUpdatedTime(LocalDateTime.now()); + + @SuppressWarnings("unchecked") + final List<DeploymentItem> deploymentItems = + (List<DeploymentItem>) asdProperties.get(DEPLOYMENT_ITEMS_PARAM_NAME); + + if (deploymentItems != null) { + deploymentItems.forEach(item -> { + final AsDeploymentItem asDeploymentItem = + new AsDeploymentItem().itemId(item.getItemId()).name(item.getName()) + .deploymentOrder(item.getDeploymentOrder() != null + ? Integer.parseInt(item.getDeploymentOrder()) + : null) + .artifactFilePath(item.getFile()).status(State.NOT_INSTANTIATED) + .createTime(LocalDateTime.now()).lastUpdateTime(LocalDateTime.now()) + .releaseName(generateReleaseName(asInst, item)); + final List<AsLifecycleParam> lifecycleParams = getLifeCycleParams(asDeploymentItem, item); + asDeploymentItem.setAsLifecycleParams(lifecycleParams); + asInst.asdeploymentItems(asDeploymentItem); + }); + } + + databaseServiceProvider.saveAsInst(asInst); + logger.info("Finished executing createAsInstanceInDb ..."); + } catch (final Exception exception) { + logger.error("Unable to create AsInst object in database", exception); + throw exception; + } + + } + + private List<AsLifecycleParam> getLifeCycleParams(final AsDeploymentItem asDeploymentItem, + final DeploymentItem deploymentItem) { + final List<AsLifecycleParam> asLifecycleParams = new ArrayList<>(); + if (deploymentItem.getLifecycleParameters() != null) { + for (final String lifecycleParam : deploymentItem.getLifecycleParameters()) { + asLifecycleParams.add( + new AsLifecycleParam().asDeploymentItemInst(asDeploymentItem).asLifecycleParam(lifecycleParam)); + } + + + } + return asLifecycleParams; + } + + private String generateReleaseName(final AsInst asInst, final DeploymentItem item) { + return String.join("-", Arrays.asList(asInst.getName(), item.getName(), item.getItemId())).toLowerCase() + .replaceAll("[\\s\\_]", "-"); + } + + public void createGenericVnfInstanceInAai(final DelegateExecution execution) { + logger.info("Executing createAsInstanceInAai ..."); + try { + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Creating Generic Vnf Instance in AAI"); + + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + final AsInst asInst = getAsInst(execution, asInstId); + + final GenericVnf genericVnf = new GenericVnf(); + genericVnf.setVnfId(asInstId); + genericVnf.setVnfName(asInst.getName()); + genericVnf.setVnfType(asInst.getServiceInstanceName() + "/" + asInst.getName()); + genericVnf.setServiceId(asInst.getServiceInstanceId()); + genericVnf.setOperationalStatus("Created"); + genericVnf.setOrchestrationStatus("Created"); + genericVnf.setIsClosedLoopDisabled(false); + aaiServiceProvider.createGenericVnfAndConnectServiceInstance(asInst.getServiceInstanceId(), asInstId, + genericVnf); + + aaiServiceProvider.connectGenericVnfToTenant(asInstId, asInst.getCloudOwner(), asInst.getCloudRegion(), + asInst.getTenantId()); + + } catch (final Exception exception) { + final String message = "Unable to Create Generic Vnf Instance in AAI"; + logger.error(message, exception); + abortOperation(execution, message); + } + logger.info("Finished executing createNsInstanceInAai ..."); + + } + + public void setCreateAsResponse(final DelegateExecution execution) { + logger.info("Executing setCreateAsResponse ..."); + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + final Optional<AsInst> optional = databaseServiceProvider.getAsInst(asInstId); + + if (optional.isPresent()) { + final AsInst asInst = optional.get(); + final AsInstance response = + new AsInstance().asInstanceid(asInst.getAsInstId()).asInstanceName(asInst.getName()) + .asdId(asInst.getAsdId()).asInstanceDescription(asInst.getDescription()) + .instantiationState(InstantiationStateEnum.fromValue(asInst.getStatus().toString())) + .asProvider(asInst.getAsProvider()).asApplicationName(asInst.getAsApplicationName()) + .asApplicationVersion(asInst.getAsApplicationVersion()); + logger.info("Saving CreateNsResponse: {} in Execution ...", response); + execution.setVariable(CREATE_AS_RESPONSE_PARAM_NAME, response); + } else { + final String message = "Unable to find AS Instance in datababse using id: " + asInstId; + logger.error(message); + abortOperation(execution, message); + } + + logger.info("Finished executing setCreateNsResponse ..."); + + } + + private String getMandatoryValue(final Map<String, Object> additionalParams, final String key, + final DelegateExecution execution) { + final Object value = additionalParams.get(key); + if (value == null) { + abortOperation(execution, "Missing '" + key + "' mandatory field"); + } + return value.toString(); + } + + private String getAsInstId(final String resourceId) { + if ((resourceId != null) && !(resourceId.isBlank())) { + logger.debug("Will use resourceId as asInstId: {}", resourceId); + return resourceId; + } + final String asInstId = UUID.randomUUID().toString(); + logger.debug("Creating random UUID for asInstId: {}", asInstId); + return asInstId; + } + + private String getParamValue(final Map<String, Object> properties, final String key) { + final Object object = properties.get(key); + if (object != null) { + return object.toString(); + } + logger.warn("Unable to final property value for key {}", key); + return null; + } +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/CreateAs.bpmn b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/CreateAs.bpmn new file mode 100644 index 0000000..f828e6d --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/CreateAs.bpmn @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1l4zor5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.0.0"> + <bpmn:process id="CreateAs" name=" CreateAs" isExecutable="true"> + <bpmn:startEvent id="StartEvent_1" name="Start Process"> + <bpmn:outgoing>Flow_1tqn5q5</bpmn:outgoing> + </bpmn:startEvent> + <bpmn:endEvent id="EndEvent_1" name="End Process"> + <bpmn:incoming>Flow_0t87ov3</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sequenceFlow id="Flow_1tqn5q5" sourceRef="StartEvent_1" targetRef="Activity_15ksfz6" /> + <bpmn:serviceTask id="Activity_15ksfz6" name="Set Job Status to STARTED" camunda:asyncBefore="true" camunda:expression="${CreateAsTask.setJobStatusToStarted(execution)}"> + <bpmn:incoming>Flow_1tqn5q5</bpmn:incoming> + <bpmn:outgoing>Flow_0y07mxe</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_0y07mxe" sourceRef="Activity_15ksfz6" targetRef="Activity_12yonzp" /> + <bpmn:serviceTask id="Activity_1r4l8w8" name="Set Job Status to FINISHED" camunda:expression="${CreateAsTask.setJobStatusToFinished(execution)}"> + <bpmn:incoming>Flow_1rtsvpm</bpmn:incoming> + <bpmn:outgoing>Flow_0t87ov3</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_0t87ov3" sourceRef="Activity_1r4l8w8" targetRef="EndEvent_1" /> + <bpmn:exclusiveGateway id="Gateway_0fuwzjj" name="Does Asd Package exists?"> + <bpmn:incoming>Flow_09582uw</bpmn:incoming> + <bpmn:outgoing>Flow_1f4vi10</bpmn:outgoing> + <bpmn:outgoing>Flow_0qabgp7</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:serviceTask id="Activity_12yonzp" name="Get As Package from SDC" camunda:expression="${CreateAsTask.getAsPackage(execution)}"> + <bpmn:incoming>Flow_0y07mxe</bpmn:incoming> + <bpmn:outgoing>Flow_09582uw</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_09582uw" sourceRef="Activity_12yonzp" targetRef="Gateway_0fuwzjj" /> + <bpmn:subProcess id="Activity_06ko4e2" name="Error Handling" triggeredByEvent="true"> + <bpmn:startEvent id="Event_1ibvrn2" name="error"> + <bpmn:outgoing>Flow_0554tjv</bpmn:outgoing> + <bpmn:errorEventDefinition id="ErrorEventDefinition_0lc46mh" /> + </bpmn:startEvent> + <bpmn:endEvent id="Event_02f7sr1" name="end"> + <bpmn:incoming>Flow_04xvpee</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sequenceFlow id="Flow_0554tjv" sourceRef="Event_1ibvrn2" targetRef="Activity_1sj0nvr" /> + <bpmn:serviceTask id="Activity_1sj0nvr" name="Set Job Status to ERROR" camunda:asyncBefore="true" camunda:expression="${CreateAsTask.setJobStatusToError(execution)}"> + <bpmn:incoming>Flow_0554tjv</bpmn:incoming> + <bpmn:outgoing>Flow_04xvpee</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_04xvpee" sourceRef="Activity_1sj0nvr" targetRef="Event_02f7sr1" /> + </bpmn:subProcess> + <bpmn:subProcess id="Activity_1dx9fz6" name="Java Exception Handling" triggeredByEvent="true"> + <bpmn:startEvent id="Event_0zne7ch" name="error"> + <bpmn:outgoing>Flow_0j1otrx</bpmn:outgoing> + <bpmn:errorEventDefinition id="ErrorEventDefinition_1p3h4ta" errorRef="Error_0s855yd" camunda:errorCodeVariable="BPMN_javaExpCode" camunda:errorMessageVariable="BPMN_javaExpMsg" /> + </bpmn:startEvent> + <bpmn:endEvent id="Event_0bcyh7u"> + <bpmn:incoming>Flow_0oqv7vl</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sequenceFlow id="Flow_0j1otrx" sourceRef="Event_0zne7ch" targetRef="Activity_15uwy90" /> + <bpmn:serviceTask id="Activity_15uwy90" name="Set Job Status to ERROR" camunda:asyncBefore="true" camunda:expression="${CreateAsTask.setJobStatusToError(execution)}"> + <bpmn:incoming>Flow_0j1otrx</bpmn:incoming> + <bpmn:outgoing>Flow_0oqv7vl</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_0oqv7vl" sourceRef="Activity_15uwy90" targetRef="Event_0bcyh7u" /> + </bpmn:subProcess> + <bpmn:sequenceFlow id="Flow_1f4vi10" name="No" sourceRef="Gateway_0fuwzjj" targetRef="Event_016q8gu"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{not doesAsPackageExists}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:endEvent id="Event_016q8gu"> + <bpmn:incoming>Flow_1f4vi10</bpmn:incoming> + <bpmn:incoming>Flow_1yql1cm</bpmn:incoming> + <bpmn:errorEventDefinition id="ErrorEventDefinition_1ugx52k" errorRef="Error_0rqvnym" /> + </bpmn:endEvent> + <bpmn:sequenceFlow id="Flow_0qabgp7" name="Yes" sourceRef="Gateway_0fuwzjj" targetRef="Activity_0vlb2nk"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{doesAsPackageExists}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:serviceTask id="Activity_0vlb2nk" name="Check AS Instance exists In DB " camunda:expression="${CreateAsTask.doesAsInstanceExistsInDb(execution)}"> + <bpmn:incoming>Flow_0qabgp7</bpmn:incoming> + <bpmn:outgoing>Flow_1exrj2b</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_1exrj2b" sourceRef="Activity_0vlb2nk" targetRef="Gateway_0d7n517" /> + <bpmn:exclusiveGateway id="Gateway_0d7n517"> + <bpmn:incoming>Flow_1exrj2b</bpmn:incoming> + <bpmn:outgoing>Flow_1rkg44s</bpmn:outgoing> + <bpmn:outgoing>Flow_1yql1cm</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="Flow_1rkg44s" name="No" sourceRef="Gateway_0d7n517" targetRef="Activity_09tqz8x"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{not doesAsInstanceExists}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:sequenceFlow id="Flow_1yql1cm" name="Yes" sourceRef="Gateway_0d7n517" targetRef="Event_016q8gu"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{doesAsInstanceExists}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:serviceTask id="Activity_09tqz8x" name="Create AS Instance record in DB" camunda:expression="${CreateAsTask.createAsInstanceInDb(execution)}"> + <bpmn:incoming>Flow_1rkg44s</bpmn:incoming> + <bpmn:outgoing>Flow_1jvfwd2</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_1jvfwd2" sourceRef="Activity_09tqz8x" targetRef="Activity_1akc79d" /> + <bpmn:serviceTask id="Activity_1akc79d" name="Create Generic Vnf Instance in AAI" camunda:expression="${CreateAsTask.createGenericVnfInstanceInAai(execution)}"> + <bpmn:incoming>Flow_1jvfwd2</bpmn:incoming> + <bpmn:outgoing>Flow_0e5hvno</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_0e5hvno" sourceRef="Activity_1akc79d" targetRef="Activity_03ht66t" /> + <bpmn:serviceTask id="Activity_03ht66t" name="Set Create AS Response" camunda:expression="${CreateAsTask.setCreateAsResponse(execution)}"> + <bpmn:incoming>Flow_0e5hvno</bpmn:incoming> + <bpmn:outgoing>Flow_1rtsvpm</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_1rtsvpm" sourceRef="Activity_03ht66t" targetRef="Activity_1r4l8w8" /> + </bpmn:process> + <bpmn:error id="Error_0s855yd" name="java.lang.Exception" errorCode="java.lang.Exception" /> + <bpmn:error id="Error_0rqvnym" name="NsWorkflowProcessingException" errorCode="CREATE_AS_WORKFLOW_PROCESSING_EXCEPTION" /> + <bpmndi:BPMNDiagram id="BPMNDiagram_1"> + <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="CreateAs"> + <bpmndi:BPMNEdge id="Flow_1rtsvpm_di" bpmnElement="Flow_1rtsvpm"> + <di:waypoint x="1160" y="157" /> + <di:waypoint x="1160" y="230" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0e5hvno_di" bpmnElement="Flow_0e5hvno"> + <di:waypoint x="1070" y="117" /> + <di:waypoint x="1110" y="117" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1jvfwd2_di" bpmnElement="Flow_1jvfwd2"> + <di:waypoint x="930" y="117" /> + <di:waypoint x="970" y="117" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1yql1cm_di" bpmnElement="Flow_1yql1cm"> + <di:waypoint x="760" y="142" /> + <di:waypoint x="760" y="230" /> + <di:waypoint x="668" y="230" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="766" y="183" width="19" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1rkg44s_di" bpmnElement="Flow_1rkg44s"> + <di:waypoint x="785" y="117" /> + <di:waypoint x="830" y="117" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="799" y="99" width="14" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1exrj2b_di" bpmnElement="Flow_1exrj2b"> + <di:waypoint x="700" y="117" /> + <di:waypoint x="735" y="117" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0qabgp7_di" bpmnElement="Flow_0qabgp7"> + <di:waypoint x="565" y="117" /> + <di:waypoint x="600" y="117" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="579" y="99" width="19" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1f4vi10_di" bpmnElement="Flow_1f4vi10"> + <di:waypoint x="540" y="142" /> + <di:waypoint x="540" y="230" /> + <di:waypoint x="632" y="230" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="548" y="183" width="14" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_09582uw_di" bpmnElement="Flow_09582uw"> + <di:waypoint x="480" y="117" /> + <di:waypoint x="515" y="117" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0t87ov3_di" bpmnElement="Flow_0t87ov3"> + <di:waypoint x="1160" y="310" /> + <di:waypoint x="1160" y="357" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0y07mxe_di" bpmnElement="Flow_0y07mxe"> + <di:waypoint x="350" y="117" /> + <di:waypoint x="380" y="117" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1tqn5q5_di" bpmnElement="Flow_1tqn5q5"> + <di:waypoint x="208" y="117" /> + <di:waypoint x="250" y="117" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> + <dc:Bounds x="172" y="99" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="158" y="142" width="67" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0db1w1a_di" bpmnElement="EndEvent_1"> + <dc:Bounds x="1142" y="357" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="1129" y="400" width="63" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_15ksfz6_di" bpmnElement="Activity_15ksfz6"> + <dc:Bounds x="250" y="77" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1r4l8w8_di" bpmnElement="Activity_1r4l8w8"> + <dc:Bounds x="1110" y="230" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_0fuwzjj_di" bpmnElement="Gateway_0fuwzjj" isMarkerVisible="true"> + <dc:Bounds x="515" y="92" width="50" height="50" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="502" y="62" width="80" height="27" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_12yonzp_di" bpmnElement="Activity_12yonzp"> + <dc:Bounds x="380" y="77" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_06ko4e2_di" bpmnElement="Activity_06ko4e2" isExpanded="true"> + <dc:Bounds x="431" y="310" width="438" height="130" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="Flow_04xvpee_di" bpmnElement="Flow_04xvpee"> + <di:waypoint x="681" y="373" /> + <di:waypoint x="813" y="373" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0554tjv_di" bpmnElement="Flow_0554tjv"> + <di:waypoint x="489" y="373" /> + <di:waypoint x="581" y="373" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Event_1ibvrn2_di" bpmnElement="Event_1ibvrn2"> + <dc:Bounds x="453" y="355" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="459" y="398" width="24" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_02f7sr1_di" bpmnElement="Event_02f7sr1"> + <dc:Bounds x="813" y="355" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="823" y="397" width="19" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1sj0nvr_di" bpmnElement="Activity_1sj0nvr"> + <dc:Bounds x="581" y="333" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1dx9fz6_di" bpmnElement="Activity_1dx9fz6" isExpanded="true"> + <dc:Bounds x="431" y="470" width="438" height="130" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="Flow_0oqv7vl_di" bpmnElement="Flow_0oqv7vl"> + <di:waypoint x="680" y="533" /> + <di:waypoint x="772" y="533" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0j1otrx_di" bpmnElement="Flow_0j1otrx"> + <di:waypoint x="522" y="533" /> + <di:waypoint x="580" y="533" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Event_0zne7ch_di" bpmnElement="Event_0zne7ch"> + <dc:Bounds x="486" y="515" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="493" y="558" width="24" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0bcyh7u_di" bpmnElement="Event_0bcyh7u"> + <dc:Bounds x="772" y="515" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_15uwy90_di" bpmnElement="Activity_15uwy90"> + <dc:Bounds x="580" y="493" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0spfqz1_di" bpmnElement="Event_016q8gu"> + <dc:Bounds x="632" y="212" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0vlb2nk_di" bpmnElement="Activity_0vlb2nk"> + <dc:Bounds x="600" y="77" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_0d7n517_di" bpmnElement="Gateway_0d7n517" isMarkerVisible="true"> + <dc:Bounds x="735" y="92" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_09tqz8x_di" bpmnElement="Activity_09tqz8x"> + <dc:Bounds x="830" y="77" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1akc79d_di" bpmnElement="Activity_1akc79d"> + <dc:Bounds x="970" y="77" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_03ht66t_di" bpmnElement="Activity_03ht66t"> + <dc:Bounds x="1110" y="77" width="100" height="80" /> + </bpmndi:BPMNShape> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</bpmn:definitions> diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/BaseTest.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/BaseTest.java new file mode 100644 index 0000000..9920ab9 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/BaseTest.java @@ -0,0 +1,181 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.onap.so.cnfm.lcm.bpmn.flows; + +import static org.camunda.bpm.engine.history.HistoricProcessInstance.STATE_ACTIVE; +import static org.slf4j.LoggerFactory.getLogger; + +import com.github.tomakehurst.wiremock.WireMockServer; +import java.io.IOException; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import org.camunda.bpm.engine.HistoryService; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.history.HistoricProcessInstance; +import org.camunda.bpm.engine.history.HistoricVariableInstance; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.junit.runner.RunWith; +//import org.onap.so.cnfm.lcm.bpmn.flows.service.KubConfigProvider; +//import org.onap.so.cnfm.lcm.bpmn.flows.tasks.MockedHelmClientConfiguration; +//import org.onap.so.cnfm.lcm.bpmn.flows.tasks.MockedKubernetesClientProviderConfiguration; +import org.onap.so.cnfm.lcm.database.beans.AsInst; +import org.onap.so.cnfm.lcm.database.beans.Job; +import org.onap.so.cnfm.lcm.database.beans.JobAction; +import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum; +import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +//import org.springframework.context.annotation.Import; +//import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.FileSystemUtils; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles("test") +@ContextConfiguration +@AutoConfigureWireMock(port = 0) +//@Import({MockedHelmClientConfiguration.class, MockedKubernetesClientProviderConfiguration.class}) +public abstract class BaseTest { + protected static final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString(); + protected static final String SERVICE_INSTANCE_NAME = "ServiceName"; +// private static final String KUBE_CONFIG_EMPTY_FILE_NAME = "kube-config-empty-file"; +// private static final String EMPTY = ""; + + protected static final String UUID_REGEX = + "[0-9a-zA-Z]{8}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{12}"; + protected static final String RANDOM_JOB_ID = UUID.randomUUID().toString(); + protected static final Logger logger = getLogger(BaseTest.class); + + private static final long TIME_OUT_IN_SECONDS = 120; + private static final int SLEEP_TIME_IN_SECONDS = 5; + + @Autowired + private HistoryService historyService; + + @Autowired + private RuntimeService runtimeService; + +// @Autowired +// private KubConfigProvider kubConfigProvider; + + @Autowired + protected DatabaseServiceProvider databaseServiceProvider; + + @Autowired + protected WireMockServer wireMockServer; + + public Job createNewJob(final String jobAction, final String nsdId, final String nsName) { + final Job newJob = new Job().startTime(LocalDateTime.now()).jobType("AS").jobAction(JobAction.CREATE) + .status(JobStatusEnum.STARTING).resourceId(nsdId).resourceName(nsName); + databaseServiceProvider.addJob(newJob); + return newJob; + } + + public Optional<Job> getJob(final String jobId) { + return databaseServiceProvider.getJob(jobId); + } + + public Optional<Job> getJobByResourceId(final String resourceId) { + return databaseServiceProvider.getJobByResourceId(resourceId); + } + + public ProcessInstance executeWorkflow(final String processDefinitionKey, final String businessKey, + final Map<String, Object> variables) { + return runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables); + } + + public HistoricProcessInstance getHistoricProcessInstance(final String processInstanceId) { + return historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + } + + public HistoricVariableInstance getVariable(final String processInstanceId, final String name) { + return historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId) + .variableName(name).singleResult(); + } + + public List<HistoricVariableInstance> getVariables(final String processInstanceId) { + return historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list(); + } + + public boolean waitForProcessInstanceToFinish(final String processInstanceId) throws InterruptedException { + final long startTimeInMillis = System.currentTimeMillis(); + final long timeOutTime = startTimeInMillis + TimeUnit.SECONDS.toMillis(TIME_OUT_IN_SECONDS); + while (timeOutTime > System.currentTimeMillis()) { + + if (isProcessEndedByProcessInstanceId(processInstanceId)) { + logger.info("processInstanceId: {} is finished", processInstanceId); + return true; + } + logger.info("processInstanceId: {} is still running", processInstanceId); + logger.info("Process instance {} not finished yet, will try again in {} seconds", processInstanceId, + SLEEP_TIME_IN_SECONDS); + TimeUnit.SECONDS.sleep(SLEEP_TIME_IN_SECONDS); + } + logger.warn("Timeout {} process didn't finished ", processInstanceId); + return false; + } + + + public boolean isProcessEndedByProcessInstanceId(final String processInstanceId) { + return !isProcessInstanceActive(processInstanceId) && isProcessInstanceEnded(processInstanceId) + && isProcessInstanceCompleted(processInstanceId); + } + + private boolean isProcessInstanceActive(final String processInstanceId) { + final HistoricProcessInstance processInstance = getHistoricProcessInstance(processInstanceId); + return processInstance != null && STATE_ACTIVE.equalsIgnoreCase(processInstance.getState()); + } + + private boolean isProcessInstanceEnded(final String processInstanceId) { + return runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult() == null; + } + + private boolean isProcessInstanceCompleted(final String processInstanceId) { + final HistoricProcessInstance result = + historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + return result == null ? false : HistoricProcessInstance.STATE_COMPLETED.equalsIgnoreCase(result.getState()); + } + + public void createKubeConfigFile(final AsInst asInst) throws IOException { +// final MockMultipartFile file = new MockMultipartFile(KUBE_CONFIG_EMPTY_FILE_NAME, EMPTY.getBytes()); +// kubConfigProvider.addKubeConfigFile(file, asInst.getCloudOwner(), asInst.getCloudRegion(), +// asInst.getTenantId()); + } + + public void deleteFoldersAndFiles(final Path path) throws IOException { + FileSystemUtils.deleteRecursively(path); + } + +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/DefaultToShortClassNameBeanNameGenerator.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/DefaultToShortClassNameBeanNameGenerator.java new file mode 100644 index 0000000..3ae5cac --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/DefaultToShortClassNameBeanNameGenerator.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.onap.so.cnfm.lcm.bpmn.flows; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.AnnotationBeanNameGenerator; +import org.springframework.util.ClassUtils; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public class DefaultToShortClassNameBeanNameGenerator extends AnnotationBeanNameGenerator { + + @Override + protected String buildDefaultBeanName(final BeanDefinition definition) { + return ClassUtils.getShortName(definition.getBeanClassName()); + } +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/TestApplication.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/TestApplication.java new file mode 100644 index 0000000..40868ab --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/TestApplication.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.onap.so.cnfm.lcm.bpmn.flows; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.ComponentScan.Filter; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@SpringBootApplication(scanBasePackages = {"org.onap.so"}) +@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class}) +@ComponentScan(basePackages = {"org.onap"}, nameGenerator = DefaultToShortClassNameBeanNameGenerator.class, + excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = SpringBootApplication.class)}) +public class TestApplication { + + public static void main(final String[] args) { + new SpringApplication(TestApplication.class).run(args); + } + +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/CreateAsTaskTest.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/CreateAsTaskTest.java new file mode 100644 index 0000000..bd0afe9 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/CreateAsTaskTest.java @@ -0,0 +1,191 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.notFound; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.onap.aaiclient.client.aai.AAIVersion.V19; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.CLOUD_OWNER_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.CLOUD_REGION_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.SERVICE_INSTANCE_ID_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.SERVICE_INSTANCE_NAME_PARAM_KEY; +import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.TENANT_ID_PARAM_KEY; +import static org.springframework.http.HttpHeaders.ACCEPT; +import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.camunda.bpm.engine.history.HistoricProcessInstance; +import org.camunda.bpm.engine.history.HistoricVariableInstance; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.aaiclient.client.aai.entities.Results; +import org.onap.aaiclient.client.graphinventory.entities.Resource; +import org.onap.so.cnfm.lcm.bpmn.flows.BaseTest; +import org.onap.so.cnfm.lcm.bpmn.flows.service.JobExecutorService; +import org.onap.so.cnfm.lcm.database.beans.Job; +import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum; +import org.onap.so.cnfm.lcm.model.AsInstance; +import org.onap.so.cnfm.lcm.model.AsInstance.InstantiationStateEnum; +import org.onap.so.cnfm.lcm.model.CreateAsRequest; +import org.springframework.beans.factory.annotation.Autowired; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public class CreateAsTaskTest extends BaseTest { + private static final String SRC_TEST_DIR = "src/test/resources"; + private static final String TENAT_ID = UUID.randomUUID().toString(); + private static final String CLOUD_OWNER = "CloudOwner"; + private static final String CLOUD_REGION = "CloudRegion"; + private static final String ASD_ID = UUID.randomUUID().toString(); + private static final String AS_NAME = "CreateAsService-" + ASD_ID; + private static final String SDC_GET_RESOURCE_URL = "/sdc/v1/catalog/resources/" + ASD_ID + "/toscaModel"; + private static final String RESOURCE_ASD_PACKAGE_CSAR_PATH = + SRC_TEST_DIR + "/resource-Generatedasdpackage-csar.csar"; + + @Autowired + private JobExecutorService objUnderTest; + + @Before + public void before() { + wireMockServer.resetAll(); + } + + @After + public void after() { + wireMockServer.resetAll(); + } + + @Test + public void testCreateAsWorkflow_SuccessfullCase() throws InterruptedException, IOException { + + wireMockServer.stubFor(get(SDC_GET_RESOURCE_URL) + .willReturn(aResponse().withBody(getFileContent(getAbsolutePath(RESOURCE_ASD_PACKAGE_CSAR_PATH))) + .withHeader(ACCEPT, APPLICATION_OCTET_STREAM_VALUE))); + + final CreateAsRequest createAsRequest = getCreateAsRequest(); + + mockAAIEndpoints(); + + final AsInstance nsResponse = objUnderTest.runCreateAsJob(createAsRequest); + assertNotNull(nsResponse); + assertNotNull(nsResponse.getAsInstanceid()); + + final Optional<Job> optional = getJobByResourceId(createAsRequest.getAsdId()); + assertTrue(optional.isPresent()); + final Job job = optional.get(); + + assertTrue(waitForProcessInstanceToFinish(job.getProcessInstanceId())); + + final HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(job.getProcessInstanceId()); + assertNotNull(historicProcessInstance); + + assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState()); + assertTrue(databaseServiceProvider.isAsInstExists(createAsRequest.getAsInstanceName())); + + final Job actualJob = optional.get(); + assertEquals(JobStatusEnum.FINISHED, actualJob.getStatus()); + + assertEquals(AS_NAME, nsResponse.getAsInstanceName()); + assertEquals(InstantiationStateEnum.NOT_INSTANTIATED, nsResponse.getInstantiationState()); + + final HistoricVariableInstance doesNsPackageExistsVar = + getVariable(job.getProcessInstanceId(), "doesAsPackageExists"); + assertNotNull(doesNsPackageExistsVar); + assertTrue((boolean) doesNsPackageExistsVar.getValue()); + + final HistoricVariableInstance doesNsInstanceExistsVar = + getVariable(job.getProcessInstanceId(), "doesAsInstanceExists"); + assertNotNull(doesNsInstanceExistsVar); + assertFalse((boolean) doesNsInstanceExistsVar.getValue()); + + } + + private CreateAsRequest getCreateAsRequest() { + return getCreateAsRequest(ASD_ID, AS_NAME); + } + + private CreateAsRequest getCreateAsRequest(final String asdId, final String asName) { + final Map<String, Object> additionalParams = Map.of(SERVICE_INSTANCE_ID_PARAM_KEY, SERVICE_INSTANCE_ID, + SERVICE_INSTANCE_NAME_PARAM_KEY, SERVICE_INSTANCE_NAME, CLOUD_OWNER_PARAM_KEY, CLOUD_OWNER, + CLOUD_REGION_PARAM_KEY, CLOUD_REGION, TENANT_ID_PARAM_KEY, TENAT_ID); + + return new CreateAsRequest().asdId(asdId).asInstanceName(asName).additionalParams(additionalParams); + } + + private void mockAAIEndpoints() throws JsonProcessingException { + final String modelEndpoint = "/aai/" + V19 + "/network/generic-vnfs/generic-vnf/" + UUID_REGEX; + + wireMockServer.stubFor( + get(urlMatching(modelEndpoint + "\\?resultIndex=0&resultSize=1&format=count")).willReturn(notFound())); + + wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(ok())); + wireMockServer.stubFor(put(urlMatching(modelEndpoint + "/relationship-list/relationship")).willReturn(ok())); + + wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(ok()) + .willReturn(okJson("{\"orchestration-status\": \"Created\"}"))); + + wireMockServer.stubFor(get(urlMatching("/aai/" + V19 + "/nodes/service-instances/service-instance/.*")) + .willReturn(okJson(getResourceResultsResponseAsJson(SERVICE_INSTANCE_ID)))); + + wireMockServer.stubFor(put(urlMatching("/aai/" + V19 + "/cloud-infrastructure/cloud-regions/cloud-region/" + + CLOUD_OWNER + "/" + CLOUD_REGION + "/tenants/tenant/" + TENAT_ID + "/relationship-list/relationship")) + .willReturn(ok())); + + } + + private String getResourceResultsResponseAsJson(final String nsdId) throws JsonProcessingException { + final Resource resource = new Resource(); + resource.setResourceType("service-instance"); + resource.setResourceLink("/aai/" + V19 + "/business/customers/customer/GLOBAL_CUSTOMER_ID" + + "/service-subscriptions/service-subscription/NetworkService/service-instances/service-instance/" + + nsdId); + final Results<Resource> results = new Results<>(); + results.getResult().add(resource); + return new ObjectMapper().writeValueAsString(results); + } + + private Path getAbsolutePath(final String path) { + final File file = new File(path); + return file.toPath(); + } + + private byte[] getFileContent(final Path path) throws IOException { + return Files.readAllBytes(path); + } +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/resources/application.yaml b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/resources/application.yaml index 404bbdb..72bc80f 100644 --- a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/resources/application.yaml +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/resources/application.yaml @@ -1,4 +1,4 @@ -# Copyright © 2022 Nordix Foundation +# Copyright © 2023 Nordix Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. |