Adding NS instantiation 76/112276/1
authorwaqas.ikram <waqas.ikram@est.tech>
Tue, 8 Sep 2020 13:15:20 +0000 (14:15 +0100)
committerwaqas.ikram <waqas.ikram@est.tech>
Tue, 8 Sep 2020 13:37:08 +0000 (14:37 +0100)
Change-Id: I41d32ddab1ba1e4eea42129a5918bdea3312de94
Issue-ID: SO-2868
Signed-off-by: waqas.ikram <waqas.ikram@est.tech>
15 files changed:
so-etsi-nfvo/pom.xml
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/pom.xml
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateRequest.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateVnfTask.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/CreateInstantiateVnf.bpmn [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/InstantiateNs.bpmn [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/InstantiateNsTaskTest.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/NsLcmOpOcc.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/State.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/service/DatabaseServiceProvider.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/lifecycle/NsLifeCycleManager.java

index 0b87b25..fa85460 100644 (file)
@@ -27,6 +27,7 @@
     <okio-version>1.13.0</okio-version>
     <jaxb-api>2.3.0</jaxb-api>
     <snakeyaml-version>0.11</snakeyaml-version>
+    <hamcrest-version>2.2</hamcrest-version>
   </properties>
 
   <build>
index 39acdd8..1c13eca 100644 (file)
       <artifactId>h2</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest</artifactId>
+      <version>${hamcrest-version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
\ No newline at end of file
index a373df4..65d982c 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog;
 import java.util.Optional;
 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.NetworkServiceDescriptor;
 
 /**
  * @author Waqas Ikram (waqas.ikram@est.tech)
@@ -33,4 +34,6 @@ public interface EtsiCatalogPackageManagementServiceProvider {
 
     Optional<VnfPkgInfo> getVnfPkgInfo(final String vnfPkgId);
 
+    Optional<NetworkServiceDescriptor> getNetworkServiceDescriptor(final String nsdId);
+
 }
index 32f7cc1..75dd710 100644 (file)
@@ -24,6 +24,8 @@ import java.util.Optional;
 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo;
 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.EtsiCatalogManagerRequestFailureException;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.NetworkServiceDescriptor;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.NetworkServiceDescriptorParser;
 import org.onap.so.rest.service.HttpRestServiceProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -43,12 +45,15 @@ public class EtsiCatalogPackageManagementServiceProviderImpl implements EtsiCata
 
     private final HttpRestServiceProvider httpServiceProvider;
     private final EtsiCatalogUrlProvider etsiCatalogUrlProvider;
+    private final NetworkServiceDescriptorParser networkServiceDescriptorParser;
 
     @Autowired
     public EtsiCatalogPackageManagementServiceProviderImpl(final EtsiCatalogUrlProvider etsiCatalogUrlProvider,
-            @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN) final HttpRestServiceProvider httpServiceProvider) {
+            @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN) final HttpRestServiceProvider httpServiceProvider,
+            final NetworkServiceDescriptorParser networkServiceDescriptorParser) {
         this.etsiCatalogUrlProvider = etsiCatalogUrlProvider;
         this.httpServiceProvider = httpServiceProvider;
+        this.networkServiceDescriptorParser = networkServiceDescriptorParser;
     }
 
     @Override
@@ -83,4 +88,23 @@ public class EtsiCatalogPackageManagementServiceProviderImpl implements EtsiCata
         }
     }
 
+    @Override
+    public Optional<NetworkServiceDescriptor> getNetworkServiceDescriptor(final String nsdId) {
+        try {
+            final ResponseEntity<byte[]> response = httpServiceProvider
+                    .getHttpResponse(etsiCatalogUrlProvider.getNsPackageContentUrl(nsdId), byte[].class);
+            if (response.getStatusCode().is2xxSuccessful()) {
+                if (response.hasBody()) {
+                    return networkServiceDescriptorParser.parse(response.getBody());
+                }
+                logger.error("Received response without body ...");
+            }
+            return Optional.empty();
+        } catch (final Exception restProcessingException) {
+            logger.error("Caught exception while getting NS package content for: {}", nsdId, restProcessingException);
+            throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.",
+                    restProcessingException);
+        }
+    }
+
 }
index 692aff6..f3c38e5 100644 (file)
@@ -21,12 +21,19 @@ package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service;
 
 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_REQUEST_PARAM_NAME;
 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.GLOBAL_CUSTOMER_ID_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.INSTANTIATE_NS_REQUEST_PARAM_NAME;
 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.JOB_ID_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_INSTANCE_ID_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.OCC_ID_PARAM_NAME;
 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.SERVICE_TYPE_PARAM_NAME;
 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.CREATE_NS_WORKFLOW_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.INSTANTIATE_NS_WORKFLOW_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobAction.INSTANTIATE;
 import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.ERROR;
 import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED;
 import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED_WITH_ERROR;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.IN_PROGRESS;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.STARTING;
 import static org.slf4j.LoggerFactory.getLogger;
 import java.time.Instant;
 import java.time.LocalDateTime;
@@ -35,19 +42,25 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider;
 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.NsRequestProcessingException;
 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobAction;
 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum;
 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpType;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum;
 import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider;
 import org.onap.so.etsi.nfvo.ns.lcm.model.CreateNsRequest;
 import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400;
+import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest;
 import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import com.google.common.collect.ImmutableSet;
+import com.google.gson.Gson;
 
 /**
  * @author Waqas Ikram (waqas.ikram@est.tech)
@@ -69,13 +82,16 @@ public class JobExecutorService {
     private final DatabaseServiceProvider databaseServiceProvider;
     private final WorkflowExecutorService workflowExecutorService;
     private final WorkflowQueryService workflowQueryService;
+    private Gson gson;
 
     @Autowired
     public JobExecutorService(final DatabaseServiceProvider databaseServiceProvider,
-            final WorkflowExecutorService workflowExecutorService, final WorkflowQueryService workflowQueryService) {
+            final WorkflowExecutorService workflowExecutorService, final WorkflowQueryService workflowQueryService,
+            final GsonProvider gsonProvider) {
         this.databaseServiceProvider = databaseServiceProvider;
         this.workflowExecutorService = workflowExecutorService;
         this.workflowQueryService = workflowQueryService;
+        gson = gsonProvider.getGson();
     }
 
     public NsInstancesNsInstance runCreateNsJob(final CreateNsRequest createNsRequest, final String globalCustomerId,
@@ -130,6 +146,50 @@ public class JobExecutorService {
         return optional.get();
     }
 
+    public String runInstantiateNsJob(final String nsInstanceId, final InstantiateNsRequest instantiateNsRequest) {
+
+        final NfvoJob newJob = new NfvoJob().startTime(LocalDateTime.now()).jobType("NS").jobAction(INSTANTIATE)
+                .resourceId(nsInstanceId).status(STARTING).progress(0);
+        databaseServiceProvider.addJob(newJob);
+        logger.info("New job created in database :\n{}", newJob);
+
+        final LocalDateTime currentDateTime = LocalDateTime.now();
+        final NsLcmOpOcc newNsLcmOpOcc = new NsLcmOpOcc().id(nsInstanceId).operation(NsLcmOpType.INSTANTIATE)
+                .operationState(OperationStateEnum.PROCESSING).stateEnteredTime(currentDateTime)
+                .startTime(currentDateTime).isAutoInnovation(false).isCancelPending(false)
+                .operationParams(gson.toJson(instantiateNsRequest));
+        databaseServiceProvider.addNSLcmOpOcc(newNsLcmOpOcc);
+        logger.info("New NSLcmOpOcc created in database :\n{}", newNsLcmOpOcc);
+
+        workflowExecutorService.executeWorkflow(newJob.getJobId(), INSTANTIATE_NS_WORKFLOW_NAME,
+                getVariables(nsInstanceId, newJob.getJobId(), newNsLcmOpOcc.getId(), instantiateNsRequest));
+
+        final ImmutableSet<JobStatusEnum> jobFinishedStates =
+                ImmutableSet.of(FINISHED, ERROR, FINISHED_WITH_ERROR, IN_PROGRESS);
+        final ImmutablePair<String, JobStatusEnum> immutablePair =
+                waitForJobToFinish(newJob.getJobId(), jobFinishedStates);
+
+        if (immutablePair.getRight() == null) {
+            final String message = "Failed to Instantiate NS for request: \n" + instantiateNsRequest;
+            logger.error(message);
+            throw new NsRequestProcessingException(message);
+        }
+
+        final JobStatusEnum finalJobStatus = immutablePair.getRight();
+
+        if (IN_PROGRESS.equals(finalJobStatus) || FINISHED.equals(finalJobStatus)) {
+            logger.info("Instantiation Job status: {}", finalJobStatus);
+
+
+            return newNsLcmOpOcc.getId();
+        }
+
+        final String message = "Received unexpected Job Status: " + finalJobStatus
+                + " Failed to instantiate NS for request: \n" + instantiateNsRequest;
+        logger.error(message);
+        throw new NsRequestProcessingException(message);
+    }
+
     private ImmutablePair<String, JobStatusEnum> waitForJobToFinish(final String jobId,
             final ImmutableSet<JobStatusEnum> jobFinishedStates) {
         try {
@@ -179,4 +239,14 @@ public class JobExecutorService {
         return variables;
     }
 
+    private Map<String, Object> getVariables(final String nsInstanceId, final String jobId, final String occId,
+            final InstantiateNsRequest instantiateNsRequest) {
+        final Map<String, Object> variables = new HashMap<>();
+        variables.put(NS_INSTANCE_ID_PARAM_NAME, nsInstanceId);
+        variables.put(JOB_ID_PARAM_NAME, jobId);
+        variables.put(OCC_ID_PARAM_NAME, occId);
+        variables.put(INSTANTIATE_NS_REQUEST_PARAM_NAME, instantiateNsRequest);
+        return variables;
+    }
+
 }
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateRequest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateRequest.java
new file mode 100644 (file)
index 0000000..569d9b3
--- /dev/null
@@ -0,0 +1,167 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 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.etsi.nfvo.ns.lcm.bpmn.flows.tasks;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.utils.Utils.toIndentedString;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Objects;
+import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.Tenant;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class CreateInstantiateRequest implements Serializable {
+    private static final long serialVersionUID = -4371264952509580468L;
+    private String nsInstId;
+    private String vnfdId;
+    private String vnfName;
+    private String vnfPkgId;
+    private String nfType;
+    private Tenant tenant;
+    private Map<String, String> additionalParams;
+
+    public String getNsInstId() {
+        return nsInstId;
+    }
+
+    public void setNsInstId(final String nsInstId) {
+        this.nsInstId = nsInstId;
+    }
+
+    public CreateInstantiateRequest nsInstId(final String nsInstId) {
+        this.nsInstId = nsInstId;
+        return this;
+    }
+
+    public final String getVnfdId() {
+        return vnfdId;
+    }
+
+    public final void setVnfdId(final String vnfdId) {
+        this.vnfdId = vnfdId;
+    }
+
+    public CreateInstantiateRequest vnfdId(final String vnfdId) {
+        this.vnfdId = vnfdId;
+        return this;
+    }
+
+    public final String getVnfName() {
+        return vnfName;
+    }
+
+    public final void setVnfName(final String vnfName) {
+        this.vnfName = vnfName;
+    }
+
+    public CreateInstantiateRequest vnfName(final String vnfName) {
+        this.vnfName = vnfName;
+        return this;
+    }
+
+    public final String getVnfPkgId() {
+        return vnfPkgId;
+    }
+
+    public final void setVnfPkgId(final String vnfPkgId) {
+        this.vnfPkgId = vnfPkgId;
+    }
+
+    public CreateInstantiateRequest vnfPkgId(final String vnfPkgId) {
+        this.vnfPkgId = vnfPkgId;
+        return this;
+    }
+
+    public final String getNfType() {
+        return nfType;
+    }
+
+    public final void setNfType(final String nfType) {
+        this.nfType = nfType;
+    }
+
+    public CreateInstantiateRequest nfType(final String nfType) {
+        this.nfType = nfType;
+        return this;
+    }
+
+    public final Tenant getTenant() {
+        return tenant;
+    }
+
+    public final void setTenant(final Tenant tenant) {
+        this.tenant = tenant;
+    }
+
+    public CreateInstantiateRequest tenant(final Tenant tenant) {
+        this.tenant = tenant;
+        return this;
+    }
+
+    public final Map<String, String> getAdditionalParams() {
+        return additionalParams;
+    }
+
+    public final void setAdditionalParams(final Map<String, String> additionalParams) {
+        this.additionalParams = additionalParams;
+    }
+
+    public CreateInstantiateRequest additionalParams(final Map<String, String> additionalParams) {
+        this.additionalParams = additionalParams;
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(nsInstId, vnfdId, vnfName, vnfPkgId, nfType, tenant, additionalParams);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof CreateInstantiateRequest) {
+            final CreateInstantiateRequest other = (CreateInstantiateRequest) obj;
+            return Objects.equals(nsInstId, other.nsInstId) && Objects.equals(vnfdId, other.vnfdId)
+                    && Objects.equals(vnfName, other.vnfName) && Objects.equals(vnfPkgId, other.vnfPkgId)
+                    && Objects.equals(nfType, other.nfType) && Objects.equals(tenant, other.tenant)
+                    && Objects.equals(additionalParams, other.additionalParams);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("class CreateInstantiateRequest {\n");
+        sb.append("    nsInstId: ").append(toIndentedString(nsInstId)).append("\n");
+        sb.append("    vnfdId: ").append(toIndentedString(vnfdId)).append("\n");
+        sb.append("    vnfName: ").append(toIndentedString(vnfName)).append("\n");
+        sb.append("    vnfPkgId: ").append(toIndentedString(vnfPkgId)).append("\n");
+        sb.append("    nfType: ").append(toIndentedString(nfType)).append("\n");
+        sb.append("    tenant: ").append(toIndentedString(tenant)).append("\n");
+        sb.append("    additionalParams: ").append(toIndentedString(additionalParams)).append("\n");
+
+        sb.append("}");
+        return sb.toString();
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateVnfTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateVnfTask.java
new file mode 100644 (file)
index 0000000..c33c67e
--- /dev/null
@@ -0,0 +1,234 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 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.etsi.nfvo.ns.lcm.bpmn.flows.tasks;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_INSTANCE_ID_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.ERROR;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.IN_PROGRESS;
+import java.time.LocalDateTime;
+import java.util.Optional;
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfRequest;
+import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfResponse;
+import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.Tenant;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai.AaiServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State;
+import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider;
+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 CreateInstantiateVnfTask extends AbstractNetworkServiceTask {
+    private static final Logger logger = LoggerFactory.getLogger(CreateInstantiateVnfTask.class);
+    private static final String NF_INST_ID_PARAM_NAME = "NF_INST_ID";
+    public static final String CREATE_VNF_RESPONSE_PARAM_NAME = "createVnfResponse";
+    private final AaiServiceProvider aaiServiceProvider;
+    private final Sol003AdapterServiceProvider sol003AdapterServiceProvider;
+
+    @Autowired
+    public CreateInstantiateVnfTask(final DatabaseServiceProvider databaseServiceProvider,
+            final AaiServiceProvider aaiServiceProvider,
+            final Sol003AdapterServiceProvider sol003AdapterServiceProvider) {
+        super(databaseServiceProvider);
+        this.aaiServiceProvider = aaiServiceProvider;
+        this.sol003AdapterServiceProvider = sol003AdapterServiceProvider;
+    }
+
+    public void checkIfNfInstanceExistsInDb(final DelegateExecution execution) {
+        logger.info("Executing checkIfNfInstanceInDb");
+        final CreateInstantiateRequest request = (CreateInstantiateRequest) execution.getVariable("request");
+        logger.info("request: {}", request);
+
+        setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Checking if NF Instance record exists in database for "
+                + request.getNsInstId() + " and " + request.getVnfName());
+        if (!databaseServiceProvider.isNsInstExists(request.getNsInstId(), request.getVnfName())) {
+            abortOperation(execution,
+                    request.getNsInstId() + " " + request.getVnfName() + " VNF instance already exists");
+        }
+        logger.info("Finished executing checkIfNfInstanceInDb  ...");
+
+    }
+
+    public void createNfInstanceInDb(final DelegateExecution execution) {
+        logger.info("Executing createNfInstanceInDb");
+        final CreateInstantiateRequest request = (CreateInstantiateRequest) execution.getVariable("request");
+        logger.info("request: {}", request);
+
+        setJobStatus(execution, IN_PROGRESS, "Creating NF Instance record in database for " + request.getVnfName());
+
+        final Optional<NfvoNsInst> optional = databaseServiceProvider.getNfvoNsInst(request.getNsInstId());
+
+        if (optional.isEmpty()) {
+            abortOperation(execution, "NfvoNsInst: " + request.getNsInstId() + "not founda");
+        }
+
+        final NfvoNsInst nfvoNsInst = optional.get();
+        final LocalDateTime now = LocalDateTime.now();
+        final NfvoNfInst nfvoNfInst = new NfvoNfInst().status(State.NOT_INSTANTIATED).createTime(now)
+                .lastUpdateTime(now).name(request.getVnfName()).vnfdId(request.getVnfdId())
+                .packageId(request.getVnfPkgId()).nfvoNsInst(nfvoNsInst);
+        databaseServiceProvider.saveNfvoNfInst(nfvoNfInst);
+        execution.setVariable(NF_INST_ID_PARAM_NAME, nfvoNfInst.getNfInstId());
+        logger.info("Finished executing createNfInstanceInDb  ...");
+
+    }
+
+    public void createGenericVnfInAai(final DelegateExecution execution) {
+        logger.info("Executing createGenericVnfInAai");
+        try {
+            final CreateInstantiateRequest request = (CreateInstantiateRequest) execution.getVariable("request");
+
+            setJobStatus(execution, IN_PROGRESS, "Creating GenericVnf record in AAI for " + request.getVnfName());
+
+            final String nfInstId = (String) execution.getVariable(NF_INST_ID_PARAM_NAME);
+            final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+            final NfvoNsInst nfvoNsInst = getNfvoNsInst(execution, nsInstId);
+
+            final GenericVnf genericVnf = new GenericVnf();
+            genericVnf.setVnfId(nfInstId);
+            genericVnf.setVnfName(request.getVnfName());
+            genericVnf.setVnfType(nfvoNsInst.getName() + "/" + request.getVnfName());
+            genericVnf.setServiceId(request.getNsInstId());
+            genericVnf.setNfType(request.getNfType());
+            genericVnf.setOperationalStatus("Created");
+            genericVnf.setIsClosedLoopDisabled(false);
+
+            aaiServiceProvider.createGenericVnfAndConnectServiceInstance(nsInstId, nfInstId, genericVnf);
+
+            final Tenant tenant = request.getTenant();
+            aaiServiceProvider.connectGenericVnfToTenant(nfInstId, tenant.getCloudOwner(), tenant.getRegionName(),
+                    tenant.getTenantId());
+
+        } catch (final Exception exception) {
+            final String message = "Unable to Create GenericVnf in AAI";
+            logger.error(message, exception);
+            abortOperation(execution, message);
+        }
+
+        logger.info("Finished executing createGenericVnfInAai  ...");
+    }
+
+    public void invokeCreateInstantiationRequest(final DelegateExecution execution) {
+        logger.info("Executing invokeCreateInstantiationRequest");
+
+        try {
+            final CreateInstantiateRequest request = (CreateInstantiateRequest) execution.getVariable("request");
+            logger.info("request: {}", request);
+
+            setJobStatus(execution, IN_PROGRESS,
+                    "Invoking SOL003 adapter for creating and instantiating VNF: " + request.getVnfName());
+
+            final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+            final NfvoNsInst nfvoNsInst = getNfvoNsInst(execution, nsInstId);
+            final CreateVnfRequest vnfRequest = new CreateVnfRequest();
+            vnfRequest.setTenant(request.getTenant());
+            vnfRequest.setName(nfvoNsInst.getName() + "." + request.getVnfName());
+            vnfRequest.setPkgId(request.getVnfPkgId());
+            vnfRequest.setAdditionalParams(request.getAdditionalParams());
+            final String vnfId = (String) execution.getVariable(NF_INST_ID_PARAM_NAME);
+            final Optional<CreateVnfResponse> optional =
+                    sol003AdapterServiceProvider.invokeCreateInstantiationRequest(vnfId, vnfRequest);
+
+            if (!optional.isPresent()) {
+                final String errorMessage = "Unexpected error while processing create and instantiation request";
+                logger.error(errorMessage);
+                abortOperation(execution, errorMessage);
+            }
+
+            final CreateVnfResponse vnfResponse = optional.get();
+
+            logger.info("Vnf instantiation response: {}", vnfResponse);
+            execution.setVariable(CREATE_VNF_RESPONSE_PARAM_NAME, vnfResponse);
+            setJobStatus(execution, IN_PROGRESS, "Successfully invoked SOL003 adapater creating and instantiating VNF: "
+                    + request.getVnfName() + " CreaetVnfResponse Job Id: " + vnfResponse.getJobId());
+            logger.debug("Finished executing invokeCreateInstantiationRequest ...");
+        } catch (final Exception exception) {
+            final String message = "Unable to invoke create and instantiation request";
+            logger.error(message, exception);
+            abortOperation(execution, message);
+        }
+
+    }
+
+    public void updateNfInstanceStatusToInstantiated(final DelegateExecution execution) {
+        logger.info("Executing updateNfInstanceStatusToInstantiated");
+
+        updateNfInstanceStatus(execution, State.INSTANTIATED);
+        final CreateInstantiateRequest request = (CreateInstantiateRequest) execution.getVariable("request");
+        setJobStatus(execution, FINISHED, "Successfully created and Instantiated VNF: " + request.getVnfName()
+                + " will set status to " + State.INSTANTIATED);
+
+        logger.info("Finished executing updateNfInstanceStatusToInstantiated  ...");
+
+    }
+
+    public void updateNfInstanceStatusToFailed(final DelegateExecution execution) {
+        logger.info("Executing updateNfInstanceStatusToActive");
+
+        updateNfInstanceStatus(execution, State.FAILED);
+        final CreateInstantiateRequest request = (CreateInstantiateRequest) execution.getVariable("request");
+        setJobStatus(execution, ERROR, "Failed to create and instantiate VNF: " + request.getVnfName()
+                + " will set status to " + State.FAILED);
+
+        logger.info("Finished executing updateNfInstanceStatusToInstantiated  ...");
+
+    }
+
+    private void updateNfInstanceStatus(final DelegateExecution execution, final State vnfStatus) {
+        final String nfInstId = (String) execution.getVariable(NF_INST_ID_PARAM_NAME);
+
+        final Optional<NfvoNfInst> optional = databaseServiceProvider.getNfvoNfInst(nfInstId);
+        if (!optional.isPresent()) {
+            final String message = "Unable to find NfvoNfInst record in database using nfInstId: " + nfInstId;
+            logger.error(message);
+
+            abortOperation(execution, message);
+
+        }
+
+        final NfvoNfInst nfvoNfInst = optional.get();
+        nfvoNfInst.setStatus(vnfStatus);
+        databaseServiceProvider.saveNfvoNfInst(nfvoNfInst);
+    }
+
+    private NfvoNsInst getNfvoNsInst(final DelegateExecution execution, final String nsInstId) {
+        logger.info("Getting NfvoNsInst to update with nsInstId: {}", nsInstId);
+        final Optional<NfvoNsInst> optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsInstId);
+
+        if (!optionalNfvoNsInst.isPresent()) {
+            final String message = "Unable to find NS Instance in datababse using id: " + nsInstId;
+            abortOperation(execution, message);
+        }
+
+        return optionalNfvoNsInst.get();
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java
new file mode 100644 (file)
index 0000000..8d21204
--- /dev/null
@@ -0,0 +1,416 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 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.etsi.nfvo.ns.lcm.bpmn.flows.tasks;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.INSTANTIATE_NS_REQUEST_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_INSTANCE_ID_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.OCC_ID_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.VNF_CREATE_INSTANTIATE_REQUESTS;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.IN_PROGRESS;
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.STARTED;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.Tenant;
+import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
+import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.EtsiCatalogManagerRequestFailureException;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogPackageManagementServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.NetworkServiceDescriptor;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.VirtualNetworkFunction;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State;
+import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest;
+import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ *
+ */
+@Component
+public class InstantiateNsTask extends AbstractNetworkServiceTask {
+
+    private static final String IS_NS_INSTANTIATION_SUCCESSFUL_PARAM_NAME = "isNsInstantiationSuccessful";
+    private static final String VNFD_ID_TO_VNF_PKG_ID_MAPPING_PARAM_NAME = "vnfdIdToVnfPkgIdMapping";
+    private static final Logger logger = LoggerFactory.getLogger(InstantiateNsTask.class);
+    private final EtsiCatalogPackageManagementServiceProvider etsiCatalogPackageManagementServiceProvider;
+
+    @Autowired
+    public InstantiateNsTask(final DatabaseServiceProvider databaseServiceProvider,
+            final EtsiCatalogPackageManagementServiceProvider etsiCatalogPackageManagementServiceProvider) {
+        super(databaseServiceProvider);
+        this.etsiCatalogPackageManagementServiceProvider = etsiCatalogPackageManagementServiceProvider;
+
+    }
+
+    public void setJobStatusToStarted(final DelegateExecution execution) {
+        setJobStatus(execution, STARTED, "Instantiate NS workflow process started");
+    }
+
+    public void setJobStatusToFinished(final DelegateExecution execution) {
+        setJobStatus(execution, FINISHED, "Instantiate NS workflow process finished");
+    }
+
+    public void updateNsInstanceStatusToInstantiating(final DelegateExecution execution) {
+        logger.info("Executing updateNsInstanceStatusToInstantiating");
+        setJobStatus(execution, IN_PROGRESS, "Updating NfvoNsInst Status to " + State.INSTANTIATING);
+        updateNsInstanceStatus(execution, State.INSTANTIATING);
+
+        logger.info("Finished executing updateNsInstanceStatusToInstantiating  ...");
+    }
+
+
+    public void checkIfVnfInstantiationWasSuccessful(final DelegateExecution execution) {
+        logger.info("Executing checkIfVnfInstantiationWasSuccessful");
+
+        @SuppressWarnings("unchecked")
+        final List<CreateInstantiateRequest> requests =
+                (List<CreateInstantiateRequest>) execution.getVariable(VNF_CREATE_INSTANTIATE_REQUESTS);
+
+        final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+        final List<NfvoNfInst> nfInstances = databaseServiceProvider.getNfvoNfInstByNsInstId(nsInstId);
+
+        if (nfInstances == null || nfInstances.isEmpty()) {
+            final String message = "Found empty nf instances";
+            abortOperation(execution, message);
+        }
+
+        if (requests.size() != nfInstances.size()) {
+            final String message = "Missing nf Instance. Request triggered: " + requests.size()
+                    + " Nf Instace reqeust found in database " + nfInstances.size();
+            abortOperation(execution, message);
+        }
+
+        execution.setVariable(IS_NS_INSTANTIATION_SUCCESSFUL_PARAM_NAME, true);
+
+        nfInstances.stream().forEach(instance -> {
+            if (!State.INSTANTIATED.equals(instance.getStatus())) {
+                logger.error("VNF : {} {} instantiation failed", instance.getNfInstId(), instance.getName());
+                execution.setVariable(IS_NS_INSTANTIATION_SUCCESSFUL_PARAM_NAME, false);
+            }
+        });
+
+        logger.info("Finished executing checkIfVnfInstantiationWasSuccessful  ...");
+    }
+
+    public void updateNsInstanceStatusToInstantiated(final DelegateExecution execution) {
+        logger.info("Executing updateNsInstanceStatusToInstantiated");
+        final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+        setJobStatus(execution, FINISHED, "Successfully " + State.INSTANTIATED + " NS: " + nsInstId);
+
+        updateNsInstanceStatus(execution, State.INSTANTIATED);
+        logger.info("Finished executing updateNsInstanceStatusToInstantiated  ...");
+    }
+
+    public void getAndParseNsdFromEtsiCatalog(final DelegateExecution execution) {
+        logger.info("Executing getAndParseNsdFromEtsiCatalog");
+        setJobStatus(execution, IN_PROGRESS, "Retrieving and parsing NSD from ETSI Catalog Manager");
+        final NfvoNsInst nfvoNsInst = getNfvoNsInst(execution);
+        final String nsPackageId = nfvoNsInst.getNsPackageId();
+
+        try {
+            final Optional<NetworkServiceDescriptor> optional =
+                    etsiCatalogPackageManagementServiceProvider.getNetworkServiceDescriptor(nsPackageId);
+
+            if (!optional.isPresent()) {
+                final String message = "Unable to parse NSD " + nsPackageId;
+                logger.error(message);
+                abortOperation(execution, message);
+            }
+
+            final NetworkServiceDescriptor networkServiceDescriptor = optional.get();
+            logger.info("Found {}", networkServiceDescriptor);
+            execution.setVariable(NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME, networkServiceDescriptor);
+
+        } catch (final EtsiCatalogManagerRequestFailureException failureException) {
+            final String message =
+                    "Unexpected exception occured while getting nsd content using nsPackageId: " + nsPackageId;
+            logger.error(message, failureException);
+
+            abortOperation(execution, message);
+        }
+
+        logger.info("Finished executing getAndParseNsdFromEtsiCatalog  ...");
+
+    }
+
+    public void prepareCreateInstantiateRequests(final DelegateExecution execution) {
+        logger.info("Executing prepareCreateInstantiateRequests ...");
+        setJobStatus(execution, IN_PROGRESS, "Preparing VNF CreateInstantiate requests");
+        final NetworkServiceDescriptor networkServiceDescriptor =
+                (NetworkServiceDescriptor) execution.getVariable(NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME);
+        final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+
+        final InstantiateNsRequest instantiateNsRequest =
+                (InstantiateNsRequest) execution.getVariable(INSTANTIATE_NS_REQUEST_PARAM_NAME);
+
+        final List<NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf> additionalParamsForVnfList =
+                instantiateNsRequest.getAdditionalParamsForVnf();
+
+        @SuppressWarnings("unchecked")
+        final Map<String, String> vnfdIdToVnfPkgIdMapping =
+                (Map<String, String>) execution.getVariable(VNFD_ID_TO_VNF_PKG_ID_MAPPING_PARAM_NAME);
+
+        final List<CreateInstantiateRequest> requests = new ArrayList<>();
+
+        for (final VirtualNetworkFunction vnf : networkServiceDescriptor.getVnfs()) {
+            final List<String> vnfmInfoList = vnf.getVnfmInfoList();
+
+            final String vnfdId = vnf.getVnfdId();
+            final String vnfPkgId = vnfdIdToVnfPkgIdMapping.get(vnfdId);
+            if (vnfdId == null || vnfmInfoList.isEmpty() || vnfPkgId == null) {
+                final String message = "Unable to find VnfdId/vnfmInfo/VnfPkgId for vnf: " + vnf;
+                abortOperation(execution, message);
+            }
+
+            final Optional<Tenant> optional = getTenant(vnfPkgId, additionalParamsForVnfList);
+            if (!optional.isPresent()) {
+                final String message = "Unable to find Tenant information for " + vnfdId + " in instantiateNsRequest : "
+                        + instantiateNsRequest;
+                abortOperation(execution, message);
+            }
+
+            final Tenant tenant = optional.get();
+            final CreateInstantiateRequest createInstantiateRequest = new CreateInstantiateRequest().nsInstId(nsInstId)
+                    .vnfdId(vnfdId).vnfName(vnf.getVnfName()).vnfPkgId(vnfPkgId).nfType(vnfmInfoList.get(0))
+                    .tenant(tenant).additionalParams(getAdditionalParams(vnfPkgId, additionalParamsForVnfList));
+
+            logger.info("Adding request to list: {}", createInstantiateRequest);
+            requests.add(createInstantiateRequest);
+
+        }
+        execution.setVariable(VNF_CREATE_INSTANTIATE_REQUESTS, requests);
+
+        logger.info("Finished executing prepareCreateInstantiateRequests  ...");
+    }
+
+    public void getVnfPkgIdForEachVnfdId(final DelegateExecution execution) {
+        logger.info("Executing getVnfPkgIdForEachVnfdId ...");
+
+        setJobStatus(execution, IN_PROGRESS, "Getting VnfPkgId for each VnfdId");
+
+        final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+        final NfvoNsInst nfvoNsInst = getNfvoNsInst(execution, nsInstId);
+
+        final String nsPackageId = nfvoNsInst.getNsPackageId();
+        final NsdInfo nsdInfo = getNsdInfo(execution, nsPackageId);
+
+        final Map<String, String> vnfdIdToVnfPkgIdMapping = new HashMap<>();
+        try {
+            for (final String vnfPkgId : nsdInfo.getVnfPkgIds()) {
+                final Optional<VnfPkgInfo> optional =
+                        etsiCatalogPackageManagementServiceProvider.getVnfPkgInfo(vnfPkgId);
+
+                if (!optional.isPresent()) {
+                    final String message = "Unable to find VNF package using NS vnfPkgId: " + vnfPkgId;
+                    logger.error(message);
+                    abortOperation(execution, message);
+                }
+                final VnfPkgInfo vnfPkgInfo = optional.get();
+                vnfdIdToVnfPkgIdMapping.put(vnfPkgInfo.getVnfdId(), vnfPkgId);
+
+            }
+            logger.info("vnfdIdToVnfPkgIdMapping: {}", vnfdIdToVnfPkgIdMapping);
+            execution.setVariable(VNFD_ID_TO_VNF_PKG_ID_MAPPING_PARAM_NAME, vnfdIdToVnfPkgIdMapping);
+
+        } catch (final EtsiCatalogManagerRequestFailureException failureException) {
+            final String message =
+                    "Unexpected exception occured while getting VNF package using nsPackageId: " + nsPackageId;
+            logger.error(message, failureException);
+
+            abortOperation(execution, message);
+        }
+
+        logger.info("Finished executing getVnfPkgIdForEachVnfdId ...");
+
+    }
+
+    public void logTimeOut(final DelegateExecution execution) {
+        logger.error("Vnf instantiation timedOut ...");
+        final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+        final List<NfvoNfInst> nfInstances = databaseServiceProvider.getNfvoNfInstByNsInstId(nsInstId);
+        if (nfInstances != null) {
+            nfInstances.stream().forEach(instance -> {
+                logger.info("Current status {} of vnf: {}", instance.getStatus(), instance.getName());
+            });
+        }
+    }
+
+    public void setJobStatusToError(final DelegateExecution execution) {
+        updateNsInstanceStatus(execution, State.FAILED);
+        setJobStatusToError(execution, "Instantiate NS workflow process failed");
+    }
+
+
+    public void updateNsLcmOpOccStatusToCompleted(final DelegateExecution execution) {
+        logger.info("Executing updateNsLcmOpOccStatusToCompleted ...");
+        final String occId = (String) execution.getVariable(OCC_ID_PARAM_NAME);
+
+        final Optional<NsLcmOpOcc> optional = databaseServiceProvider.getNsLcmOpOcc(occId);
+
+        if (!optional.isPresent()) {
+            final String message = "Unable to find record for NSLcmOpOcc in database using id: " + occId;
+            logger.error(message);
+            abortOperation(execution, message);
+        }
+
+        final NsLcmOpOcc nsLcmOpOcc = optional.get();
+        final OperationStateEnum operationStateCompleted = OperationStateEnum.COMPLETED;
+        logger.info("Setting operation state to {} for id: {}", operationStateCompleted, occId);
+        nsLcmOpOcc.setOperationState(operationStateCompleted);
+        databaseServiceProvider.addNSLcmOpOcc(nsLcmOpOcc);
+
+        logger.info("Finished executing updateNsLcmOpOccStatusToCompleted ...");
+
+    }
+
+    public void updateNsLcmOpOccStatusToFailed(final DelegateExecution execution) {
+        logger.info("Executing updateNsLcmOpOccStatusToFailed ...");
+        final String occId = (String) execution.getVariable(OCC_ID_PARAM_NAME);
+
+        final Optional<NsLcmOpOcc> optional = databaseServiceProvider.getNsLcmOpOcc(occId);
+
+        if (optional.isPresent()) {
+            final NsLcmOpOcc nsLcmOpOcc = optional.get();
+            final OperationStateEnum operationStateFailed = OperationStateEnum.FAILED;
+            logger.info("Setting operation state to {} for id: {}", operationStateFailed, occId);
+            nsLcmOpOcc.setOperationState(operationStateFailed);
+
+            databaseServiceProvider.addNSLcmOpOcc(nsLcmOpOcc);
+        } else {
+            logger.error("Unable to find record for NSLcmOpOcc in database using id: {}", occId);
+        }
+
+        logger.info("Finished executing updateNsLcmOpOccStatusToFailed ...");
+
+    }
+
+    private NsdInfo getNsdInfo(final DelegateExecution execution, final String nsPackageId) {
+        try {
+            final Optional<NsdInfo> optional =
+                    etsiCatalogPackageManagementServiceProvider.getNSPackageModel(nsPackageId);
+
+            if (optional.isPresent()) {
+                final NsdInfo packageModel = optional.get();
+                logger.info("NS Package exists {}", packageModel);
+                return packageModel;
+            }
+
+        } catch (final EtsiCatalogManagerRequestFailureException failureException) {
+            final String message =
+                    "Unexpected exception occured while getting ns package using nsPackageId: " + nsPackageId;
+            logger.error(message, failureException);
+
+            abortOperation(execution, message);
+        }
+
+        final String message = "Unable to find NS package using NS package id: " + nsPackageId;
+        logger.error(message);
+        abortOperation(execution, message);
+        return null;
+
+    }
+
+    private void updateNsInstanceStatus(final DelegateExecution execution, final State nsStatus) {
+        final NfvoNsInst nfvoNsInst = getNfvoNsInst(execution);
+        logger.info("Updating NfvoNsInst Status to {} and saving to DB", nsStatus);
+        nfvoNsInst.setStatus(nsStatus);
+        databaseServiceProvider.saveNfvoNsInst(nfvoNsInst);
+    }
+
+    private Optional<Tenant> getTenant(final String vnfPkgId,
+            final List<NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf> additionalParamsForVnfList) {
+
+        final Optional<NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf> optional = additionalParamsForVnfList
+                .stream().filter(entry -> vnfPkgId.equals(entry.getVnfProfileId())).findFirst();
+
+        if (optional.isPresent()) {
+            final NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf additionalParamsForVnf = optional.get();
+            @SuppressWarnings("unchecked")
+            final Map<String, Object> additionalParams =
+                    (Map<String, Object>) additionalParamsForVnf.getAdditionalParams();
+            final String vimId = (String) additionalParams.get("vim_id");
+            if (vimId != null) {
+                final String[] splitString = vimId.split("_");
+                if (splitString.length == 3) {
+                    logger.info("Found Tenant in instantiateNsRequest using vnfPkgId: {}", vnfPkgId);
+                    return Optional.of(new Tenant().cloudOwner(splitString[0]).regionName(splitString[1])
+                            .tenantId(splitString[2]));
+                }
+
+            }
+        }
+
+        logger.error("Unable to find Tenant in instantiateNsRequest using vnfPkgId: {}", vnfPkgId);
+        return Optional.empty();
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<String, String> getAdditionalParams(final String vnfPkgId,
+            final List<NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf> additionalParamsForVnfList) {
+
+        final Optional<NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf> optional = additionalParamsForVnfList
+                .stream().filter(entry -> vnfPkgId.equals(entry.getVnfProfileId())).findFirst();
+
+        if (optional.isPresent()) {
+            final NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf additionalParamsForVnf = optional.get();
+            if (additionalParamsForVnf instanceof Map) {
+                logger.info("Found AdditionalParams in instantiateNsRequest using vnfPkgId: {}", vnfPkgId);
+                return (Map<String, String>) additionalParamsForVnf.getAdditionalParams();
+            }
+        }
+
+        return Collections.emptyMap();
+
+    }
+
+    private NfvoNsInst getNfvoNsInst(final DelegateExecution execution) {
+        final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+        return getNfvoNsInst(execution, nsInstId);
+    }
+
+    private NfvoNsInst getNfvoNsInst(final DelegateExecution execution, final String nsInstId) {
+        logger.info("Getting NfvoNsInst to update with nsInstId: {}", nsInstId);
+        final Optional<NfvoNsInst> optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsInstId);
+
+        if (!optionalNfvoNsInst.isPresent()) {
+            final String message = "Unable to find NS Instance in database using id: " + nsInstId;
+            abortOperation(execution, message);
+        }
+
+        return optionalNfvoNsInst.get();
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/CreateInstantiateVnf.bpmn b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/CreateInstantiateVnf.bpmn
new file mode 100644 (file)
index 0000000..025faa4
--- /dev/null
@@ -0,0 +1,159 @@
+<?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" id="Definitions_1uf6nd9" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.0.0">
+  <bpmn:process id="CreateInstantiateVnf" name="CreateInstantiateVnf" isExecutable="true">
+    <bpmn:startEvent id="StartEvent_1">
+      <bpmn:outgoing>Flow_02bjz2v</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:serviceTask id="Activity_19rmtjr" name="Create NF Instance (VNF) record in DB" camunda:expression="${CreateInstantiateVnfTask.createNfInstanceInDb(execution)}">
+      <bpmn:incoming>Flow_123uagz</bpmn:incoming>
+      <bpmn:outgoing>Flow_03p6ifi</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_02bjz2v" sourceRef="StartEvent_1" targetRef="Activity_1cluqgp" />
+    <bpmn:endEvent id="Event_14qdixj">
+      <bpmn:incoming>Flow_0srinh7</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="Flow_03p6ifi" sourceRef="Activity_19rmtjr" targetRef="Activity_0rto3n3" />
+    <bpmn:serviceTask id="Activity_0rto3n3" name="Create Generic VNF and Connect to Service Instance in AAI" camunda:expression="${CreateInstantiateVnfTask.createGenericVnfInAai(execution)}">
+      <bpmn:incoming>Flow_03p6ifi</bpmn:incoming>
+      <bpmn:outgoing>Flow_1c3kc4e</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_1c3kc4e" sourceRef="Activity_0rto3n3" targetRef="ServiceTask_0iry5yw" />
+    <bpmn:serviceTask id="Activity_1cluqgp" name="Check If NF Instance (VNF) exists in DB" camunda:expression="${CreateInstantiateVnfTask.checkIfNfInstanceExistsInDb(execution)}">
+      <bpmn:incoming>Flow_02bjz2v</bpmn:incoming>
+      <bpmn:outgoing>Flow_123uagz</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_123uagz" sourceRef="Activity_1cluqgp" targetRef="Activity_19rmtjr" />
+    <bpmn:serviceTask id="ServiceTask_0iry5yw" name="&#10;Invoke VNFM Adaptor&#10;" camunda:asyncAfter="true" camunda:expression="${CreateInstantiateVnfTask.invokeCreateInstantiationRequest(execution)}">
+      <bpmn:incoming>Flow_1c3kc4e</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0xzptc2</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:callActivity id="CallActivity_1yilxx3" name="Monitor Sol003 adapter  Instantiation Job" calledElement="MonitorSol003AdapterCreateJob">
+      <bpmn:extensionElements>
+        <camunda:in source="createVnfResponse" target="createVnfResponse" />
+        <camunda:in source="jobId" target="jobId" />
+      </bpmn:extensionElements>
+      <bpmn:incoming>SequenceFlow_0xzptc2</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_053tvct</bpmn:outgoing>
+    </bpmn:callActivity>
+    <bpmn:callActivity id="CallActivity_0p84lpt" name="Monitor Sol003 adapter Create Node Status" calledElement="MonitorSol003AdapterCreateNodeStatus">
+      <bpmn:extensionElements>
+        <camunda:in source="NF_INST_ID" target="NF_INST_ID" />
+        <camunda:in source="createVnfResponse" target="createVnfResponse" />
+      </bpmn:extensionElements>
+      <bpmn:incoming>SequenceFlow_053tvct</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0h7yluk</bpmn:outgoing>
+    </bpmn:callActivity>
+    <bpmn:sequenceFlow id="SequenceFlow_0xzptc2" sourceRef="ServiceTask_0iry5yw" targetRef="CallActivity_1yilxx3" />
+    <bpmn:sequenceFlow id="SequenceFlow_053tvct" sourceRef="CallActivity_1yilxx3" targetRef="CallActivity_0p84lpt" />
+    <bpmn:sequenceFlow id="SequenceFlow_0h7yluk" sourceRef="CallActivity_0p84lpt" targetRef="Activity_0g3dip7" />
+    <bpmn:serviceTask id="Activity_0g3dip7" name="Update NF Instance (VNF) Status to INSTANTIATED" camunda:expression="${CreateInstantiateVnfTask.updateNfInstanceStatusToInstantiated(execution)}">
+      <bpmn:incoming>SequenceFlow_0h7yluk</bpmn:incoming>
+      <bpmn:outgoing>Flow_0srinh7</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_0srinh7" sourceRef="Activity_0g3dip7" targetRef="Event_14qdixj" />
+    <bpmn:subProcess id="Activity_0qtgdm9" name="Error Handling" triggeredByEvent="true">
+      <bpmn:startEvent id="Event_08zcwc2" name="error">
+        <bpmn:outgoing>Flow_06q1m6i</bpmn:outgoing>
+        <bpmn:errorEventDefinition id="ErrorEventDefinition_1ppvn77" />
+      </bpmn:startEvent>
+      <bpmn:endEvent id="Event_1wkm29u" name="end">
+        <bpmn:incoming>Flow_0anjylz</bpmn:incoming>
+      </bpmn:endEvent>
+      <bpmn:serviceTask id="Activity_0ltxcii" name="Update NF Instance (VNF) Status to FAILED" camunda:asyncBefore="true" camunda:expression="${CreateInstantiateVnfTask.updateNfInstanceStatusToFailed(execution)}">
+        <bpmn:incoming>Flow_06q1m6i</bpmn:incoming>
+        <bpmn:outgoing>Flow_0anjylz</bpmn:outgoing>
+      </bpmn:serviceTask>
+      <bpmn:sequenceFlow id="Flow_06q1m6i" sourceRef="Event_08zcwc2" targetRef="Activity_0ltxcii" />
+      <bpmn:sequenceFlow id="Flow_0anjylz" sourceRef="Activity_0ltxcii" targetRef="Event_1wkm29u" />
+    </bpmn:subProcess>
+  </bpmn:process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
+    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="CreateInstantiateVnf">
+      <bpmndi:BPMNEdge id="SequenceFlow_0h7yluk_di" bpmnElement="SequenceFlow_0h7yluk">
+        <di:waypoint x="1030" y="117" />
+        <di:waypoint x="1080" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_053tvct_di" bpmnElement="SequenceFlow_053tvct">
+        <di:waypoint x="880" y="117" />
+        <di:waypoint x="930" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0xzptc2_di" bpmnElement="SequenceFlow_0xzptc2">
+        <di:waypoint x="740" y="117" />
+        <di:waypoint x="780" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_123uagz_di" bpmnElement="Flow_123uagz">
+        <di:waypoint x="350" y="117" />
+        <di:waypoint x="380" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1c3kc4e_di" bpmnElement="Flow_1c3kc4e">
+        <di:waypoint x="610" y="117" />
+        <di:waypoint x="640" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_03p6ifi_di" bpmnElement="Flow_03p6ifi">
+        <di:waypoint x="480" y="117" />
+        <di:waypoint x="510" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_02bjz2v_di" bpmnElement="Flow_02bjz2v">
+        <di:waypoint x="215" y="117" />
+        <di:waypoint x="250" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0srinh7_di" bpmnElement="Flow_0srinh7">
+        <di:waypoint x="1180" y="117" />
+        <di:waypoint x="1232" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
+        <dc:Bounds x="179" y="99" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_19rmtjr_di" bpmnElement="Activity_19rmtjr">
+        <dc:Bounds x="380" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0rto3n3_di" bpmnElement="Activity_0rto3n3">
+        <dc:Bounds x="510" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1cluqgp_di" bpmnElement="Activity_1cluqgp">
+        <dc:Bounds x="250" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ServiceTask_0iry5yw_di" bpmnElement="ServiceTask_0iry5yw">
+        <dc:Bounds x="640" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="CallActivity_1yilxx3_di" bpmnElement="CallActivity_1yilxx3">
+        <dc:Bounds x="780" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="CallActivity_0p84lpt_di" bpmnElement="CallActivity_0p84lpt">
+        <dc:Bounds x="930" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_14qdixj_di" bpmnElement="Event_14qdixj">
+        <dc:Bounds x="1232" y="99" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0g3dip7_di" bpmnElement="Activity_0g3dip7">
+        <dc:Bounds x="1080" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0qtgdm9_di" bpmnElement="Activity_0qtgdm9" isExpanded="true">
+        <dc:Bounds x="430" y="270" width="438" height="130" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_06q1m6i_di" bpmnElement="Flow_06q1m6i">
+        <di:waypoint x="488" y="333" />
+        <di:waypoint x="580" y="333" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0anjylz_di" bpmnElement="Flow_0anjylz">
+        <di:waypoint x="680" y="333" />
+        <di:waypoint x="812" y="333" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Event_08zcwc2_di" bpmnElement="Event_08zcwc2">
+        <dc:Bounds x="452" y="315" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="458" y="358" width="24" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_1wkm29u_di" bpmnElement="Event_1wkm29u">
+        <dc:Bounds x="812" y="315" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="822" y="357" width="19" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0ltxcii_di" bpmnElement="Activity_0ltxcii">
+        <dc:Bounds x="580" y="293" width="100" height="80" />
+      </bpmndi:BPMNShape>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</bpmn:definitions>
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/InstantiateNs.bpmn b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/InstantiateNs.bpmn
new file mode 100644 (file)
index 0000000..ba9e641
--- /dev/null
@@ -0,0 +1,331 @@
+<?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_0mdda96" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.0.0">
+  <bpmn:process id="InstantiateNs" name="InstantiateNs" isExecutable="true">
+    <bpmn:startEvent id="StartEvent_1" name="Start Process">
+      <bpmn:outgoing>SequenceFlow_16k0f61</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:sequenceFlow id="SequenceFlow_16k0f61" sourceRef="StartEvent_1" targetRef="Activity_194tqy0" />
+    <bpmn:serviceTask id="Task_0opnwx0" name="Update NS Instance status to INSTANTIATING" camunda:expression="${InstantiateNsTask.updateNsInstanceStatusToInstantiating(execution)}">
+      <bpmn:incoming>Flow_04pxtdd</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0bdznyp</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:endEvent id="EndEvent_0szswbo" name="End Process">
+      <bpmn:incoming>Flow_1pcu8aa</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="SequenceFlow_0bdznyp" sourceRef="Task_0opnwx0" targetRef="Activity_1jrym1e" />
+    <bpmn:serviceTask id="Activity_194tqy0" name="Set Job Status to STARTED" camunda:asyncBefore="true" camunda:expression="${InstantiateNsTask.setJobStatusToStarted(execution)}">
+      <bpmn:incoming>SequenceFlow_16k0f61</bpmn:incoming>
+      <bpmn:outgoing>Flow_04pxtdd</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_04pxtdd" sourceRef="Activity_194tqy0" targetRef="Task_0opnwx0" />
+    <bpmn:subProcess id="Activity_0pjxszh" name="Error Handling" triggeredByEvent="true">
+      <bpmn:startEvent id="Event_1rpzcl3" name="error">
+        <bpmn:outgoing>Flow_07bh7l7</bpmn:outgoing>
+        <bpmn:errorEventDefinition id="ErrorEventDefinition_0m2e0oa" />
+      </bpmn:startEvent>
+      <bpmn:endEvent id="Event_1fcw3ei" name="end">
+        <bpmn:incoming>Flow_1wa1jpl</bpmn:incoming>
+      </bpmn:endEvent>
+      <bpmn:serviceTask id="Activity_0ddja9m" name="Set Job Status to ERROR" camunda:asyncBefore="true" camunda:expression="${InstantiateNsTask.setJobStatusToError(execution)}">
+        <bpmn:incoming>Flow_0n3dai5</bpmn:incoming>
+        <bpmn:outgoing>Flow_1wa1jpl</bpmn:outgoing>
+      </bpmn:serviceTask>
+      <bpmn:sequenceFlow id="Flow_1wa1jpl" sourceRef="Activity_0ddja9m" targetRef="Event_1fcw3ei" />
+      <bpmn:sequenceFlow id="Flow_07bh7l7" sourceRef="Event_1rpzcl3" targetRef="Activity_1miy3hw" />
+      <bpmn:serviceTask id="Activity_1miy3hw" name="Update NSLcmOpOcc operation status to FAILED" camunda:asyncBefore="true" camunda:expression="${InstantiateNsTask.updateNsLcmOpOccStatusToFailed(execution)}">
+        <bpmn:incoming>Flow_07bh7l7</bpmn:incoming>
+        <bpmn:outgoing>Flow_0n3dai5</bpmn:outgoing>
+      </bpmn:serviceTask>
+      <bpmn:sequenceFlow id="Flow_0n3dai5" sourceRef="Activity_1miy3hw" targetRef="Activity_0ddja9m" />
+    </bpmn:subProcess>
+    <bpmn:subProcess id="Activity_0mtscwq" name="Java Exception Handling" triggeredByEvent="true">
+      <bpmn:startEvent id="Event_0lqr6al" name="error">
+        <bpmn:outgoing>Flow_05lo00r</bpmn:outgoing>
+        <bpmn:errorEventDefinition id="ErrorEventDefinition_02lwl19" errorRef="Error_0jsct8p" camunda:errorCodeVariable="BPMN_javaExpCode" camunda:errorMessageVariable="BPMN_javaExpMsg" />
+      </bpmn:startEvent>
+      <bpmn:endEvent id="Event_05ty7c4">
+        <bpmn:incoming>Flow_16aryg5</bpmn:incoming>
+      </bpmn:endEvent>
+      <bpmn:serviceTask id="Activity_1ezu7d4" name="Set Job Status to ERROR" camunda:asyncBefore="true" camunda:expression="${InstantiateNsTask.setJobStatusToError(execution)}">
+        <bpmn:incoming>Flow_09zcw2a</bpmn:incoming>
+        <bpmn:outgoing>Flow_16aryg5</bpmn:outgoing>
+      </bpmn:serviceTask>
+      <bpmn:sequenceFlow id="Flow_16aryg5" sourceRef="Activity_1ezu7d4" targetRef="Event_05ty7c4" />
+      <bpmn:sequenceFlow id="Flow_05lo00r" sourceRef="Event_0lqr6al" targetRef="Activity_17leldb" />
+      <bpmn:serviceTask id="Activity_17leldb" name="Update NSLcmOpOcc operation status to FAILED" camunda:asyncBefore="true" camunda:expression="${InstantiateNsTask.updateNsLcmOpOccStatusToFailed(execution)}">
+        <bpmn:incoming>Flow_05lo00r</bpmn:incoming>
+        <bpmn:outgoing>Flow_09zcw2a</bpmn:outgoing>
+      </bpmn:serviceTask>
+      <bpmn:sequenceFlow id="Flow_09zcw2a" sourceRef="Activity_17leldb" targetRef="Activity_1ezu7d4" />
+    </bpmn:subProcess>
+    <bpmn:serviceTask id="Activity_1w09i1k" name="Set Job Status to FINISHED" camunda:expression="${InstantiateNsTask.setJobStatusToFinished(execution)}">
+      <bpmn:incoming>Flow_1i36dw4</bpmn:incoming>
+      <bpmn:outgoing>Flow_1pcu8aa</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_1pcu8aa" sourceRef="Activity_1w09i1k" targetRef="EndEvent_0szswbo" />
+    <bpmn:serviceTask id="Activity_1jrym1e" name="Get and parse NSD from ETSI Catalog" camunda:expression="${InstantiateNsTask.getAndParseNsdFromEtsiCatalog(execution)}">
+      <bpmn:incoming>SequenceFlow_0bdznyp</bpmn:incoming>
+      <bpmn:outgoing>Flow_10zjw0w</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_10zjw0w" sourceRef="Activity_1jrym1e" targetRef="Activity_1kikjaf" />
+    <bpmn:callActivity id="Activity_1b2s2wr" name="Create and Instantiate each Vnf" calledElement="CreateInstantiateVnf">
+      <bpmn:extensionElements>
+        <camunda:in source="request" target="request" />
+        <camunda:in source="jobId" target="jobId" />
+        <camunda:in source="NsInstanceId" target="NsInstanceId" />
+      </bpmn:extensionElements>
+      <bpmn:incoming>Flow_1irbp9b</bpmn:incoming>
+      <bpmn:outgoing>Flow_0mi4nqa</bpmn:outgoing>
+      <bpmn:multiInstanceLoopCharacteristics camunda:asyncAfter="true" camunda:collection="${vnfCreateInstantiateRequests}" camunda:elementVariable="request" />
+    </bpmn:callActivity>
+    <bpmn:boundaryEvent id="Event_0rbb817" name="Overall Wait" attachedToRef="Activity_1b2s2wr">
+      <bpmn:outgoing>Flow_17zn7we</bpmn:outgoing>
+      <bpmn:timerEventDefinition id="TimerEventDefinition_13ud1f4">
+        <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT3H</bpmn:timeDuration>
+      </bpmn:timerEventDefinition>
+    </bpmn:boundaryEvent>
+    <bpmn:sequenceFlow id="Flow_17zn7we" sourceRef="Event_0rbb817" targetRef="Activity_16z66xm" />
+    <bpmn:serviceTask id="Activity_0eou3y4" name="Prepare Create Instantiate requests" camunda:expression="${InstantiateNsTask.prepareCreateInstantiateRequests(execution)}">
+      <bpmn:incoming>Flow_01ju1mj</bpmn:incoming>
+      <bpmn:outgoing>Flow_1irbp9b</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_1irbp9b" sourceRef="Activity_0eou3y4" targetRef="Activity_1b2s2wr" />
+    <bpmn:serviceTask id="Activity_1kikjaf" name="Get Vnf Pkg ID for each VNFD ID" camunda:expression="${InstantiateNsTask.getVnfPkgIdForEachVnfdId(execution)}">
+      <bpmn:incoming>Flow_10zjw0w</bpmn:incoming>
+      <bpmn:outgoing>Flow_01ju1mj</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_01ju1mj" sourceRef="Activity_1kikjaf" targetRef="Activity_0eou3y4" />
+    <bpmn:serviceTask id="Activity_16cvdbw" name="Update NS Instance status to INSTANTIATED" camunda:expression="${InstantiateNsTask.updateNsInstanceStatusToInstantiated(execution)}">
+      <bpmn:incoming>Flow_1nieng0</bpmn:incoming>
+      <bpmn:outgoing>Flow_0xptc0r</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_0xptc0r" sourceRef="Activity_16cvdbw" targetRef="Activity_0gkpdft" />
+    <bpmn:endEvent id="Event_1e4bwip">
+      <bpmn:incoming>Flow_10oprxr</bpmn:incoming>
+      <bpmn:incoming>Flow_1p21p1m</bpmn:incoming>
+      <bpmn:errorEventDefinition id="ErrorEventDefinition_0vg6v5r" errorRef="Error_0jsct8p" />
+    </bpmn:endEvent>
+    <bpmn:exclusiveGateway id="Gateway_0nxf0rv" name="is Successful?">
+      <bpmn:incoming>Flow_15m4nm1</bpmn:incoming>
+      <bpmn:outgoing>Flow_1nieng0</bpmn:outgoing>
+      <bpmn:outgoing>Flow_10oprxr</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:sequenceFlow id="Flow_1nieng0" name="Yes" sourceRef="Gateway_0nxf0rv" targetRef="Activity_16cvdbw">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{isNsInstantiationSuccessful}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:serviceTask id="Activity_14iwa8x" name="Check if VNF Instantiation was Successful" camunda:expression="${InstantiateNsTask.checkIfVnfInstantiationWasSuccessful(execution)}">
+      <bpmn:incoming>Flow_0mi4nqa</bpmn:incoming>
+      <bpmn:outgoing>Flow_15m4nm1</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_0mi4nqa" sourceRef="Activity_1b2s2wr" targetRef="Activity_14iwa8x" />
+    <bpmn:sequenceFlow id="Flow_15m4nm1" sourceRef="Activity_14iwa8x" targetRef="Gateway_0nxf0rv" />
+    <bpmn:serviceTask id="Activity_16z66xm" name="Log TimeOut" camunda:expression="${InstantiateNsTask.logTimeOut(execution)}">
+      <bpmn:incoming>Flow_17zn7we</bpmn:incoming>
+      <bpmn:outgoing>Flow_1p21p1m</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_10oprxr" name="No" sourceRef="Gateway_0nxf0rv" targetRef="Event_1e4bwip">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{not isNsInstantiationSuccessful}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:sequenceFlow id="Flow_1p21p1m" sourceRef="Activity_16z66xm" targetRef="Event_1e4bwip" />
+    <bpmn:serviceTask id="Activity_0gkpdft" name="Update NSLcmOpOcc operation status to COMPLETED" camunda:expression="${InstantiateNsTask.updateNsLcmOpOccStatusToCompleted(execution)}">
+      <bpmn:incoming>Flow_0xptc0r</bpmn:incoming>
+      <bpmn:outgoing>Flow_1i36dw4</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_1i36dw4" sourceRef="Activity_0gkpdft" targetRef="Activity_1w09i1k" />
+  </bpmn:process>
+  <bpmn:error id="Error_0jsct8p" name="InstantiateNsProcessingException" errorCode="INSTANTIATE_NS_PROCESSING_EXCEPTION" />
+  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
+    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="InstantiateNs">
+      <bpmndi:BPMNEdge id="Flow_1p21p1m_di" bpmnElement="Flow_1p21p1m">
+        <di:waypoint x="1250" y="270" />
+        <di:waypoint x="1332" y="270" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_10oprxr_di" bpmnElement="Flow_10oprxr">
+        <di:waypoint x="1350" y="146" />
+        <di:waypoint x="1350" y="252" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1358" y="196" width="14" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_15m4nm1_di" bpmnElement="Flow_15m4nm1">
+        <di:waypoint x="1250" y="121" />
+        <di:waypoint x="1325" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0mi4nqa_di" bpmnElement="Flow_0mi4nqa">
+        <di:waypoint x="1090" y="121" />
+        <di:waypoint x="1150" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1nieng0_di" bpmnElement="Flow_1nieng0">
+        <di:waypoint x="1375" y="121" />
+        <di:waypoint x="1430" y="121" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1393" y="103" width="19" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0xptc0r_di" bpmnElement="Flow_0xptc0r">
+        <di:waypoint x="1530" y="121" />
+        <di:waypoint x="1580" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_01ju1mj_di" bpmnElement="Flow_01ju1mj">
+        <di:waypoint x="800" y="121" />
+        <di:waypoint x="850" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1irbp9b_di" bpmnElement="Flow_1irbp9b">
+        <di:waypoint x="950" y="121" />
+        <di:waypoint x="990" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_17zn7we_di" bpmnElement="Flow_17zn7we">
+        <di:waypoint x="1070" y="179" />
+        <di:waypoint x="1070" y="270" />
+        <di:waypoint x="1150" y="270" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_10zjw0w_di" bpmnElement="Flow_10zjw0w">
+        <di:waypoint x="649" y="121" />
+        <di:waypoint x="700" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1pcu8aa_di" bpmnElement="Flow_1pcu8aa">
+        <di:waypoint x="1820" y="121" />
+        <di:waypoint x="1862" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_04pxtdd_di" bpmnElement="Flow_04pxtdd">
+        <di:waypoint x="360" y="121" />
+        <di:waypoint x="400" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_0bdznyp_di" bpmnElement="SequenceFlow_0bdznyp">
+        <di:waypoint x="500" y="121" />
+        <di:waypoint x="549" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_16k0f61_di" bpmnElement="SequenceFlow_16k0f61">
+        <di:waypoint x="208" y="121" />
+        <di:waypoint x="260" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1i36dw4_di" bpmnElement="Flow_1i36dw4">
+        <di:waypoint x="1680" y="121" />
+        <di:waypoint x="1720" y="121" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
+        <dc:Bounds x="172" y="103" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="157" y="146" width="67" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ServiceTask_1y7xfqt_di" bpmnElement="Task_0opnwx0">
+        <dc:Bounds x="400" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_194tqy0_di" bpmnElement="Activity_194tqy0">
+        <dc:Bounds x="260" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="EndEvent_0szswbo_di" bpmnElement="EndEvent_0szswbo">
+        <dc:Bounds x="1862" y="103" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1848" y="79" width="63" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1w09i1k_di" bpmnElement="Activity_1w09i1k">
+        <dc:Bounds x="1720" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0gkpdft_di" bpmnElement="Activity_0gkpdft">
+        <dc:Bounds x="1580" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0pjxszh_di" bpmnElement="Activity_0pjxszh" isExpanded="true">
+        <dc:Bounds x="380" y="270" width="510" height="130" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_07bh7l7_di" bpmnElement="Flow_07bh7l7">
+        <di:waypoint x="438" y="333" />
+        <di:waypoint x="500" y="333" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1wa1jpl_di" bpmnElement="Flow_1wa1jpl">
+        <di:waypoint x="760" y="333" />
+        <di:waypoint x="822" y="333" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0n3dai5_di" bpmnElement="Flow_0n3dai5">
+        <di:waypoint x="600" y="333" />
+        <di:waypoint x="660" y="333" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Event_1rpzcl3_di" bpmnElement="Event_1rpzcl3">
+        <dc:Bounds x="402" y="315" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="408" y="358" width="24" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1miy3hw_di" bpmnElement="Activity_1miy3hw">
+        <dc:Bounds x="500" y="293" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0ddja9m_di" bpmnElement="Activity_0ddja9m">
+        <dc:Bounds x="660" y="293" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_1fcw3ei_di" bpmnElement="Event_1fcw3ei">
+        <dc:Bounds x="822" y="315" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="832" y="357" width="19" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0mtscwq_di" bpmnElement="Activity_0mtscwq" isExpanded="true">
+        <dc:Bounds x="380" y="430" width="510" height="130" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_05lo00r_di" bpmnElement="Flow_05lo00r">
+        <di:waypoint x="438" y="493" />
+        <di:waypoint x="500" y="493" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_16aryg5_di" bpmnElement="Flow_16aryg5">
+        <di:waypoint x="760" y="493" />
+        <di:waypoint x="822" y="493" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_09zcw2a_di" bpmnElement="Flow_09zcw2a">
+        <di:waypoint x="600" y="493" />
+        <di:waypoint x="660" y="493" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Event_0lqr6al_di" bpmnElement="Event_0lqr6al">
+        <dc:Bounds x="402" y="475" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="409" y="518" width="24" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_17leldb_di" bpmnElement="Activity_17leldb">
+        <dc:Bounds x="500" y="453" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1ezu7d4_di" bpmnElement="Activity_1ezu7d4">
+        <dc:Bounds x="660" y="453" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_05ty7c4_di" bpmnElement="Event_05ty7c4">
+        <dc:Bounds x="822" y="475" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1jrym1e_di" bpmnElement="Activity_1jrym1e">
+        <dc:Bounds x="549" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1xjmizv_di" bpmnElement="Activity_1b2s2wr">
+        <dc:Bounds x="990" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0eou3y4_di" bpmnElement="Activity_0eou3y4">
+        <dc:Bounds x="850" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1kikjaf_di" bpmnElement="Activity_1kikjaf">
+        <dc:Bounds x="700" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_16cvdbw_di" bpmnElement="Activity_16cvdbw">
+        <dc:Bounds x="1430" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_16umj30_di" bpmnElement="Event_1e4bwip">
+        <dc:Bounds x="1332" y="252" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Gateway_0nxf0rv_di" bpmnElement="Gateway_0nxf0rv" isMarkerVisible="true">
+        <dc:Bounds x="1325" y="96" width="50" height="50" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1320" y="66" width="71" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_14iwa8x_di" bpmnElement="Activity_14iwa8x">
+        <dc:Bounds x="1150" y="81" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_16z66xm_di" bpmnElement="Activity_16z66xm">
+        <dc:Bounds x="1150" y="230" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_0rbb817_di" bpmnElement="Event_0rbb817">
+        <dc:Bounds x="1052" y="143" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1000" y="183" width="60" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</bpmn:definitions>
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/InstantiateNsTaskTest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/InstantiateNsTaskTest.java
new file mode 100644 (file)
index 0000000..bfccddc
--- /dev/null
@@ -0,0 +1,319 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 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.etsi.nfvo.ns.workflow.engine.tasks;
+
+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.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterConfiguration.SOL003_ADAPTER_REST_TEMPLATE_BEAN;
+import static org.springframework.test.web.client.ExpectedCount.times;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import org.camunda.bpm.engine.history.HistoricProcessInstance;
+import org.camunda.bpm.engine.history.HistoricVariableInstance;
+import org.hamcrest.text.MatchesPattern;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfResponse;
+import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStatusRetrievalStatusEnum;
+import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
+import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.BaseTest;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.NetworkServiceDescriptor;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service.JobExecutorService;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State;
+import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest;
+import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.GsonHttpMessageConverter;
+import org.springframework.test.web.client.MockRestServiceServer;
+import org.springframework.web.client.RestTemplate;
+import com.google.gson.Gson;
+
+/**
+ * @author Andrew Lamb (andrew.a.lamb@est.tech)
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class InstantiateNsTaskTest extends BaseTest {
+
+    private static final String TENANT_ID = "6ca8680feba04dad9254f423c6e28e1c";
+    private static final String CLOUD_REGION = "regionOne";
+    private static final String CLOUD_OWNER = "CloudOwner";
+    private 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}";
+    private static final String VCPE_VBRGEMU_VNFD_ID = "b1bb0ce7-2222-4fa7-95ed-4840d70a1102";
+    private static final String VCPE_VBNG = "b1bb0ce7-2222-4fa7-95ed-4840d70a1101";
+    private static final String VCPE_INFRA_VNFD_ID = "b1bb0ce7-2222-4fa7-95ed-4840d70a1100";
+    private static final String VGMUX_VNFD_ID = "0408f076-e6c0-4c82-9940-272fddbb82de";
+    private static final String VGW_VNFD_ID = "3fca3543-07f5-492f-812c-ed462e4f94f4";
+    private static final String[] VCPE_VNFDS =
+            new String[] {VGW_VNFD_ID, VGMUX_VNFD_ID, VCPE_INFRA_VNFD_ID, VCPE_VBNG, VCPE_VBRGEMU_VNFD_ID};
+    private static final String SAMPLE_NSD_FILE = "src/test/resources/ns.csar";
+    private static final String NS_NAME = "InstantiateNetworkService";
+
+    @Autowired
+    private DatabaseServiceProvider databaseServiceProvider;
+
+    @Autowired
+    @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
+    private RestTemplate etsiCatalogRestTemplate;
+
+    @Autowired
+    @Qualifier(SOL003_ADAPTER_REST_TEMPLATE_BEAN)
+    private RestTemplate sol003AdapterRestTemplate;
+
+    private MockRestServiceServer mockEtsiCatalogRestServiceServer;
+
+    private MockRestServiceServer mockSol003AdapterRestServiceServer;
+
+    @Autowired
+    private JobExecutorService objUnderTest;
+
+    @Autowired
+    private GsonProvider gsonProvider;
+
+    private Gson gson;
+
+    private static final Map<String, String> VNFD_ID_TO_VNFPKG_ID_MAPPING = new HashMap<>();
+    static {
+        for (final String vnfd : VCPE_VNFDS) {
+            VNFD_ID_TO_VNFPKG_ID_MAPPING.put(vnfd, UUID.randomUUID().toString());
+        }
+    }
+
+    @Before
+    public void before() {
+        wireMockServer.resetAll();
+        gson = gsonProvider.getGson();
+
+        mockEtsiCatalogRestServiceServer =
+                MockRestServiceServer.bindTo(etsiCatalogRestTemplate).ignoreExpectOrder(true).build();
+        mockSol003AdapterRestServiceServer =
+                MockRestServiceServer.bindTo(sol003AdapterRestTemplate).ignoreExpectOrder(true).build();
+
+        etsiCatalogRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
+        sol003AdapterRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
+
+    }
+
+    @After
+    public void after() {
+        wireMockServer.resetAll();
+        mockEtsiCatalogRestServiceServer.reset();
+    }
+
+    @Test
+    public void testInstantiateNsWorkflow_JustUpdateStatus_SuccessfullCase() throws InterruptedException, IOException {
+        final String nsdId = UUID.randomUUID().toString();
+        final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
+
+        final NfvoNsInst newNfvoNsInst = new NfvoNsInst().nsInstId(nsdId).name(nsdName)
+                .nsPackageId(UUID.randomUUID().toString()).nsPackageId(nsdId).nsdId(nsdId).nsdInvariantId(nsdId)
+                .status(State.NOT_INSTANTIATED).statusUpdatedTime(LocalDateTime.now());
+
+        databaseServiceProvider.saveNfvoNsInst(newNfvoNsInst);
+
+        mockSol003AdapterEndpoints();
+        mockAAIEndpoints(nsdId);
+        mockEtsiCatalogEndpoints(nsdId);
+
+        final String nsLcmOpOccId =
+                objUnderTest.runInstantiateNsJob(newNfvoNsInst.getNsInstId(), getInstantiateNsRequest());
+
+        final Optional<NfvoJob> optional = getJobByResourceId(newNfvoNsInst.getNsInstId());
+        assertTrue(optional.isPresent());
+        final NfvoJob nfvoJob = optional.get();
+
+        assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId()));
+
+        final HistoricProcessInstance historicProcessInstance =
+                getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
+        assertNotNull(historicProcessInstance);
+
+        assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
+
+        // check if value in database has updated
+        final Optional<NfvoNsInst> optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsdId);
+        final NfvoNsInst nfvoNsInst = optionalNfvoNsInst.get();
+        assertEquals(State.INSTANTIATED, nfvoNsInst.getStatus());
+
+        final HistoricVariableInstance historicVariableInstance =
+                getVariable(nfvoJob.getProcessInstanceId(), NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME);
+        assertNotNull(historicVariableInstance);
+        final NetworkServiceDescriptor nsd = (NetworkServiceDescriptor) historicVariableInstance.getValue();
+        assertNotNull(nsd);
+
+        assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nsd.getVnfs().size());
+
+        final List<NfvoNfInst> nfvoNfInsts = databaseServiceProvider.getNfvoNfInstByNsInstId(nsdId);
+        assertNotNull(nsd);
+        assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nfvoNfInsts.size());
+
+        final Optional<NsLcmOpOcc> optionalNsLcmOpOcc = databaseServiceProvider.getNsLcmOpOcc(nsLcmOpOccId);
+        assertTrue(optionalNsLcmOpOcc.isPresent());
+
+        assertEquals(OperationStateEnum.COMPLETED, optionalNsLcmOpOcc.get().getOperationState());
+
+        final Map<String, NfvoNfInst> nfvoNfInstsMap =
+                nfvoNfInsts.stream().collect(Collectors.toMap(NfvoNfInst::getVnfdId, nfvoNfInst -> nfvoNfInst));
+
+        for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
+            assertTrue(nfvoNfInstsMap.containsKey(entry.getKey()));
+            assertEquals(State.INSTANTIATED, nfvoNfInstsMap.get(entry.getKey()).getStatus());
+
+        }
+
+    }
+
+    private void mockSol003AdapterEndpoints() {
+        mockSol003AdapterRestServiceServer
+                .expect(times(VNFD_ID_TO_VNFPKG_ID_MAPPING.size()),
+                        requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/vnfs/.*")))
+                .andExpect(method(HttpMethod.POST))
+                .andRespond(withSuccess(gson.toJson(new CreateVnfResponse().jobId(UUID.randomUUID().toString())),
+                        MediaType.APPLICATION_JSON));
+
+        mockSol003AdapterRestServiceServer
+                .expect(times(VNFD_ID_TO_VNFPKG_ID_MAPPING.size()),
+                        requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/.*")))
+                .andExpect(method(HttpMethod.GET))
+                .andRespond(withSuccess(gson.toJson(
+                        new org.onap.so.adapters.etsisol003adapter.lcm.v1.model.QueryJobResponse().operationState(
+                                org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum.COMPLETED)
+                                .operationStatusRetrievalStatus(OperationStatusRetrievalStatusEnum.STATUS_FOUND)),
+                        MediaType.APPLICATION_JSON));
+    }
+
+    private void mockEtsiCatalogEndpoints(final String nsdId) throws IOException {
+        mockEtsiCatalogRestServiceServer.expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId))
+                .andExpect(method(HttpMethod.GET))
+                .andRespond(withSuccess(gson.toJson(getNSPackageModel(nsdId)), MediaType.APPLICATION_JSON));
+        mockEtsiCatalogRestServiceServer
+                .expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId + "/nsd_content"))
+                .andExpect(method(HttpMethod.GET)).andRespond(withSuccess(
+                        getFileContent(getAbsolutePath(SAMPLE_NSD_FILE)), MediaType.APPLICATION_OCTET_STREAM));
+
+        for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
+            mockEtsiCatalogRestServiceServer
+                    .expect(requestTo(ETSI_CATALOG_URL + "/vnfpkgm/v1/vnf_packages/" + entry.getValue()))
+                    .andExpect(method(HttpMethod.GET)).andRespond(withSuccess(
+                            gson.toJson(getVnfPkgInfo(entry.getKey(), entry.getValue())), MediaType.APPLICATION_JSON));
+        }
+
+    }
+
+    private VnfPkgInfo getVnfPkgInfo(final String vnfdId, final String vnfPkgId) {
+        return new VnfPkgInfo().id(vnfPkgId).vnfdId(vnfdId);
+    }
+
+    private InstantiateNsRequest getInstantiateNsRequest() {
+        final Map<String, Object> additionalParams = new HashMap<>();
+        additionalParams.put("vim_id", CLOUD_OWNER + "_" + CLOUD_REGION + "_" + TENANT_ID);
+
+        final InstantiateNsRequest instantiateNsRequest = new InstantiateNsRequest().nsFlavourId("default");
+
+        for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
+            instantiateNsRequest
+                    .addAdditionalParamsForVnfItem(new NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf()
+                            .vnfProfileId(entry.getValue()).additionalParams(additionalParams));
+        }
+
+        return instantiateNsRequest;
+    }
+
+    private NsdInfo getNSPackageModel(final String nsdId) {
+        return new NsdInfo().id(nsdId).nsdId(nsdId).nsdInvariantId(NSD_INVARIANT_ID).nsdName("vcpe").nsdDesigner("ONAP")
+                .vnfPkgIds(new ArrayList<>(VNFD_ID_TO_VNFPKG_ID_MAPPING.values()));
+    }
+
+    private byte[] getFileContent(final String path) throws IOException {
+        return Files.readAllBytes(Paths.get(path));
+    }
+
+
+    private String getAbsolutePath(final String path) {
+        return new File(path).getAbsolutePath();
+    }
+
+    private void mockAAIEndpoints(final String nsdId) {
+        final String modelEndpoint = "/aai/v[0-9]+/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\"}")));
+
+        final String resourceType = "service-instance";
+        final String resourceLink = "/aai/v20/business/customers/customer/" + GLOBAL_CUSTOMER_ID
+                + "/service-subscriptions/service-subscription/NetworkService/service-instances/service-instance/"
+                + nsdId;
+
+        final String body = "{\n" + "  \"results\": [{\n" + "    \"resource-type\": \"" + resourceType + "\",\n"
+                + "    \"resource-link\": \"" + resourceLink + "\"\n" + "  }]\n" + "}";
+
+        wireMockServer.stubFor(
+                get(urlMatching("/aai/v[0-9]+/nodes/service-instances/service-instance/" + nsdId + "\\?format=pathed"))
+                        .willReturn(okJson(body)));
+
+        wireMockServer
+                .stubFor(put(urlMatching("/aai/v[0-9]+/cloud-infrastructure/cloud-regions/cloud-region/" + CLOUD_OWNER
+                        + "/" + CLOUD_REGION + "/tenants/tenant/" + TENANT_ID + "/relationship-list/relationship"))
+                                .willReturn(ok()));
+
+    }
+
+}
index 7549b49..cb8f920 100644 (file)
@@ -65,7 +65,7 @@ public class NsLcmOpOcc {
     @Column(name = "IS_AUTO_INNOVATION")
     private boolean isAutoInnovation;
 
-    @Column(name = "OPERATION_PARAMS")
+    @Column(name = "OPERATION_PARAMS", columnDefinition = "LONGTEXT")
     private String operationParams;
 
     @Column(name = "IS_CANCEL_PENDING")
index 254a369..3682425 100644 (file)
@@ -81,6 +81,12 @@ public class DatabaseServiceProvider {
         return nfvoNsInstRepository.existsNfvoNsInstByName(name);
     }
 
+    public boolean isNsInstExists(final String nsInstId, final String nfName) {
+        logger.info("Checking if NfvoNfInst entry exists in database using nsInstId: {} and nfName: {}", nsInstId,
+                nfName);
+        return nfvoNfInstRepository.findByNsInstNsInstIdAndName(nsInstId, nfName).isEmpty();
+    }
+
     public boolean saveNfvoNsInst(final NfvoNsInst nfvoNsInst) {
         logger.info("Saving NfvoNsInst: {} to database", nfvoNsInst);
         return nfvoNsInstRepository.save(nfvoNsInst) != null;
@@ -116,6 +122,11 @@ public class DatabaseServiceProvider {
         return nfvoNfInstRepository.findByNsInstNsInstIdAndName(nsInstId, name);
     }
 
+    public Optional<NfvoNfInst> getNfvoNfInst(final String nfInstId) {
+        logger.info("Querying database for NfvoNfInst using nfInstId: {}", nfInstId);
+        return nfvoNfInstRepository.findByNfInstId(nfInstId);
+    }
+
     public boolean addNSLcmOpOcc(final NsLcmOpOcc nsLcmOpOcc) {
         logger.info("Adding NSLcmOpOcc: {} to database", nsLcmOpOcc);
         return nsLcmOpOccRepository.save(nsLcmOpOcc) != null;
@@ -127,5 +138,4 @@ public class DatabaseServiceProvider {
     }
 
 
-
 }
index f295731..792ffdd 100644 (file)
@@ -25,6 +25,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.onap.so.etsi.nfvo.ns.lcm.EtsiSoNsLcmManagerUrlProvider;
 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service.JobExecutorService;
 import org.onap.so.etsi.nfvo.ns.lcm.model.CreateNsRequest;
+import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest;
 import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -64,4 +65,13 @@ public class NsLifeCycleManager {
                 nsInstanceResponse);
     }
 
+    public URI instantiateNs(final String nsInstanceId, final InstantiateNsRequest instantiateNsRequest) {
+        logger.info("Will execute Instantiate Ns for InstantiateNsRequest: {} and nsInstanceId: {}",
+                instantiateNsRequest, nsInstanceId);
+        final String nsLcmOpOccId = jobExecutorService.runInstantiateNsJob(nsInstanceId, instantiateNsRequest);
+
+        return etsiSoNsLcmManagerUrlProvider.getInstantiatedOccUri(nsLcmOpOccId);
+
+    }
+
 }