summaryrefslogtreecommitdiffstats
path: root/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main
diff options
context:
space:
mode:
authorwaqas.ikram <waqas.ikram@est.tech>2023-01-23 14:59:18 +0000
committerwaqas.ikram <waqas.ikram@est.tech>2023-01-23 14:59:29 +0000
commit9783df1b5660ee0e0460cfd8dc5477a7edcb1d94 (patch)
treee3ffe3209ff38f839cd1af60a4f0dffd341dd1ee /so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main
parentbd591af78a4ab97af4f65d6b7094d9c60f7879c4 (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/src/main')
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/AbstractServiceTask.java208
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/CreateAsTask.java342
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/CreateAs.bpmn266
3 files changed, 816 insertions, 0 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="&#10;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>