Implementing Create NS 87/112187/3
authorwaqas.ikram <waqas.ikram@est.tech>
Thu, 20 Aug 2020 08:59:05 +0000 (09:59 +0100)
committerwaqas.ikram <waqas.ikram@est.tech>
Fri, 4 Sep 2020 16:20:54 +0000 (17:20 +0100)
Change-Id: Ib54e7476820fe716137e6d5e08e4d0deb9f104b9
Issue-ID: SO-3179
Signed-off-by: waqas.ikram <waqas.ikram@est.tech>
59 files changed:
so-etsi-nfvo/pom.xml
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-application/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/app/Application.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-application/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/app/AsyncThreadExecutorConfiguration.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-application/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/app/DefaultToShortClassNameBeanNameGenerator.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-application/src/main/resources/application.yaml
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/CamundaCustomConfiguration.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/CamundaDatabaseConfiguration.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/CamundaVariableNameConstants.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/Constants.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/GsonProvider.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/exceptions/EtsiCatalogManagerRequestFailureException.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/exceptions/NsRequestProcessingException.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/extclients/aai/AaiClientProvider.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/extclients/aai/AaiPropertiesImpl.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/extclients/aai/AaiServiceProvider.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/extclients/aai/AaiServiceProviderImpl.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/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.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/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.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/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.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/extclients/etsicatalog/EtsiCatalogUrlProvider.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/service/JobExecutorService.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/service/WorkflowExecutorService.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/service/WorkflowQueryService.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/AbstractNetworkServiceTask.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/CreateNsTask.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/utils/LocalDateTimeTypeAdapter.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/CreateNs.bpmn [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/META-INF/services/org.onap.so.client.RestProperties [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/lcm/bpmn/flows/BaseTest.java [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/lcm/bpmn/flows/DefaultToShortClassNameBeanNameGenerator.java [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/lcm/bpmn/flows/TestApplication.java [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/CreateNsTaskTest.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/pom.xml
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/JobAction.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/NfvoJobStatus.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/NfvoNsInst.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/config/NfvoDatabaseConfiguration.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/repository/NfvoJobRepository.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/repository/NfvoNsInstRepository.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/service/DatabaseServiceProvider.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/resources/db/migration/V1_1__create_nfvo_tables.sql
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/DatabaseServiceProviderTest.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/TestApplication.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/utils/UtilsTest.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/resources/application.yaml [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/pom.xml
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/Constants.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/EtsiSoNsLcmManagerUrlProvider.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/GsonSerializerConfiguration.java [new file with mode: 0644]
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 [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLcmOperationOccurrencesController.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/rest/NsLifecycleManagementController.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/rest/exceptions/NsLcmControllerExceptionHandler.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/TestApplication.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLcmOperationOccurrencesControllerTest.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementControllerTest.java
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/resources/application.yaml

index 8048f0c..0b87b25 100644 (file)
@@ -26,6 +26,7 @@
     <okhttp-version>2.7.5</okhttp-version>
     <okio-version>1.13.0</okio-version>
     <jaxb-api>2.3.0</jaxb-api>
+    <snakeyaml-version>0.11</snakeyaml-version>
   </properties>
 
   <build>
index 24c09d4..12f3bfc 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Ericsson. All rights reserved.
+ *  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=========================================================
  */
index 2eaa710..4427e1a 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Ericsson. All rights reserved.
+ *  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=========================================================
  */
index 13649ac..2546c9c 100644 (file)
@@ -1,23 +1,22 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Nordix. All rights reserved.
+ *  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.app;
 
 import org.springframework.beans.factory.config.BeanDefinition;
index 457e956..563a15f 100644 (file)
 # 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.
+aai:
+   auth: 2A11B07DB6214A839394AA1EC5844695F5114FC407FF5422625FB00175A3DCB8A1FF745F22867EFA72D5369D599BBD88DA8BED4233CF5586
+   version: v19
+   endpoint: https://aai.onap:8443
+camunda:
+   bpm:
+      admin-user:
+         id: admin
+         password: admin
+      history-level: full
+      job-execution:
+         max-pool-size: 30
+         core-pool-size: 3
 spring:
    security:
       usercredentials:
@@ -22,7 +35,35 @@ spring:
          preferred-json-mapper: gson
    main:
       allow-bean-definition-overriding: true
+   datasource:
+      hikari:
+         camunda:
+            jdbcUrl: jdbc:mariadb://${DB_HOST}:${DB_PORT}/camundabpmn
+            username: ${DB_USERNAME}
+            password: ${DB_PASSWORD}
+            driver-class-name: org.mariadb.jdbc.Driver
+            pool-name: bpmn-pool
+            registerMbeans: true
+         nfvo:
+            jdbcUrl: jdbc:mariadb://${DB_HOST}:${DB_PORT}/camundabpmn
+            username: ${DB_USERNAME}
+            password: ${DB_PASSWORD}
+            driver-class-name: org.mariadb.jdbc.Driver
+            pool-name: nfvo-pool
+            registerMbeans: true
 server:
    port: 9095
    tomcat:
-      max-threads: 50
\ No newline at end of file
+      max-threads: 50
+mso:
+   key: 07a7159d3bf51a0e53be7a8f89699be7
+so:
+   adapters:
+      sol003-adapter:
+         url: https://so-vnfm-adapter.onap:9092/so/vnfm-adapter/v1
+         auth: Basic dm5mbTpwYXNzd29yZDEk
+etsi-catalog-manager:
+   base:
+      endpoint: http://modeling-etsicatalog.onap:8806/api
+etsi-so-ns-lcm-manager:
+   endpoint: http://so-etsi-nfvo-ns-lcm:9095
\ No newline at end of file
index e608465..66c11f2 100644 (file)
@@ -8,11 +8,88 @@
   </parent>
   <artifactId>so-etsi-nfvo-ns-lcm-bpmn-flows</artifactId>
   <name>SO ETSI NFVO NS LCM BPMN Flows</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemPropertyVariables>
+            <so.log.level>DEBUG</so.log.level>
+          </systemPropertyVariables>
+          <rerunFailingTestsCount>2</rerunFailingTestsCount>
+          <parallel>suites</parallel>
+          <useUnlimitedThreads>false</useUnlimitedThreads>
+          <threadCount>1</threadCount>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
   <dependencies>
+    <dependency>
+      <groupId>org.onap.so.etsi.nfvo</groupId>
+      <artifactId>so-etsi-nfvo-ns-lcm-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.onap.so.etsi.nfvo</groupId>
       <artifactId>so-etsi-nfvo-ns-lcm-database-service</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.onap.so.adapters</groupId>
+      <artifactId>etsi-sol003-pkgm-ext-clients</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.onap.so</groupId>
+      <artifactId>aai-client</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.camunda.bpm.springboot</groupId>
+      <artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
+      <version>${camunda.springboot.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.camunda.bpmn</groupId>
+          <artifactId>camunda-engine-rest-core</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.yaml</groupId>
+      <artifactId>snakeyaml</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.shazam</groupId>
+      <artifactId>shazamcrest</artifactId>
+      <version>${snakeyaml-version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>com.google.guava</groupId>
+          <artifactId>guava</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.commons</groupId>
+          <artifactId>commons-lang3</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.vaadin.external.google</groupId>
+          <artifactId>android-json</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>com.h2database</groupId>
+      <artifactId>h2</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
\ No newline at end of file
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/CamundaCustomConfiguration.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/CamundaCustomConfiguration.java
new file mode 100644 (file)
index 0000000..33923f4
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============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;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.NS_WORKFLOW_ENGINE;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.TENANT_ID;
+import static org.slf4j.LoggerFactory.getLogger;
+import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration;
+import org.camunda.bpm.spring.boot.starter.configuration.Ordering;
+import org.camunda.bpm.spring.boot.starter.configuration.impl.AbstractCamundaConfiguration;
+import org.slf4j.Logger;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Component
+@Order(Ordering.DEFAULT_ORDER + 1)
+public class CamundaCustomConfiguration extends AbstractCamundaConfiguration {
+    private static final Logger logger = getLogger(CamundaCustomConfiguration.class);
+
+    @Override
+    public void preInit(final SpringProcessEngineConfiguration processEngineConfiguration) {
+        logger.info("Setting DeploymentTenantId to {} and DeploymentName to {}", TENANT_ID, NS_WORKFLOW_ENGINE);
+        processEngineConfiguration.setDeploymentTenantId(TENANT_ID);
+        processEngineConfiguration.setDeploymentName(NS_WORKFLOW_ENGINE);
+        super.preInit(processEngineConfiguration);
+    }
+
+}
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/CamundaDatabaseConfiguration.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/CamundaDatabaseConfiguration.java
new file mode 100644 (file)
index 0000000..946bd38
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ============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;
+
+
+import static org.slf4j.LoggerFactory.getLogger;
+import javax.sql.DataSource;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+import org.springframework.jmx.export.MBeanExporter;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Configuration
+@EnableTransactionManagement
+@Profile({"!test"})
+public class CamundaDatabaseConfiguration {
+
+    private static final Logger logger = getLogger(CamundaDatabaseConfiguration.class);
+
+    @Autowired(required = false)
+    private MBeanExporter mBeanExporter;
+
+    @Bean
+    @ConfigurationProperties(prefix = "spring.datasource.hikari.camunda")
+    public HikariConfig camundaDbConfig() {
+        logger.debug("Creating HikariConfig bean ... ");
+        return new HikariConfig();
+    }
+
+    @Primary
+    @Bean(name = "dataSource")
+    public DataSource dataSource() {
+        if (mBeanExporter != null) {
+            mBeanExporter.addExcludedBean("dataSource");
+        }
+        logger.debug("Creating HikariDataSource bean ... ");
+        final HikariConfig hikariConfig = this.camundaDbConfig();
+        return new HikariDataSource(hikariConfig);
+    }
+
+}
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/CamundaVariableNameConstants.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/CamundaVariableNameConstants.java
new file mode 100644 (file)
index 0000000..ed6da54
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ============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;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class CamundaVariableNameConstants {
+
+    public static final String JOB_ID_PARAM_NAME = "jobId";
+    public static final String JOB_BUSINESS_KEY_PARAM_NAME = "jobBusinessKey";
+    public static final String CREATE_NS_REQUEST_PARAM_NAME = "createNsRequest";
+    public static final String GLOBAL_CUSTOMER_ID_PARAM_NAME = "globalCustomerId";
+    public static final String SERVICE_TYPE_PARAM_NAME = "serviceType";
+
+
+    public static final String NS_PACKAGE_MODEL_PARAM_NAME = "NSPackageModel";
+    public static final String CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME =
+            "CreateNsWorkflowProcessingException";
+    public static final String CREATE_NS_RESPONSE_PARAM_NAME = "createNsResponse";
+
+    public static final String INSTANTIATE_NS_REQUEST_PARAM_NAME = "instantiateNsRequest";
+    public static final String OCC_ID_PARAM_NAME = "occId";
+    public static final String NS_INSTANCE_ID_PARAM_NAME = "NsInstanceId";
+    public static final String NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME = "NetworkServiceDescriptor";
+    public static final String VNF_CREATE_INSTANTIATE_REQUESTS = "vnfCreateInstantiateRequests";
+
+    private CamundaVariableNameConstants() {}
+
+}
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/Constants.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/Constants.java
new file mode 100644 (file)
index 0000000..46115a7
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============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;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class Constants {
+
+    public static final String TENANT_ID = "ns-workflow-engine-tenant";
+    public static final String NS_WORKFLOW_ENGINE = "NS-WORKFLOW-ENGINE";
+    public static final String CREATE_NS_WORKFLOW_NAME = "CreateNs";
+    public static final String INSTANTIATE_NS_WORKFLOW_NAME = "InstantiateNs";
+    public static final String GET_NS_OCCURRENCE_OPERATION_STATUS_NAME = "GetNsOccurrenceOperationStatus";
+
+    private Constants() {}
+
+}
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/GsonProvider.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/GsonProvider.java
new file mode 100644 (file)
index 0000000..31961d5
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============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;
+
+import java.time.LocalDateTime;
+import org.onap.so.etsi.nfvo.ns.lcm.JSON;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.utils.LocalDateTimeTypeAdapter;
+import org.springframework.stereotype.Component;
+import org.threeten.bp.OffsetDateTime;
+import com.google.gson.Gson;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Component
+public class GsonProvider {
+
+    private final JSON.OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new JSON.OffsetDateTimeTypeAdapter();
+
+    public Gson getGson() {
+        return JSON.createGson().registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter)
+                .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()).create();
+    }
+
+
+}
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/exceptions/EtsiCatalogManagerRequestFailureException.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/exceptions/EtsiCatalogManagerRequestFailureException.java
new file mode 100644 (file)
index 0000000..553d2f1
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * ============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.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class EtsiCatalogManagerRequestFailureException extends RuntimeException {
+
+    private static final long serialVersionUID = 66862444537194516L;
+
+    public EtsiCatalogManagerRequestFailureException(final String message) {
+        super(message);
+    }
+
+    public EtsiCatalogManagerRequestFailureException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
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/exceptions/NsRequestProcessingException.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/exceptions/NsRequestProcessingException.java
new file mode 100644 (file)
index 0000000..0dcadfd
--- /dev/null
@@ -0,0 +1,53 @@
+/*-
+ * ============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.exceptions;
+
+import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * 
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class NsRequestProcessingException extends RuntimeException {
+
+    private static final long serialVersionUID = 66862444537194516L;
+    private InlineResponse400 problemDetails;
+
+    public NsRequestProcessingException(final String message) {
+        super(message);
+    }
+
+    public NsRequestProcessingException(final String message, final InlineResponse400 problemDetails) {
+        super(message);
+        this.problemDetails = problemDetails;
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return this;
+    }
+
+    public InlineResponse400 getProblemDetails() {
+        return problemDetails;
+    }
+}
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/extclients/aai/AaiClientProvider.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/extclients/aai/AaiClientProvider.java
new file mode 100644 (file)
index 0000000..673662a
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * ============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.extclients.aai;
+
+import org.onap.aaiclient.client.aai.AAIResourcesClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AaiClientProvider {
+
+    @Bean
+    public AAIResourcesClient getAaiClient() {
+        return new AAIResourcesClient();
+    }
+}
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/extclients/aai/AaiPropertiesImpl.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/extclients/aai/AaiPropertiesImpl.java
new file mode 100644 (file)
index 0000000..3df3580
--- /dev/null
@@ -0,0 +1,76 @@
+/*-
+ * ============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.extclients.aai;
+
+import org.onap.aaiclient.client.aai.AAIProperties;
+import org.onap.aaiclient.client.aai.AAIVersion;
+import org.onap.so.spring.SpringContextHelper;
+import org.springframework.context.ApplicationContext;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class AaiPropertiesImpl implements AAIProperties {
+
+    private final String endpoint;
+    private final String encryptedBasicAuth;
+    private final String encryptionKey;
+    private final String aaiVersion;
+
+    public AaiPropertiesImpl() {
+
+        final ApplicationContext context = SpringContextHelper.getAppContext();
+        this.endpoint = context.getEnvironment().getProperty("aai.endpoint");
+        this.encryptedBasicAuth = context.getEnvironment().getProperty("aai.auth");
+        this.encryptionKey = context.getEnvironment().getProperty("mso.key");
+        this.aaiVersion = context.getEnvironment().getProperty("aai.version");
+    }
+
+    @Override
+    public URL getEndpoint() throws MalformedURLException {
+        return new URL(endpoint);
+    }
+
+    @Override
+    public String getSystemName() {
+        return "MSO";
+    }
+
+    @Override
+    public AAIVersion getDefaultVersion() {
+        for (final AAIVersion version : AAIVersion.values()) {
+            if (version.toString().equalsIgnoreCase(this.aaiVersion)) {
+                return version;
+            } ;
+
+        }
+        return AAIVersion.LATEST;
+    }
+
+    @Override
+    public String getAuth() {
+        return encryptedBasicAuth;
+    }
+
+    @Override
+    public String getKey() {
+        return encryptionKey;
+    }
+}
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/extclients/aai/AaiServiceProvider.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/extclients/aai/AaiServiceProvider.java
new file mode 100644 (file)
index 0000000..5306239
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============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.extclients.aai;
+
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.ServiceInstance;
+import java.util.Optional;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface AaiServiceProvider {
+
+    void createServiceInstance(final String globalCustomerId, final String serviceType,
+            final ServiceInstance aaiServiceInstance);
+
+    void createGenericVnfAndConnectServiceInstance(final String serviceInstanceId, final String vnfId,
+            final GenericVnf genericVnf);
+
+    void connectGenericVnfToTenant(final String vnfId, final String cloudOwner, final String cloudRegion,
+            final String tenantId);
+
+    Optional<GenericVnf> getGenericVnf(final String vnfId);
+
+}
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/extclients/aai/AaiServiceProviderImpl.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/extclients/aai/AaiServiceProviderImpl.java
new file mode 100644 (file)
index 0000000..049746c
--- /dev/null
@@ -0,0 +1,83 @@
+/*-
+ * ============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.extclients.aai;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.aaiclient.client.aai.AAIObjectType;
+import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
+import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ */
+@Service
+public class AaiServiceProviderImpl implements AaiServiceProvider {
+    private static final Logger logger = LoggerFactory.getLogger(AaiServiceProviderImpl.class);
+    private final AaiClientProvider aaiClientProvider;
+
+    @Autowired
+    public AaiServiceProviderImpl(final AaiClientProvider aaiClientProvider) {
+        this.aaiClientProvider = aaiClientProvider;
+    }
+
+    @Override
+    public void createServiceInstance(final String globalCustomerId, final String serviceType,
+            final ServiceInstance aaiServiceInstance) {
+        logger.info("Creating service instance in AAI: {}", aaiServiceInstance);
+        final AAIResourceUri serviceInstanceURI = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE,
+                globalCustomerId, serviceType, aaiServiceInstance.getServiceInstanceId());
+        aaiClientProvider.getAaiClient().createIfNotExists(serviceInstanceURI, Optional.of(aaiServiceInstance));
+
+    }
+
+    @Override
+    public void createGenericVnfAndConnectServiceInstance(final String serviceInstanceId, final String vnfId,
+            final GenericVnf genericVnf) {
+        logger.info("Creating GenericVnf in AAI: {}", genericVnf);
+        final AAIResourceUri genericVnfURI = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId);
+        final AAIResourceUri serviceInstanceURI =
+                AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, serviceInstanceId);
+        aaiClientProvider.getAaiClient().createIfNotExists(genericVnfURI, Optional.of(genericVnf))
+                .connect(genericVnfURI, serviceInstanceURI);
+
+    }
+
+    @Override
+    public void connectGenericVnfToTenant(final String vnfId, final String cloudOwner, final String cloudRegion,
+            final String tenantId) {
+        logger.info("Connecting GenericVnf {} to {}/{}/{} in AAI", vnfId, cloudOwner, cloudRegion, tenantId);
+        final AAIResourceUri tenantURI =
+                AAIUriFactory.createResourceUri(AAIObjectType.TENANT, cloudOwner, cloudRegion, tenantId);
+        final AAIResourceUri genericVnfURI = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId);
+        aaiClientProvider.getAaiClient().connect(tenantURI, genericVnfURI);
+    }
+
+    @Override
+    public Optional<GenericVnf> getGenericVnf(final String vnfId) {
+        return aaiClientProvider.getAaiClient().get(GenericVnf.class,
+                AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId));
+    }
+}
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/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.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/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java
new file mode 100644 (file)
index 0000000..a373df4
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============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.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;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface EtsiCatalogPackageManagementServiceProvider {
+
+    Optional<NsdInfo> getNSPackageModel(final String nsdId);
+
+    Optional<VnfPkgInfo> getVnfPkgInfo(final String vnfPkgId);
+
+}
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/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.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/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.java
new file mode 100644 (file)
index 0000000..32f7cc1
--- /dev/null
@@ -0,0 +1,86 @@
+/*-
+ * ============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.extclients.etsicatalog;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_SERVICE_PROVIDER_BEAN;
+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.rest.service.HttpRestServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class EtsiCatalogPackageManagementServiceProviderImpl implements EtsiCatalogPackageManagementServiceProvider {
+
+    private static final Logger logger = LoggerFactory.getLogger(EtsiCatalogPackageManagementServiceProviderImpl.class);
+
+    private final HttpRestServiceProvider httpServiceProvider;
+    private final EtsiCatalogUrlProvider etsiCatalogUrlProvider;
+
+    @Autowired
+    public EtsiCatalogPackageManagementServiceProviderImpl(final EtsiCatalogUrlProvider etsiCatalogUrlProvider,
+            @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN) final HttpRestServiceProvider httpServiceProvider) {
+        this.etsiCatalogUrlProvider = etsiCatalogUrlProvider;
+        this.httpServiceProvider = httpServiceProvider;
+    }
+
+    @Override
+    public Optional<NsdInfo> getNSPackageModel(final String nsdId) {
+        try {
+            final ResponseEntity<NsdInfo> response =
+                    httpServiceProvider.getHttpResponse(etsiCatalogUrlProvider.getNsPackageUrl(nsdId), NsdInfo.class);
+            if (response.getStatusCode().is2xxSuccessful()) {
+                return Optional.ofNullable(response.getBody());
+            }
+            return Optional.empty();
+        } catch (final Exception restProcessingException) {
+            logger.error("Caught exception while getting NS package model for: {}", nsdId, restProcessingException);
+            throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.",
+                    restProcessingException);
+        }
+    }
+
+    @Override
+    public Optional<VnfPkgInfo> getVnfPkgInfo(final String vnfPkgId) {
+        try {
+            final ResponseEntity<VnfPkgInfo> response = httpServiceProvider
+                    .getHttpResponse(etsiCatalogUrlProvider.getVnfPackageUrl(vnfPkgId), VnfPkgInfo.class);
+            if (response.getStatusCode().is2xxSuccessful()) {
+                return Optional.ofNullable(response.getBody());
+            }
+            return Optional.empty();
+        } catch (final Exception restProcessingException) {
+            logger.error("Caught exception while getting VNF package model for: {}", vnfPkgId, restProcessingException);
+            throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.",
+                    restProcessingException);
+        }
+    }
+
+}
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/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.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/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java
new file mode 100644 (file)
index 0000000..8c6ea92
--- /dev/null
@@ -0,0 +1,188 @@
+/*-
+ * ============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.extclients.etsicatalog;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.logging.filter.spring.SpringClientPayloadFilter;
+import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
+import org.onap.so.configuration.rest.HttpClientConnectionConfiguration;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider;
+import org.onap.so.logging.jaxrs.filter.SOSpringClientFilter;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.onap.so.rest.service.HttpRestServiceProviderImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.GsonHttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Configures the HttpRestServiceProvider to make REST calls to the ETSI Catalog Manager
+ * 
+ * @author gareth.roper@est.tech
+ */
+
+@Configuration
+public class EtsiCatalogServiceProviderConfiguration {
+    public static final String ETSI_CATALOG_REST_TEMPLATE_BEAN = "etsiCatalogRestTemplate";
+
+    public static final String ETSI_CATALOG_SERVICE_PROVIDER_BEAN = "etsiCatalogServiceProvider";
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(EtsiCatalogServiceProviderConfiguration.class);
+
+    private final HttpClientConnectionConfiguration clientConnectionConfiguration;
+
+    @Value("${etsi-catalog-manager.http.client.ssl.trust-store:#{null}}")
+    private Resource trustStore;
+    @Value("${etsi-catalog-manager.http.client.ssl.trust-store-password:#{null}}")
+    private String trustStorePassword;
+
+    private final GsonProvider gsonProvider;
+
+    @Autowired
+    public EtsiCatalogServiceProviderConfiguration(
+            final HttpClientConnectionConfiguration clientConnectionConfiguration, final GsonProvider gsonProvider) {
+        this.clientConnectionConfiguration = clientConnectionConfiguration;
+        this.gsonProvider = gsonProvider;
+    }
+
+    @Bean
+    @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
+    public RestTemplate etsiCatalogRestTemplate() {
+        final RestTemplate restTemplate = new RestTemplate();
+        restTemplate.getInterceptors().add(new SOSpringClientFilter());
+        restTemplate.getInterceptors().add((new SpringClientPayloadFilter()));
+        return restTemplate;
+    }
+
+    @Bean
+    @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN)
+    public HttpRestServiceProvider etsiCatalogHttpRestServiceProvider(
+            @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN) final RestTemplate restTemplate) {
+        setGsonMessageConverter(restTemplate);
+
+        final HttpClientBuilder httpClientBuilder = getHttpClientBuilder();
+        if (trustStore != null) {
+            try {
+                LOGGER.debug("Setting up HttpComponentsClientHttpRequestFactory with SSL Context");
+                LOGGER.debug("Setting client trust-store: {}", trustStore.getURL());
+                LOGGER.debug("Creating SSLConnectionSocketFactory with AllowAllHostsVerifier ... ");
+                final SSLContext sslContext = new SSLContextBuilder()
+                        .loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray()).build();
+                final SSLConnectionSocketFactory sslConnectionSocketFactory =
+                        new SSLConnectionSocketFactory(sslContext, AllowAllHostsVerifier.INSTANCE);
+                httpClientBuilder.setSSLSocketFactory(sslConnectionSocketFactory);
+                final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
+                        .<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
+                        .register("https", sslConnectionSocketFactory).build();
+
+                httpClientBuilder.setConnectionManager(getConnectionManager(socketFactoryRegistry));
+            } catch (final KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException
+                    | IOException exception) {
+                LOGGER.error("Error reading truststore, TLS connection will fail.", exception);
+            }
+
+        } else {
+            LOGGER.debug("Setting connection manager without SSL ConnectionSocketFactory ...");
+            httpClientBuilder.setConnectionManager(getConnectionManager());
+        }
+
+        final HttpComponentsClientHttpRequestFactory factory =
+                new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
+        restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(factory));
+
+        return new HttpRestServiceProviderImpl(restTemplate, new BasicHttpHeadersProvider().getHttpHeaders());
+    }
+
+    private PoolingHttpClientConnectionManager getConnectionManager(
+            final Registry<ConnectionSocketFactory> socketFactoryRegistry) {
+        return new PoolingHttpClientConnectionManager(socketFactoryRegistry, null, null, null,
+                clientConnectionConfiguration.getTimeToLiveInMins(), TimeUnit.MINUTES);
+    }
+
+    private PoolingHttpClientConnectionManager getConnectionManager() {
+        return new PoolingHttpClientConnectionManager(clientConnectionConfiguration.getTimeToLiveInMins(),
+                TimeUnit.MINUTES);
+    }
+
+    private HttpClientBuilder getHttpClientBuilder() {
+        return HttpClientBuilder.create().setMaxConnPerRoute(clientConnectionConfiguration.getMaxConnectionsPerRoute())
+                .setMaxConnTotal(clientConnectionConfiguration.getMaxConnections())
+                .setDefaultRequestConfig(getRequestConfig());
+    }
+
+    private RequestConfig getRequestConfig() {
+        return RequestConfig.custom().setSocketTimeout(clientConnectionConfiguration.getSocketTimeOutInMiliSeconds())
+                .setConnectTimeout(clientConnectionConfiguration.getConnectionTimeOutInMilliSeconds()).build();
+    }
+
+    private static final class AllowAllHostsVerifier implements HostnameVerifier {
+
+        private static final AllowAllHostsVerifier INSTANCE = new AllowAllHostsVerifier();
+
+        @Override
+        public boolean verify(final String hostname, final SSLSession session) {
+            LOGGER.debug("Skipping hostname verification ...");
+            return true;
+        }
+
+    }
+
+    public void setGsonMessageConverter(final RestTemplate restTemplate) {
+        final Iterator<HttpMessageConverter<?>> iterator = restTemplate.getMessageConverters().iterator();
+        while (iterator.hasNext()) {
+            if (iterator.next() instanceof MappingJackson2HttpMessageConverter) {
+                iterator.remove();
+            }
+        }
+        restTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gsonProvider.getGson()));
+    }
+
+
+
+}
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/extclients/etsicatalog/EtsiCatalogUrlProvider.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/extclients/etsicatalog/EtsiCatalogUrlProvider.java
new file mode 100644 (file)
index 0000000..e3c159c
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============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.extclients.etsicatalog;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class EtsiCatalogUrlProvider {
+
+    @Value("${etsi-catalog-manager.base.endpoint}")
+    private String etsiCatalogManagerEndpoint;
+
+    public EtsiCatalogUrlProvider() {}
+
+    public String getNsPackageUrl(final String nsdId) {
+        return etsiCatalogManagerEndpoint + "/nsd/v1/ns_descriptors/" + nsdId;
+    }
+
+    public String getNsPackageContentUrl(final String nsdId) {
+        return etsiCatalogManagerEndpoint + "/nsd/v1/ns_descriptors/" + nsdId + "/nsd_content";
+    }
+
+    public String getVnfPackageUrl(final String vnfPkgId) {
+        return etsiCatalogManagerEndpoint + "/vnfpkgm/v1/vnf_packages/" + vnfPkgId;
+    }
+
+
+}
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/service/JobExecutorService.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/service/JobExecutorService.java
new file mode 100644 (file)
index 0000000..692aff6
--- /dev/null
@@ -0,0 +1,182 @@
+/*-
+ * ============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.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.JOB_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.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.slf4j.LoggerFactory.getLogger;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+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.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.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.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;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class JobExecutorService {
+
+    private static final Logger logger = getLogger(JobExecutorService.class);
+
+    private static final ImmutableSet<JobStatusEnum> JOB_FINISHED_STATES =
+            ImmutableSet.of(FINISHED, ERROR, FINISHED_WITH_ERROR);
+
+    private static final int SLEEP_TIME_IN_SECONDS = 5;
+
+    @Value("${so-etsi-ns-lcm-workflow-engine.requesttimeout.timeoutInSeconds:300}")
+    private int timeOutInSeconds;
+
+    private final DatabaseServiceProvider databaseServiceProvider;
+    private final WorkflowExecutorService workflowExecutorService;
+    private final WorkflowQueryService workflowQueryService;
+
+    @Autowired
+    public JobExecutorService(final DatabaseServiceProvider databaseServiceProvider,
+            final WorkflowExecutorService workflowExecutorService, final WorkflowQueryService workflowQueryService) {
+        this.databaseServiceProvider = databaseServiceProvider;
+        this.workflowExecutorService = workflowExecutorService;
+        this.workflowQueryService = workflowQueryService;
+    }
+
+    public NsInstancesNsInstance runCreateNsJob(final CreateNsRequest createNsRequest, final String globalCustomerId,
+            final String serviceType) {
+        logger.info("Starting 'Create NS' workflow job for request:\n{}", createNsRequest);
+        final NfvoJob newJob = new NfvoJob().startTime(LocalDateTime.now()).jobType("NS").jobAction(JobAction.CREATE)
+                .resourceId(createNsRequest.getNsdId()).resourceName(createNsRequest.getNsName())
+                .status(JobStatusEnum.STARTING).progress(5);
+        databaseServiceProvider.addJob(newJob);
+
+        logger.info("New job created in database :\n{}", newJob);
+
+        workflowExecutorService.executeWorkflow(newJob.getJobId(), CREATE_NS_WORKFLOW_NAME,
+                getVariables(newJob.getJobId(), createNsRequest, globalCustomerId, serviceType));
+
+        final ImmutablePair<String, JobStatusEnum> immutablePair =
+                waitForJobToFinish(newJob.getJobId(), JOB_FINISHED_STATES);
+
+        if (immutablePair.getRight() == null) {
+            final String message = "Failed to create NS for request: \n" + createNsRequest;
+            logger.error(message);
+            throw new NsRequestProcessingException(message);
+        }
+        final JobStatusEnum finalJobStatus = immutablePair.getRight();
+        final String processInstanceId = immutablePair.getLeft();
+
+        if (!FINISHED.equals(finalJobStatus)) {
+
+            final Optional<InlineResponse400> optional = workflowQueryService.getProblemDetails(processInstanceId);
+            if (optional.isPresent()) {
+                final InlineResponse400 problemDetails = optional.get();
+                final String message =
+                        "Failed to create NS for request: \n" + createNsRequest + " due to \n" + problemDetails;
+                logger.error(message);
+                throw new NsRequestProcessingException(message, problemDetails);
+            }
+
+            final String message = "Received unexpected Job Status: " + finalJobStatus
+                    + " Failed to Create NS for request: \n" + createNsRequest;
+            logger.error(message);
+            throw new NsRequestProcessingException(message);
+        }
+
+        logger.debug("Will query for CreateNsResponse using processInstanceId:{}", processInstanceId);
+        final Optional<NsInstancesNsInstance> optional = workflowQueryService.getCreateNsResponse(processInstanceId);
+        if (optional.isEmpty()) {
+            final String message =
+                    "Unable to find CreateNsReponse in Camunda History for process instance: " + processInstanceId;
+            logger.error(message);
+            throw new NsRequestProcessingException(message);
+        }
+        return optional.get();
+    }
+
+    private ImmutablePair<String, JobStatusEnum> waitForJobToFinish(final String jobId,
+            final ImmutableSet<JobStatusEnum> jobFinishedStates) {
+        try {
+            final long startTimeInMillis = System.currentTimeMillis();
+            final long timeOutTime = startTimeInMillis + TimeUnit.SECONDS.toMillis(timeOutInSeconds);
+
+            logger.info("Will wait till {} for {} job to finish", Instant.ofEpochMilli(timeOutTime).toString(), jobId);
+            JobStatusEnum currentJobStatus = null;
+            while (timeOutTime > System.currentTimeMillis()) {
+
+                final Optional<NfvoJob> optional = databaseServiceProvider.getJob(jobId);
+
+                if (optional.isEmpty()) {
+                    logger.error("Unable to find Job using jobId: {}", jobId);
+                    return ImmutablePair.nullPair();
+                }
+
+                final NfvoJob nfvoJob = optional.get();
+                currentJobStatus = nfvoJob.getStatus();
+                logger.debug("Received job status response: \n ", nfvoJob);
+                if (jobFinishedStates.contains(nfvoJob.getStatus())) {
+                    logger.info("Job finished \n {}", currentJobStatus);
+                    return ImmutablePair.of(nfvoJob.getProcessInstanceId(), currentJobStatus);
+                }
+
+                logger.debug("Haven't received one of finish state {} yet, will try again in {} seconds",
+                        jobFinishedStates, SLEEP_TIME_IN_SECONDS);
+                TimeUnit.SECONDS.sleep(SLEEP_TIME_IN_SECONDS);
+
+            }
+            logger.warn("Timeout current job status: {}", currentJobStatus);
+            return ImmutablePair.nullPair();
+        } catch (final InterruptedException interruptedException) {
+            Thread.currentThread().interrupt();
+            logger.error("Sleep was interrupted", interruptedException);
+            return ImmutablePair.nullPair();
+        }
+    }
+
+    private Map<String, Object> getVariables(final String jobId, final CreateNsRequest createNsRequest,
+            final String globalCustomerId, final String serviceType) {
+        final Map<String, Object> variables = new HashMap<>();
+        variables.put(JOB_ID_PARAM_NAME, jobId);
+        variables.put(CREATE_NS_REQUEST_PARAM_NAME, createNsRequest);
+        variables.put(GLOBAL_CUSTOMER_ID_PARAM_NAME, globalCustomerId);
+        variables.put(SERVICE_TYPE_PARAM_NAME, serviceType);
+        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/service/WorkflowExecutorService.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/service/WorkflowExecutorService.java
new file mode 100644 (file)
index 0000000..fa2b8d5
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ============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.service;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.TENANT_ID;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.util.Map;
+import org.camunda.bpm.engine.RuntimeService;
+import org.camunda.bpm.engine.runtime.ProcessInstance;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class WorkflowExecutorService {
+
+    private static final Logger logger = getLogger(WorkflowExecutorService.class);
+
+    private final RuntimeService runtimeService;
+
+    @Autowired
+    public WorkflowExecutorService(final RuntimeService runtimeService) {
+        this.runtimeService = runtimeService;
+    }
+
+    @Async
+    public void executeWorkflow(final String jobId, final String processDefinitionKey,
+            final Map<String, Object> variables) {
+        logger.info("Executing {} workflow with business key: {}", processDefinitionKey, jobId);
+        final ProcessInstance processInstance = runtimeService.createProcessInstanceByKey(processDefinitionKey)
+                .businessKey(jobId).setVariables(variables).processDefinitionTenantId(TENANT_ID).execute();
+
+        logger.info("Workflow running with processInstanceId: {} and business key: {}",
+                processInstance.getProcessInstanceId(), processInstance.getBusinessKey());
+    }
+
+}
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/service/WorkflowQueryService.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/service/WorkflowQueryService.java
new file mode 100644 (file)
index 0000000..297e9c3
--- /dev/null
@@ -0,0 +1,108 @@
+/*-
+ * ============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.service;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_RESPONSE_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.TENANT_ID;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.util.Optional;
+import org.camunda.bpm.engine.HistoryService;
+import org.camunda.bpm.engine.ProcessEngineException;
+import org.camunda.bpm.engine.history.HistoricVariableInstance;
+import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400;
+import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.google.common.base.Strings;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class WorkflowQueryService {
+
+    private static final Logger logger = getLogger(WorkflowQueryService.class);
+
+    private final HistoryService camundaHistoryService;
+
+    @Autowired
+    public WorkflowQueryService(final HistoryService camundaHistoryService) {
+        this.camundaHistoryService = camundaHistoryService;
+    }
+
+    public Optional<NsInstancesNsInstance> getCreateNsResponse(final String processInstanceId) {
+        try {
+
+            if (Strings.isNullOrEmpty(processInstanceId)) {
+                logger.error("Invalid processInstanceId: {}", processInstanceId);
+                return Optional.empty();
+            }
+
+            final HistoricVariableInstance historicVariableInstance =
+                    getVariable(processInstanceId, CREATE_NS_RESPONSE_PARAM_NAME);
+
+            if (historicVariableInstance != null) {
+                logger.info("Found HistoricVariableInstance : {}", historicVariableInstance);
+                final Object variableValue = historicVariableInstance.getValue();
+                if (variableValue instanceof NsInstancesNsInstance) {
+                    return Optional.ofNullable((NsInstancesNsInstance) variableValue);
+                }
+                logger.error("Unknown CreateNsResponse object type {} received value: {}",
+                        historicVariableInstance.getValue() != null ? variableValue.getClass() : null, variableValue);
+            }
+        } catch (final ProcessEngineException processEngineException) {
+            logger.error("Unable to find {} variable using processInstanceId: {}", CREATE_NS_RESPONSE_PARAM_NAME,
+                    processInstanceId, processEngineException);
+        }
+        logger.error("Unable to find {} variable using processInstanceId: {}", CREATE_NS_RESPONSE_PARAM_NAME,
+                processInstanceId);
+        return Optional.empty();
+
+    }
+
+    public Optional<InlineResponse400> getProblemDetails(final String processInstanceId) {
+        try {
+            final HistoricVariableInstance historicVariableInstance =
+                    getVariable(processInstanceId, CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME);
+
+            logger.info("Found HistoricVariableInstance : {}", historicVariableInstance);
+            final Object variableValue = historicVariableInstance.getValue();
+            if (variableValue instanceof InlineResponse400) {
+                return Optional.ofNullable((InlineResponse400) variableValue);
+            }
+            logger.error("Unknown ProblemDetails object type {} received value: {}",
+                    historicVariableInstance.getValue() != null ? variableValue.getClass() : null, variableValue);
+        } catch (final ProcessEngineException processEngineException) {
+            logger.error("Unable to find {} variable using processInstanceId: {}",
+                    CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, processInstanceId, processEngineException);
+        }
+        return Optional.empty();
+    }
+
+
+    private HistoricVariableInstance getVariable(final String processInstanceId, final String name) {
+        return camundaHistoryService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId)
+                .variableName(name).tenantIdIn(TENANT_ID).singleResult();
+    }
+
+}
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/AbstractNetworkServiceTask.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/AbstractNetworkServiceTask.java
new file mode 100644 (file)
index 0000000..99116da
--- /dev/null
@@ -0,0 +1,117 @@
+/*-
+ * ============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.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.JOB_ID_PARAM_NAME;
+import java.time.LocalDateTime;
+import java.util.Optional;
+import org.camunda.bpm.engine.delegate.BpmnError;
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.onap.so.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.NfvoJobStatus;
+import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public abstract class AbstractNetworkServiceTask {
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+    protected final DatabaseServiceProvider databaseServiceProvider;
+
+    public AbstractNetworkServiceTask(final DatabaseServiceProvider jobServiceProvider) {
+        this.databaseServiceProvider = jobServiceProvider;
+    }
+
+    public void setJobStatus(final DelegateExecution execution, final JobStatusEnum jobStatus,
+            final String description) {
+        logger.info("Setting Job Status to {}", jobStatus);
+        final NfvoJob nfvoJob = getNfvoJob(execution);
+        nfvoJob.status(jobStatus);
+        if (JobStatusEnum.STARTED.equals(jobStatus)) {
+            nfvoJob.processInstanceId(execution.getProcessInstanceId());
+        }
+
+        if (JobStatusEnum.FINISHED.equals(jobStatus)) {
+            nfvoJob.endTime(LocalDateTime.now());
+        }
+
+        nfvoJob.nfvoJobStatus(
+                new NfvoJobStatus().status(jobStatus).description(description).updatedTime(LocalDateTime.now()));
+        databaseServiceProvider.addJob(nfvoJob);
+
+    }
+
+    public void setJobStatusToError(final DelegateExecution execution, final String description) {
+        logger.info("Setting Job Status to {}", JobStatusEnum.ERROR);
+
+        final String jobId = (String) execution.getVariable(JOB_ID_PARAM_NAME);
+        final Optional<NfvoJob> optional = databaseServiceProvider.getJob(jobId);
+        if (optional.isPresent()) {
+            final InlineResponse400 problemDetails =
+                    (InlineResponse400) execution.getVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME);
+
+            final NfvoJob nfvoJob = optional.get();
+            nfvoJob.status(JobStatusEnum.ERROR).endTime(LocalDateTime.now());
+
+            if (problemDetails != null) {
+                logger.error("Found failed reason: {}", problemDetails);
+                nfvoJob.nfvoJobStatus(new NfvoJobStatus().status(JobStatusEnum.ERROR)
+                        .description(problemDetails.getDetail()).updatedTime(LocalDateTime.now()));
+            }
+            nfvoJob.nfvoJobStatus(new NfvoJobStatus().status(JobStatusEnum.ERROR).description(description)
+                    .updatedTime(LocalDateTime.now()));
+
+            databaseServiceProvider.addJob(nfvoJob);
+        }
+        logger.info("Finished setting Job Status to {}", JobStatusEnum.ERROR);
+
+    }
+
+    protected void abortOperation(final DelegateExecution execution, final String message) {
+        abortOperation(execution, message, new InlineResponse400().detail(message));
+    }
+
+    protected void abortOperation(final DelegateExecution execution, final String message,
+            final InlineResponse400 problemDetails) {
+        logger.error(message);
+        execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, problemDetails);
+        throw new BpmnError("WORKFLOW_FAILED");
+    }
+
+    private NfvoJob getNfvoJob(final DelegateExecution execution) {
+        final String jobId = (String) execution.getVariable(JOB_ID_PARAM_NAME);
+        final Optional<NfvoJob> optional = databaseServiceProvider.getJob(jobId);
+        if (!optional.isPresent()) {
+            final String message = "Unable to find job using job id: " + jobId;
+            logger.error(message);
+            execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME,
+                    new InlineResponse400().detail(message));
+            throw new BpmnError("WORKFLOW_FAILED");
+
+        }
+        return optional.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/CreateNsTask.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/CreateNsTask.java
new file mode 100644 (file)
index 0000000..19cac68
--- /dev/null
@@ -0,0 +1,221 @@
+/*-
+ * ============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.CREATE_NS_REQUEST_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_RESPONSE_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_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.NS_INSTANCE_ID_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_PACKAGE_MODEL_PARAM_NAME;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.SERVICE_TYPE_PARAM_NAME;
+import java.time.LocalDateTime;
+import java.util.Optional;
+import java.util.UUID;
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.EtsiCatalogManagerRequestFailureException;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai.AaiServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogPackageManagementServiceProvider;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum;
+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.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.NsInstancesNsInstance;
+import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance.NsStateEnum;
+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 CreateNsTask extends AbstractNetworkServiceTask {
+    private static final String NETWORK_SERVICE_NAME = "NetworkService";
+    private static final String NETWORK_SERVICE_ROLE = "NetworkService";
+    private static final String DOES_NS_PACKAGE_EXISTS_PARAM_NAME = "doesNsPackageExists";
+    private static final String DOES_NS_INSTANCE_EXISTS_PARAM_NAME = "doesNsInstanceExists";
+    private static final Logger logger = LoggerFactory.getLogger(CreateNsTask.class);
+    private final EtsiCatalogPackageManagementServiceProvider etsiCatalogPackageManagementServiceProvider;
+    private final AaiServiceProvider aaiServiceProvider;
+
+    @Autowired
+    public CreateNsTask(final DatabaseServiceProvider databaseServiceProvider,
+            final AaiServiceProvider aaiServiceProvider,
+            final EtsiCatalogPackageManagementServiceProvider etsiCatalogPackageManagementServiceProvider) {
+        super(databaseServiceProvider);
+        this.aaiServiceProvider = aaiServiceProvider;
+        this.etsiCatalogPackageManagementServiceProvider = etsiCatalogPackageManagementServiceProvider;
+    }
+
+    public void setJobStatusToStarted(final DelegateExecution execution) {
+        setJobStatus(execution, JobStatusEnum.STARTED, "Create NS workflow process started");
+    }
+
+    public void setJobStatusToFinished(final DelegateExecution execution) {
+        setJobStatus(execution, JobStatusEnum.FINISHED, "Create NS workflow process finished");
+    }
+
+    public void setJobStatusToError(final DelegateExecution execution) {
+        setJobStatusToError(execution, "Create NS workflow process failed");
+    }
+
+    public void getNsPackage(final DelegateExecution execution) {
+        logger.info("Retrieving NS package from ETSI Catalog Manager ...");
+        setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Retrieving NS package from ETSI Catalog Manager");
+
+        final CreateNsRequest createNsRequest = (CreateNsRequest) execution.getVariable(CREATE_NS_REQUEST_PARAM_NAME);
+
+        try {
+            final Optional<NsdInfo> optional =
+                    etsiCatalogPackageManagementServiceProvider.getNSPackageModel(createNsRequest.getNsdId());
+
+            if (optional.isPresent()) {
+                final NsdInfo packageModel = optional.get();
+                logger.info("NS Package exists {}", packageModel);
+                execution.setVariable(NS_PACKAGE_MODEL_PARAM_NAME, packageModel);
+                execution.setVariable(DOES_NS_PACKAGE_EXISTS_PARAM_NAME, true);
+            } else {
+                final String message = "Unable to find NS package using NsdId: " + createNsRequest.getNsdId();
+                logger.error(message);
+                execution.setVariable(DOES_NS_PACKAGE_EXISTS_PARAM_NAME, false);
+                execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME,
+                        new InlineResponse400().detail(message));
+            }
+
+        } catch (final EtsiCatalogManagerRequestFailureException failureException) {
+            final String message =
+                    "Unexpected exception occured while getting ns package using nsdId: " + createNsRequest.getNsdId();
+            logger.error(message, failureException);
+
+            execution.setVariable(DOES_NS_PACKAGE_EXISTS_PARAM_NAME, false);
+
+            execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME,
+                    new InlineResponse400().title(message).detail(message));
+        }
+
+    }
+
+    public void doesNsInstanceExistsInDb(final DelegateExecution execution) {
+        logger.info("Executing doesNsInstanceExistsInDb  ...");
+
+        setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Checking if NS package exists in database");
+
+        final CreateNsRequest createNsRequest =
+                (CreateNsRequest) execution.getVariables().get(CREATE_NS_REQUEST_PARAM_NAME);
+
+        final boolean exists = databaseServiceProvider.isNsInstExists(createNsRequest.getNsName());
+        logger.info("Ns Instance entry {} exists in database", exists ? "does" : "doesn't");
+        execution.setVariable(DOES_NS_INSTANCE_EXISTS_PARAM_NAME, exists);
+
+        if (exists) {
+            final Optional<NfvoNsInst> optional =
+                    databaseServiceProvider.getNfvoNsInstByName(createNsRequest.getNsName());
+            final NfvoNsInst nfvoNsInst = optional.get();
+            execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, new InlineResponse400()
+                    .detail("Ns Instance already exists in database : " + nfvoNsInst.toString()));
+        }
+
+        logger.info("Finished executing doesNsInstanceExistsInDb  ...");
+
+    }
+
+    public void createNsInstanceInDb(final DelegateExecution execution) {
+        logger.info("Executing createNsInstanceInDb  ...");
+
+        setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Checking if NS package exists");
+
+        final CreateNsRequest createNsRequest = (CreateNsRequest) execution.getVariable(CREATE_NS_REQUEST_PARAM_NAME);
+        final NsdInfo packageMode = (NsdInfo) execution.getVariable(NS_PACKAGE_MODEL_PARAM_NAME);
+
+        final String globalCustomerId = (String) execution.getVariable(GLOBAL_CUSTOMER_ID_PARAM_NAME);
+        final String serviceType = (String) execution.getVariable(SERVICE_TYPE_PARAM_NAME);
+
+        final String nsInstId = UUID.randomUUID().toString();
+        execution.setVariable(NS_INSTANCE_ID_PARAM_NAME, nsInstId);
+
+        databaseServiceProvider.saveNfvoNsInst(new NfvoNsInst().nsInstId(nsInstId).name(createNsRequest.getNsName())
+                .nsPackageId(packageMode.getId()).nsdId(packageMode.getNsdId())
+                .nsdInvariantId(packageMode.getNsdInvariantId()).description(createNsRequest.getNsDescription())
+                .status(State.NOT_INSTANTIATED).statusUpdatedTime(LocalDateTime.now())
+                .globalCustomerId(globalCustomerId).serviceType(serviceType));
+        logger.info("Finished executing createNsInstanceInDb  ...");
+
+    }
+
+
+    public void createNsInstanceInAai(final DelegateExecution execution) {
+        logger.info("Executing createNsInstanceInAai  ...");
+        try {
+            setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Creating NS Instance in AAI");
+
+            final CreateNsRequest createNsRequest =
+                    (CreateNsRequest) execution.getVariable(CREATE_NS_REQUEST_PARAM_NAME);
+            final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+
+            final String globalCustomerId = (String) execution.getVariable(GLOBAL_CUSTOMER_ID_PARAM_NAME);
+            final String serviceType = (String) execution.getVariable(SERVICE_TYPE_PARAM_NAME);
+
+            final ServiceInstance aaiServiceInstance = new ServiceInstance();
+            aaiServiceInstance.setServiceInstanceId(nsInstId);
+            aaiServiceInstance.setServiceInstanceName(createNsRequest.getNsName());
+            aaiServiceInstance.setServiceType(NETWORK_SERVICE_NAME);
+            aaiServiceInstance.setServiceRole(NETWORK_SERVICE_ROLE);
+
+            aaiServiceProvider.createServiceInstance(globalCustomerId, serviceType, aaiServiceInstance);
+        } catch (final Exception exception) {
+            final String message = "Unable to Create Service Instance in AAI";
+            logger.error(message, exception);
+            abortOperation(execution, message, new InlineResponse400().detail(message));
+        }
+        logger.info("Finished executing createNsInstanceInAai  ...");
+
+    }
+
+    public void setCreateNsResponse(final DelegateExecution execution) {
+        logger.info("Executing setCreateNsResponse  ...");
+        final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME);
+        final Optional<NfvoNsInst> optional = databaseServiceProvider.getNfvoNsInstByNsInstId(nsInstId);
+
+        if (optional.isPresent()) {
+            final NfvoNsInst nfvoNsInst = optional.get();
+            final NsInstancesNsInstance response = new NsInstancesNsInstance().id(nfvoNsInst.getNsInstId())
+                    .nsInstanceName(nfvoNsInst.getName()).nsdId(nfvoNsInst.getNsdId())
+                    .nsdInfoId(nfvoNsInst.getNsPackageId()).nsInstanceDescription(nfvoNsInst.getDescription())
+                    .nsState(NsStateEnum.fromValue(nfvoNsInst.getStatus().toString()));
+            logger.info("Saving CreateNsResponse: {} in Execution ...", response);
+            execution.setVariable(CREATE_NS_RESPONSE_PARAM_NAME, response);
+        } else {
+            final String message = "Unable to find NS Instance in datababse using id: " + nsInstId;
+            logger.error(message);
+            abortOperation(execution, message);
+        }
+
+        logger.info("Finished executing setCreateNsResponse  ...");
+
+    }
+
+}
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/utils/LocalDateTimeTypeAdapter.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/utils/LocalDateTimeTypeAdapter.java
new file mode 100644 (file)
index 0000000..34959ee
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * ============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.utils;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class LocalDateTimeTypeAdapter extends TypeAdapter<LocalDateTime> {
+
+    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    @Override
+    public void write(final JsonWriter out, final LocalDateTime localDateTime) throws IOException {
+        if (localDateTime == null) {
+            out.nullValue();
+        } else {
+            out.value(FORMATTER.format(localDateTime));
+        }
+    }
+
+    @Override
+    public LocalDateTime read(final JsonReader in) throws IOException {
+        switch (in.peek()) {
+            case NULL:
+                in.nextNull();
+                return null;
+            default:
+                final String dateTime = in.nextString();
+                return LocalDateTime.parse(dateTime, FORMATTER);
+        }
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/CreateNs.bpmn b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/CreateNs.bpmn
new file mode 100644 (file)
index 0000000..815b76c
--- /dev/null
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1l4zor5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.0.0">
+  <bpmn:process id="CreateNs" name="&#10;CreateNs" isExecutable="true">
+    <bpmn:startEvent id="StartEvent_1" name="Start Process">
+      <bpmn:outgoing>Flow_1tqn5q5</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:endEvent id="EndEvent_1" name="End Process">
+      <bpmn:incoming>Flow_0t87ov3</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="Flow_1tqn5q5" sourceRef="StartEvent_1" targetRef="Activity_15ksfz6" />
+    <bpmn:serviceTask id="Activity_15ksfz6" name="Set Job Status to STARTED" camunda:asyncBefore="true" camunda:expression="${CreateNsTask.setJobStatusToStarted(execution)}">
+      <bpmn:incoming>Flow_1tqn5q5</bpmn:incoming>
+      <bpmn:outgoing>Flow_0y07mxe</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_0y07mxe" sourceRef="Activity_15ksfz6" targetRef="Activity_12yonzp" />
+    <bpmn:serviceTask id="Activity_1r4l8w8" name="Set Job Status to FINISHED" camunda:expression="${CreateNsTask.setJobStatusToFinished(execution)}">
+      <bpmn:incoming>Flow_1rtsvpm</bpmn:incoming>
+      <bpmn:outgoing>Flow_0t87ov3</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_0t87ov3" sourceRef="Activity_1r4l8w8" targetRef="EndEvent_1" />
+    <bpmn:exclusiveGateway id="Gateway_0fuwzjj" name="Does Ns Package exists?">
+      <bpmn:incoming>Flow_09582uw</bpmn:incoming>
+      <bpmn:outgoing>Flow_1f4vi10</bpmn:outgoing>
+      <bpmn:outgoing>Flow_0qabgp7</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:serviceTask id="Activity_12yonzp" name="Get Ns Package from ETSI Catalog Manager" camunda:expression="${CreateNsTask.getNsPackage(execution)}">
+      <bpmn:incoming>Flow_0y07mxe</bpmn:incoming>
+      <bpmn:outgoing>Flow_09582uw</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_09582uw" sourceRef="Activity_12yonzp" targetRef="Gateway_0fuwzjj" />
+    <bpmn:subProcess id="Activity_06ko4e2" name="Error Handling" triggeredByEvent="true">
+      <bpmn:startEvent id="Event_1ibvrn2" name="error">
+        <bpmn:outgoing>Flow_0554tjv</bpmn:outgoing>
+        <bpmn:errorEventDefinition id="ErrorEventDefinition_0lc46mh" />
+      </bpmn:startEvent>
+      <bpmn:endEvent id="Event_02f7sr1" name="end">
+        <bpmn:incoming>Flow_04xvpee</bpmn:incoming>
+      </bpmn:endEvent>
+      <bpmn:sequenceFlow id="Flow_0554tjv" sourceRef="Event_1ibvrn2" targetRef="Activity_1sj0nvr" />
+      <bpmn:serviceTask id="Activity_1sj0nvr" name="Set Job Status to ERROR" camunda:asyncBefore="true" camunda:expression="${CreateNsTask.setJobStatusToError(execution)}">
+        <bpmn:incoming>Flow_0554tjv</bpmn:incoming>
+        <bpmn:outgoing>Flow_04xvpee</bpmn:outgoing>
+      </bpmn:serviceTask>
+      <bpmn:sequenceFlow id="Flow_04xvpee" sourceRef="Activity_1sj0nvr" targetRef="Event_02f7sr1" />
+    </bpmn:subProcess>
+    <bpmn:subProcess id="Activity_1dx9fz6" name="Java Exception Handling" triggeredByEvent="true">
+      <bpmn:startEvent id="Event_0zne7ch" name="error">
+        <bpmn:outgoing>Flow_0j1otrx</bpmn:outgoing>
+        <bpmn:errorEventDefinition id="ErrorEventDefinition_1p3h4ta" errorRef="Error_0s855yd" camunda:errorCodeVariable="BPMN_javaExpCode" camunda:errorMessageVariable="BPMN_javaExpMsg" />
+      </bpmn:startEvent>
+      <bpmn:endEvent id="Event_0bcyh7u">
+        <bpmn:incoming>Flow_0oqv7vl</bpmn:incoming>
+      </bpmn:endEvent>
+      <bpmn:sequenceFlow id="Flow_0j1otrx" sourceRef="Event_0zne7ch" targetRef="Activity_15uwy90" />
+      <bpmn:serviceTask id="Activity_15uwy90" name="Set Job Status to ERROR" camunda:asyncBefore="true" camunda:expression="${CreateNsTask.setJobStatusToError(execution)}">
+        <bpmn:incoming>Flow_0j1otrx</bpmn:incoming>
+        <bpmn:outgoing>Flow_0oqv7vl</bpmn:outgoing>
+      </bpmn:serviceTask>
+      <bpmn:sequenceFlow id="Flow_0oqv7vl" sourceRef="Activity_15uwy90" targetRef="Event_0bcyh7u" />
+    </bpmn:subProcess>
+    <bpmn:sequenceFlow id="Flow_1f4vi10" name="No" sourceRef="Gateway_0fuwzjj" targetRef="Event_016q8gu">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{not doesNsPackageExists}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:endEvent id="Event_016q8gu">
+      <bpmn:incoming>Flow_1f4vi10</bpmn:incoming>
+      <bpmn:incoming>Flow_1yql1cm</bpmn:incoming>
+      <bpmn:errorEventDefinition id="ErrorEventDefinition_1ugx52k" errorRef="Error_0rqvnym" />
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="Flow_0qabgp7" name="Yes" sourceRef="Gateway_0fuwzjj" targetRef="Activity_0vlb2nk">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{doesNsPackageExists}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:serviceTask id="Activity_0vlb2nk" name="Check NS Instance exists In DB " camunda:expression="${CreateNsTask.doesNsInstanceExistsInDb(execution)}">
+      <bpmn:incoming>Flow_0qabgp7</bpmn:incoming>
+      <bpmn:outgoing>Flow_1exrj2b</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_1exrj2b" sourceRef="Activity_0vlb2nk" targetRef="Gateway_0d7n517" />
+    <bpmn:exclusiveGateway id="Gateway_0d7n517">
+      <bpmn:incoming>Flow_1exrj2b</bpmn:incoming>
+      <bpmn:outgoing>Flow_1rkg44s</bpmn:outgoing>
+      <bpmn:outgoing>Flow_1yql1cm</bpmn:outgoing>
+    </bpmn:exclusiveGateway>
+    <bpmn:sequenceFlow id="Flow_1rkg44s" name="No" sourceRef="Gateway_0d7n517" targetRef="Activity_09tqz8x">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{not doesNsInstanceExists}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:sequenceFlow id="Flow_1yql1cm" name="Yes" sourceRef="Gateway_0d7n517" targetRef="Event_016q8gu">
+      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">#{doesNsInstanceExists}</bpmn:conditionExpression>
+    </bpmn:sequenceFlow>
+    <bpmn:serviceTask id="Activity_09tqz8x" name="Create NS Instance record in DB" camunda:expression="${CreateNsTask.createNsInstanceInDb(execution)}">
+      <bpmn:incoming>Flow_1rkg44s</bpmn:incoming>
+      <bpmn:outgoing>Flow_1jvfwd2</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_1jvfwd2" sourceRef="Activity_09tqz8x" targetRef="Activity_1akc79d" />
+    <bpmn:serviceTask id="Activity_1akc79d" name="Create NS Instance in AAI" camunda:expression="${CreateNsTask.createNsInstanceInAai(execution)}">
+      <bpmn:incoming>Flow_1jvfwd2</bpmn:incoming>
+      <bpmn:outgoing>Flow_0e5hvno</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_0e5hvno" sourceRef="Activity_1akc79d" targetRef="Activity_03ht66t" />
+    <bpmn:serviceTask id="Activity_03ht66t" name="Set Create NS Response" camunda:expression="${CreateNsTask.setCreateNsResponse(execution)}">
+      <bpmn:incoming>Flow_0e5hvno</bpmn:incoming>
+      <bpmn:outgoing>Flow_1rtsvpm</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="Flow_1rtsvpm" sourceRef="Activity_03ht66t" targetRef="Activity_1r4l8w8" />
+  </bpmn:process>
+  <bpmn:error id="Error_0s855yd" name="java.lang.Exception" errorCode="java.lang.Exception" />
+  <bpmn:error id="Error_0rqvnym" name="CreateNsProcessingException" errorCode="CREATE_NS_PROCESSING_EXCEPTION" />
+  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
+    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="CreateNs">
+      <bpmndi:BPMNEdge id="Flow_1rtsvpm_di" bpmnElement="Flow_1rtsvpm">
+        <di:waypoint x="1160" y="157" />
+        <di:waypoint x="1160" y="230" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0e5hvno_di" bpmnElement="Flow_0e5hvno">
+        <di:waypoint x="1070" y="117" />
+        <di:waypoint x="1110" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1jvfwd2_di" bpmnElement="Flow_1jvfwd2">
+        <di:waypoint x="930" y="117" />
+        <di:waypoint x="970" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1yql1cm_di" bpmnElement="Flow_1yql1cm">
+        <di:waypoint x="760" y="142" />
+        <di:waypoint x="760" y="230" />
+        <di:waypoint x="668" y="230" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="766" y="183" width="19" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1rkg44s_di" bpmnElement="Flow_1rkg44s">
+        <di:waypoint x="785" y="117" />
+        <di:waypoint x="830" y="117" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="799" y="99" width="14" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1exrj2b_di" bpmnElement="Flow_1exrj2b">
+        <di:waypoint x="700" y="117" />
+        <di:waypoint x="735" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0qabgp7_di" bpmnElement="Flow_0qabgp7">
+        <di:waypoint x="565" y="117" />
+        <di:waypoint x="600" y="117" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="579" y="99" width="19" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1f4vi10_di" bpmnElement="Flow_1f4vi10">
+        <di:waypoint x="540" y="142" />
+        <di:waypoint x="540" y="230" />
+        <di:waypoint x="632" y="230" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="548" y="183" width="14" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_09582uw_di" bpmnElement="Flow_09582uw">
+        <di:waypoint x="480" y="117" />
+        <di:waypoint x="515" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0t87ov3_di" bpmnElement="Flow_0t87ov3">
+        <di:waypoint x="1160" y="310" />
+        <di:waypoint x="1160" y="357" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0y07mxe_di" bpmnElement="Flow_0y07mxe">
+        <di:waypoint x="350" y="117" />
+        <di:waypoint x="380" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_1tqn5q5_di" bpmnElement="Flow_1tqn5q5">
+        <di:waypoint x="208" y="117" />
+        <di:waypoint x="250" y="117" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
+        <dc:Bounds x="172" y="99" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="158" y="142" width="67" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_0db1w1a_di" bpmnElement="EndEvent_1">
+        <dc:Bounds x="1142" y="357" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="1129" y="400" width="63" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_15ksfz6_di" bpmnElement="Activity_15ksfz6">
+        <dc:Bounds x="250" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1r4l8w8_di" bpmnElement="Activity_1r4l8w8">
+        <dc:Bounds x="1110" y="230" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Gateway_0fuwzjj_di" bpmnElement="Gateway_0fuwzjj" isMarkerVisible="true">
+        <dc:Bounds x="515" y="92" width="50" height="50" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="498" y="62" width="88" height="27" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_12yonzp_di" bpmnElement="Activity_12yonzp">
+        <dc:Bounds x="380" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_06ko4e2_di" bpmnElement="Activity_06ko4e2" isExpanded="true">
+        <dc:Bounds x="431" y="310" width="438" height="130" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_04xvpee_di" bpmnElement="Flow_04xvpee">
+        <di:waypoint x="681" y="373" />
+        <di:waypoint x="813" y="373" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0554tjv_di" bpmnElement="Flow_0554tjv">
+        <di:waypoint x="489" y="373" />
+        <di:waypoint x="581" y="373" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Event_1ibvrn2_di" bpmnElement="Event_1ibvrn2">
+        <dc:Bounds x="453" y="355" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="459" y="398" width="24" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_02f7sr1_di" bpmnElement="Event_02f7sr1">
+        <dc:Bounds x="813" y="355" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="823" y="397" width="19" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1sj0nvr_di" bpmnElement="Activity_1sj0nvr">
+        <dc:Bounds x="581" y="333" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1dx9fz6_di" bpmnElement="Activity_1dx9fz6" isExpanded="true">
+        <dc:Bounds x="431" y="470" width="438" height="130" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_0oqv7vl_di" bpmnElement="Flow_0oqv7vl">
+        <di:waypoint x="680" y="533" />
+        <di:waypoint x="772" y="533" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0j1otrx_di" bpmnElement="Flow_0j1otrx">
+        <di:waypoint x="522" y="533" />
+        <di:waypoint x="580" y="533" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Event_0zne7ch_di" bpmnElement="Event_0zne7ch">
+        <dc:Bounds x="486" y="515" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="493" y="558" width="24" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_0bcyh7u_di" bpmnElement="Event_0bcyh7u">
+        <dc:Bounds x="772" y="515" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_15uwy90_di" bpmnElement="Activity_15uwy90">
+        <dc:Bounds x="580" y="493" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_0spfqz1_di" bpmnElement="Event_016q8gu">
+        <dc:Bounds x="632" y="212" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0vlb2nk_di" bpmnElement="Activity_0vlb2nk">
+        <dc:Bounds x="600" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Gateway_0d7n517_di" bpmnElement="Gateway_0d7n517" isMarkerVisible="true">
+        <dc:Bounds x="735" y="92" width="50" height="50" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_09tqz8x_di" bpmnElement="Activity_09tqz8x">
+        <dc:Bounds x="830" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1akc79d_di" bpmnElement="Activity_1akc79d">
+        <dc:Bounds x="970" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_03ht66t_di" bpmnElement="Activity_03ht66t">
+        <dc:Bounds x="1110" y="77" width="100" height="80" />
+      </bpmndi:BPMNShape>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</bpmn:definitions>
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/META-INF/services/org.onap.so.client.RestProperties b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/META-INF/services/org.onap.so.client.RestProperties
new file mode 100644 (file)
index 0000000..9d9ba73
--- /dev/null
@@ -0,0 +1 @@
+org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai.AaiPropertiesImpl
\ No newline at end of file
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/lcm/bpmn/flows/BaseTest.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/lcm/bpmn/flows/BaseTest.java
new file mode 100644 (file)
index 0000000..16557e7
--- /dev/null
@@ -0,0 +1,138 @@
+/*-
+ * ============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;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.camunda.bpm.engine.HistoryService;
+import org.camunda.bpm.engine.RuntimeService;
+import org.camunda.bpm.engine.history.HistoricProcessInstance;
+import org.camunda.bpm.engine.history.HistoricVariableInstance;
+import org.camunda.bpm.engine.runtime.ProcessInstance;
+import org.junit.runner.RunWith;
+import org.onap.so.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.service.DatabaseServiceProvider;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import com.github.tomakehurst.wiremock.WireMockServer;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+@ContextConfiguration
+@AutoConfigureWireMock(port = 0)
+public abstract class BaseTest {
+    protected static final String ETSI_CATALOG_URL = "http://modeling-etsicatalog.onap:8806/api";
+    protected static final String SOL003_ADAPTER_ENDPOINT_URL = "https://so-vnfm-adapter.onap:9092/so/vnfm-adapter/v1";
+    protected static final String GLOBAL_CUSTOMER_ID = UUID.randomUUID().toString();
+    protected static final String NSD_INVARIANT_ID = UUID.randomUUID().toString();
+    protected static final String SERVICE_TYPE = "NetworkService";
+    protected static final Logger logger = getLogger(BaseTest.class);
+
+    private static final long TIME_OUT_IN_SECONDS = 60;
+    private static final int SLEEP_TIME_IN_SECONDS = 5;
+
+    @Autowired
+    private HistoryService historyService;
+
+    @Autowired
+    private RuntimeService runtimeService;
+
+    @Autowired
+    protected DatabaseServiceProvider databaseServiceProvider;
+
+    @Autowired
+    protected WireMockServer wireMockServer;
+
+    public NfvoJob createNewNfvoJob(final String jobAction, final String nsdId, final String nsName) {
+        final NfvoJob newJob = new NfvoJob().startTime(LocalDateTime.now()).jobType("NS").jobAction(JobAction.CREATE)
+                .status(JobStatusEnum.STARTING).resourceId(nsdId).resourceName(nsName);
+        databaseServiceProvider.addJob(newJob);
+        return newJob;
+    }
+
+    public Optional<NfvoJob> getNfvoJob(final String jobId) {
+        return databaseServiceProvider.getJob(jobId);
+    }
+
+    public Optional<NfvoJob> getJobByResourceId(final String resourceId) {
+        return databaseServiceProvider.getJobByResourceId(resourceId);
+    }
+
+    public ProcessInstance executeWorkflow(final String processDefinitionKey, final String businessKey,
+            final Map<String, Object> variables) {
+        return runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
+    }
+
+    public HistoricProcessInstance getHistoricProcessInstance(final String processInstanceId) {
+        return historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
+    }
+
+    public HistoricVariableInstance getVariable(final String processInstanceId, final String name) {
+        return historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId)
+                .variableName(name).singleResult();
+    }
+
+    public List<HistoricVariableInstance> getVariables(final String processInstanceId) {
+        return historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
+    }
+
+    public boolean waitForProcessInstanceToFinish(final String processInstanceId) throws InterruptedException {
+        final long startTimeInMillis = System.currentTimeMillis();
+        final long timeOutTime = startTimeInMillis + TimeUnit.SECONDS.toMillis(TIME_OUT_IN_SECONDS);
+        while (timeOutTime > System.currentTimeMillis()) {
+
+            if (isProcessEndedByProcessInstanceId(processInstanceId)) {
+                logger.info("processInstanceId: {} is finished", processInstanceId);
+                return true;
+            }
+            logger.info("processInstanceId: {} is still running", processInstanceId);
+            logger.info("Process instance {} not finished yet, will try again in {} seconds", processInstanceId,
+                    SLEEP_TIME_IN_SECONDS);
+            TimeUnit.SECONDS.sleep(SLEEP_TIME_IN_SECONDS);
+        }
+        logger.warn("Timeout {} process didn't finished ", processInstanceId);
+        return false;
+    }
+
+
+    public boolean isProcessEndedByProcessInstanceId(final String processInstanceId) {
+        final HistoricProcessInstance processInstance = getHistoricProcessInstance(processInstanceId);
+        return processInstance != null
+                && !HistoricProcessInstance.STATE_ACTIVE.equalsIgnoreCase(processInstance.getState());
+    }
+
+}
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/lcm/bpmn/flows/DefaultToShortClassNameBeanNameGenerator.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/lcm/bpmn/flows/DefaultToShortClassNameBeanNameGenerator.java
new file mode 100644 (file)
index 0000000..f91cf9d
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ============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;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.AnnotationBeanNameGenerator;
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class DefaultToShortClassNameBeanNameGenerator extends AnnotationBeanNameGenerator {
+
+    @Override
+    protected String buildDefaultBeanName(final BeanDefinition definition) {
+        return ClassUtils.getShortName(definition.getBeanClassName());
+    }
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/TestApplication.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/lcm/bpmn/flows/TestApplication.java
new file mode 100644 (file)
index 0000000..18d6019
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ============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;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.context.annotation.ComponentScan.Filter;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@SpringBootApplication(scanBasePackages = {"org.onap.so"})
+@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class})
+@ComponentScan(basePackages = {"org.onap"}, nameGenerator = DefaultToShortClassNameBeanNameGenerator.class,
+        excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = SpringBootApplication.class)})
+public class TestApplication {
+
+    public static void main(final String[] args) {
+        new SpringApplication(TestApplication.class).run(args);
+    }
+
+}
diff --git a/so-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/CreateNsTaskTest.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/CreateNsTaskTest.java
new file mode 100644 (file)
index 0000000..05213a3
--- /dev/null
@@ -0,0 +1,387 @@
+/*-
+ * ============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.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN;
+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.withStatus;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import org.camunda.bpm.engine.history.HistoricProcessInstance;
+import org.camunda.bpm.engine.history.HistoricVariableInstance;
+import org.camunda.bpm.engine.runtime.ProcessInstance;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.BaseTest;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants;
+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.bpmn.flows.service.JobExecutorService;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service.WorkflowQueryService;
+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.NfvoNsInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State;
+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.NsInstancesNsInstance;
+import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance.NsStateEnum;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+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.github.tomakehurst.wiremock.client.WireMock;
+import com.google.gson.Gson;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class CreateNsTaskTest extends BaseTest {
+    private static final String NSD_ID = UUID.randomUUID().toString();
+    private static final String NS_NAME = "CreateNetworkService-" + NSD_ID;
+    private static final String CREATE_NS_WORKFLOW_NAME = "CreateNs";
+
+    @Autowired
+    @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private GsonProvider gsonProvider;
+
+    @Autowired
+    private JobExecutorService objUnderTest;
+
+    @Autowired
+    private WorkflowQueryService workflowQueryService;
+
+    private MockRestServiceServer mockRestServiceServer;
+
+    private Gson gson;
+
+    @Before
+    public void before() {
+        wireMockServer.resetAll();
+        final MockRestServiceServer.MockRestServiceServerBuilder builder = MockRestServiceServer.bindTo(restTemplate);
+        builder.ignoreExpectOrder(true);
+        mockRestServiceServer = builder.build();
+        gson = gsonProvider.getGson();
+        restTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
+    }
+
+    @After
+    public void after() {
+        wireMockServer.resetAll();
+        mockRestServiceServer.reset();
+    }
+
+    @Test
+    public void testCreateNsWorkflow_SuccessfullCase() throws InterruptedException {
+        final CreateNsRequest createNsRequest = getCreateNsRequest();
+
+        mockEtsiCatalogEndpoints();
+        mockAAIEndpoints(createNsRequest);
+
+        final NsInstancesNsInstance nsResponse =
+                objUnderTest.runCreateNsJob(createNsRequest, GLOBAL_CUSTOMER_ID, SERVICE_TYPE);
+        assertNotNull(nsResponse);
+        assertNotNull(nsResponse.getId());
+
+        final Optional<NfvoJob> optional = getJobByResourceId(createNsRequest.getNsdId());
+        assertTrue(optional.isPresent());
+        final NfvoJob nfvoJob = optional.get();
+
+        assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId()));
+
+        mockRestServiceServer.verify();
+        final HistoricProcessInstance historicProcessInstance =
+                getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
+        assertNotNull(historicProcessInstance);
+
+        assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
+        assertTrue(databaseServiceProvider.isNsInstExists(createNsRequest.getNsName()));
+
+        final NfvoJob actualJob = optional.get();
+        assertEquals(JobStatusEnum.FINISHED, actualJob.getStatus());
+
+        assertEquals(NS_NAME, nsResponse.getNsInstanceName());
+        assertEquals(NsStateEnum.NOT_INSTANTIATED, nsResponse.getNsState());
+
+        final HistoricVariableInstance doesNsPackageExistsVar =
+                getVariable(nfvoJob.getProcessInstanceId(), "doesNsPackageExists");
+        assertNotNull(doesNsPackageExistsVar);
+        assertTrue((boolean) doesNsPackageExistsVar.getValue());
+
+        final HistoricVariableInstance doesNsInstanceExistsVar =
+                getVariable(nfvoJob.getProcessInstanceId(), "doesNsInstanceExists");
+        assertNotNull(doesNsInstanceExistsVar);
+        assertFalse((boolean) doesNsInstanceExistsVar.getValue());
+
+    }
+
+    @Test
+    public void testCreateNsWorkflow_FailsToGetNsPackage() throws InterruptedException {
+        final String nsdId = UUID.randomUUID().toString();
+        final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
+        final CreateNsRequest createNsRequest = getCreateNsRequest(nsdId, nsdName);
+
+        mockRestServiceServer.expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId))
+                .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.NOT_FOUND));
+
+        try {
+            objUnderTest.runCreateNsJob(createNsRequest, GLOBAL_CUSTOMER_ID, SERVICE_TYPE);
+            fail("runCreateNsJob should throw exception");
+        } catch (final Exception exception) {
+            assertEquals(NsRequestProcessingException.class, exception.getClass());
+        }
+
+        final Optional<NfvoJob> optional = getJobByResourceId(createNsRequest.getNsdId());
+        assertTrue(optional.isPresent());
+        final NfvoJob nfvoJob = optional.get();
+        assertEquals(JobStatusEnum.ERROR, nfvoJob.getStatus());
+
+        assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId()));
+
+        mockRestServiceServer.verify();
+        final HistoricProcessInstance historicProcessInstance =
+                getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
+        assertNotNull(historicProcessInstance);
+
+        assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
+
+
+        final HistoricVariableInstance nsResponseVariable =
+                getVariable(nfvoJob.getProcessInstanceId(), CamundaVariableNameConstants.CREATE_NS_RESPONSE_PARAM_NAME);
+        assertNull(nsResponseVariable);
+
+        final Optional<InlineResponse400> problemDetailsOptional =
+                workflowQueryService.getProblemDetails(nfvoJob.getProcessInstanceId());
+        assertTrue(problemDetailsOptional.isPresent());
+
+        final InlineResponse400 problemDetails = problemDetailsOptional.get();
+        assertNotNull(problemDetails);
+        assertNotNull(problemDetails.getDetail());
+
+        final HistoricVariableInstance doesNsPackageExistsVar =
+                getVariable(nfvoJob.getProcessInstanceId(), "doesNsPackageExists");
+        assertNotNull(doesNsPackageExistsVar);
+        assertFalse((boolean) doesNsPackageExistsVar.getValue());
+        assertEquals("Unexpected exception occured while getting ns package using nsdId: " + nsdId,
+                problemDetails.getDetail());
+    }
+
+    @Test
+    public void testCreateNsWorkflow_FailsToFindJobUsingJobId() throws InterruptedException {
+        final String nsdId = UUID.randomUUID().toString();
+        final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
+        final CreateNsRequest createNsRequest = getCreateNsRequest(nsdId, nsdName);
+
+        final String randomJobId = UUID.randomUUID().toString();
+        final ProcessInstance processInstance =
+                executeWorkflow(CREATE_NS_WORKFLOW_NAME, randomJobId, getVariables(randomJobId, createNsRequest));
+        assertTrue(waitForProcessInstanceToFinish(processInstance.getProcessInstanceId()));
+
+        mockRestServiceServer.verify();
+        final HistoricProcessInstance historicProcessInstance =
+                getHistoricProcessInstance(processInstance.getProcessInstanceId());
+        assertNotNull(historicProcessInstance);
+
+        assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
+
+        final HistoricVariableInstance nsResponseVariable = getVariable(processInstance.getProcessInstanceId(),
+                CamundaVariableNameConstants.CREATE_NS_RESPONSE_PARAM_NAME);
+
+        assertNull(nsResponseVariable);
+
+        final HistoricVariableInstance workflowExceptionVariable = getVariable(processInstance.getProcessInstanceId(),
+                CamundaVariableNameConstants.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME);
+
+        final InlineResponse400 problemDetails = (InlineResponse400) workflowExceptionVariable.getValue();
+        assertNotNull(problemDetails);
+        assertNotNull(problemDetails.getDetail());
+        assertEquals("Unable to find job using job id: " + randomJobId, problemDetails.getDetail());
+
+    }
+
+    @Test
+    public void testCreateNsWorkflow_NsInstanceExistsInDb() throws InterruptedException {
+        final String nsdId = UUID.randomUUID().toString();
+        final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
+        final CreateNsRequest createNsRequest = getCreateNsRequest(nsdId, nsdName);
+
+        databaseServiceProvider.saveNfvoNsInst(new NfvoNsInst().nsInstId(nsdId).name(createNsRequest.getNsName())
+                .nsPackageId(UUID.randomUUID().toString()).nsdId(nsdId).nsdInvariantId(nsdId)
+                .description(createNsRequest.getNsDescription()).status(State.INSTANTIATED)
+                .statusUpdatedTime(LocalDateTime.now()).globalCustomerId(GLOBAL_CUSTOMER_ID).serviceType(SERVICE_TYPE));
+
+        mockEtsiCatalogEndpoints(nsdId);
+
+        try {
+            objUnderTest.runCreateNsJob(createNsRequest, GLOBAL_CUSTOMER_ID, SERVICE_TYPE);
+            fail("runCreateNsJob should throw exception");
+        } catch (final Exception exception) {
+            assertEquals(NsRequestProcessingException.class, exception.getClass());
+        }
+
+        final Optional<NfvoJob> optional = getJobByResourceId(createNsRequest.getNsdId());
+        assertTrue(optional.isPresent());
+        final NfvoJob nfvoJob = optional.get();
+        assertEquals(JobStatusEnum.ERROR, nfvoJob.getStatus());
+
+        assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId()));
+
+        mockRestServiceServer.verify();
+        final HistoricProcessInstance historicProcessInstance =
+                getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
+        assertNotNull(historicProcessInstance);
+
+        assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
+        assertTrue(databaseServiceProvider.isNsInstExists(createNsRequest.getNsName()));
+
+        final HistoricVariableInstance historicVariableInstance =
+                getVariable(nfvoJob.getProcessInstanceId(), CamundaVariableNameConstants.CREATE_NS_RESPONSE_PARAM_NAME);
+
+        assertNull(historicVariableInstance);
+
+        final Optional<InlineResponse400> problemDetailsOptional =
+                workflowQueryService.getProblemDetails(nfvoJob.getProcessInstanceId());
+
+        final InlineResponse400 problemDetails = problemDetailsOptional.get();
+        assertNotNull(problemDetails);
+        assertNotNull(problemDetails.getDetail());
+        assertTrue(problemDetails.getDetail().startsWith("Ns Instance already exists in database"));
+
+        final HistoricVariableInstance doesNsInstanceExistsVar =
+                getVariable(nfvoJob.getProcessInstanceId(), "doesNsInstanceExists");
+        assertNotNull(doesNsInstanceExistsVar);
+        assertTrue((boolean) doesNsInstanceExistsVar.getValue());
+
+    }
+
+    @Test
+    public void testCreateNsWorkflow_FailToCreateResouceInAai() throws InterruptedException {
+        final String nsdId = UUID.randomUUID().toString();
+        final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
+        final CreateNsRequest createNsRequest = getCreateNsRequest(nsdId, nsdName);
+
+        mockEtsiCatalogEndpoints(nsdId);
+
+        final String modelEndpoint = getAiaServiceInstancelEndPoint(createNsRequest);
+        wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(WireMock.serverError()));
+        wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(WireMock.serverError()));
+
+        try {
+            objUnderTest.runCreateNsJob(createNsRequest, GLOBAL_CUSTOMER_ID, SERVICE_TYPE);
+            fail("runCreateNsJob should throw exception");
+        } catch (final Exception exception) {
+            assertEquals(NsRequestProcessingException.class, exception.getClass());
+        }
+        final Optional<NfvoJob> optional = getJobByResourceId(createNsRequest.getNsdId());
+        assertTrue(optional.isPresent());
+        final NfvoJob nfvoJob = optional.get();
+        assertEquals(JobStatusEnum.ERROR, nfvoJob.getStatus());
+
+        mockRestServiceServer.verify();
+        final HistoricProcessInstance historicProcessInstance =
+                getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
+        assertNotNull(historicProcessInstance);
+
+        assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
+        assertTrue(databaseServiceProvider.isNsInstExists(createNsRequest.getNsName()));
+
+        final Optional<InlineResponse400> problemDetailsOptional =
+                workflowQueryService.getProblemDetails(nfvoJob.getProcessInstanceId());
+
+        final InlineResponse400 problemDetails = problemDetailsOptional.get();
+        assertNotNull(problemDetails);
+        assertEquals("Unable to Create Service Instance in AAI", problemDetails.getDetail());
+
+    }
+
+    private void mockAAIEndpoints(final CreateNsRequest createNsRequest) {
+        final String modelEndpoint = getAiaServiceInstancelEndPoint(createNsRequest);
+
+        wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(ok()));
+        wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(notFound()));
+    }
+
+    private String getAiaServiceInstancelEndPoint(final CreateNsRequest createNsRequest) {
+        return "/aai/v[0-9]+/business/customers/customer/" + GLOBAL_CUSTOMER_ID
+                + "/service-subscriptions/service-subscription/" + SERVICE_TYPE
+                + "/service-instances/service-instance/.*";
+    }
+
+    private void mockEtsiCatalogEndpoints(final String nsdId) {
+        mockRestServiceServer.expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId))
+                .andExpect(method(HttpMethod.GET))
+                .andRespond(withSuccess(gson.toJson(getNSPackageModel(NSD_ID)), MediaType.APPLICATION_JSON));
+    }
+
+    private void mockEtsiCatalogEndpoints() {
+        mockEtsiCatalogEndpoints(NSD_ID);;
+    }
+
+    private NsdInfo getNSPackageModel(final String nsdId) {
+        return new NsdInfo().id(nsdId).nsdId(nsdId).nsdInvariantId(NSD_INVARIANT_ID).nsdName("vcpe").nsdDesigner("ONAP")
+                .vnfPkgIds(Arrays.asList(GLOBAL_CUSTOMER_ID));
+    }
+
+    private CreateNsRequest getCreateNsRequest() {
+        return getCreateNsRequest(NSD_ID, NS_NAME);
+    }
+
+    private CreateNsRequest getCreateNsRequest(final String nsdId, final String nsName) {
+        return new CreateNsRequest().nsdId(nsdId).nsName(nsName);
+    }
+
+    private Map<String, Object> getVariables(final String jobId, final CreateNsRequest createNsRequest) {
+        final Map<String, Object> variables = new HashMap<>();
+        variables.put(CamundaVariableNameConstants.JOB_ID_PARAM_NAME, jobId);
+        variables.put(CamundaVariableNameConstants.CREATE_NS_REQUEST_PARAM_NAME, createNsRequest);
+        variables.put(CamundaVariableNameConstants.GLOBAL_CUSTOMER_ID_PARAM_NAME, GLOBAL_CUSTOMER_ID);
+        variables.put(CamundaVariableNameConstants.SERVICE_TYPE_PARAM_NAME, SERVICE_TYPE);
+
+        return variables;
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml
new file mode 100644 (file)
index 0000000..3faa62c
--- /dev/null
@@ -0,0 +1,48 @@
+# Copyright Â© 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.
+spring:
+   main:
+      allow-bean-definition-overriding: true
+   datasource:
+      hikari:
+         camunda:
+            jdbcUrl: jdbc:h2:mem:example-simple;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+            driver-class-name: org.h2.Driver
+            pool-name: ns-lcm-bpmn-pool
+            registerMbeans: true
+         nfvo:
+            jdbcUrl: jdbc:h2:mem:nfvo;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS nfvo;
+            driver-class-name: org.h2.Driver
+            pool-name: ns-lcm-bpmn-pool
+            registerMbeans: true
+   jpa:
+      generate-ddl: true
+      hibernate:
+         ddl-auto: create
+hibernate:
+   dialect: org.hibernate.dialect.H2Dialect
+   hbm2ddl:
+      auto: create
+aai:
+   version: v19
+   endpoint: http://localhost:${wiremock.server.port}
+etsi-catalog-manager:
+   base:
+      endpoint: http://modeling-etsicatalog.onap:8806/api
+so-etsi-ns-lcm-workflow-engine:
+   requesttimeout:
+      timeoutInSeconds: 10
+logging:
+   level:
+      org.reflections.Reflections: ERROR
\ No newline at end of file
index b860dde..e043907 100644 (file)
       <groupId>org.flywaydb</groupId>
       <artifactId>flyway-core</artifactId>
     </dependency>
+    <dependency>
+      <groupId>com.h2database</groupId>
+      <artifactId>h2</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
\ No newline at end of file
index 0438a42..8f146e5 100644 (file)
@@ -48,11 +48,12 @@ import com.zaxxer.hikari.HikariDataSource;
         basePackages = {"org.onap.so.etsi.nfvo.ns.lcm.database.repository"})
 public class NfvoDatabaseConfiguration {
 
+    private static final String PERSISTENCE_UNIT = "nfvo";
+    private static final String NFVO_DATA_SOURCE_QUALIFIER = "nfvoDataSource";
+
     @Autowired(required = false)
     private MBeanExporter mBeanExporter;
 
-    private static final String NFVO_DATA_SOURCE_QUALIFIER = "nfvoDataSource";
-
     @Bean
     @ConfigurationProperties(prefix = "spring.datasource.hikari.nfvo")
     public HikariConfig nfvoDbConfig() {
@@ -72,8 +73,8 @@ public class NfvoDatabaseConfiguration {
     @Bean(name = "entityManagerFactory")
     public LocalContainerEntityManagerFactoryBean entityManagerFactory(final EntityManagerFactoryBuilder builder,
             @Qualifier(NFVO_DATA_SOURCE_QUALIFIER) final DataSource dataSource) {
-        return builder.dataSource(dataSource).packages(NfvoJob.class.getPackage().getName()).persistenceUnit("nfvo")
-                .build();
+        return builder.dataSource(dataSource).packages(NfvoJob.class.getPackage().getName())
+                .persistenceUnit(PERSISTENCE_UNIT).build();
     }
 
     @Primary
diff --git a/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/repository/NfvoJobRepository.java b/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/repository/NfvoJobRepository.java
new file mode 100644 (file)
index 0000000..844f608
--- /dev/null
@@ -0,0 +1,35 @@
+/*-
+ * ============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.database.repository;
+
+import java.util.Optional;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface NfvoJobRepository extends CrudRepository<NfvoJob, String> {
+
+    Optional<NfvoJob> findByResourceId(final String resourceId);
+
+
+}
diff --git a/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/repository/NfvoNsInstRepository.java b/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/repository/NfvoNsInstRepository.java
new file mode 100644 (file)
index 0000000..beeeacf
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ============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.database.repository;
+
+import java.util.Optional;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface NfvoNsInstRepository extends CrudRepository<NfvoNsInst, String> {
+
+    Optional<NfvoNsInst> findByName(final String name);
+
+    Optional<NfvoNsInst> findByNsInstId(final String nsInstId);
+
+    boolean existsNfvoNsInstByName(final String name);
+
+
+}
diff --git a/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 b/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
new file mode 100644 (file)
index 0000000..420d916
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * ============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.database.service;
+
+import java.util.Optional;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob;
+import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst;
+import org.onap.so.etsi.nfvo.ns.lcm.database.repository.NfvoJobRepository;
+import org.onap.so.etsi.nfvo.ns.lcm.database.repository.NfvoNsInstRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+
+@Service
+public class DatabaseServiceProvider {
+    private static final Logger logger = LoggerFactory.getLogger(DatabaseServiceProvider.class);
+
+    private final NfvoJobRepository nfvoJobRepository;
+
+    private final NfvoNsInstRepository nfvoNsInstRepository;
+
+    @Autowired
+    public DatabaseServiceProvider(final NfvoJobRepository nfvoJobRepository,
+            final NfvoNsInstRepository nfvoNsInstRepository) {
+        this.nfvoJobRepository = nfvoJobRepository;
+        this.nfvoNsInstRepository = nfvoNsInstRepository;
+    }
+
+    public boolean addJob(final NfvoJob job) {
+        logger.info("Adding NfvoJob: {} to database", job);
+        return nfvoJobRepository.save(job) != null;
+    }
+
+    public Optional<NfvoJob> getJob(final String jobId) {
+        logger.info("Querying database for NfvoJob using jobId: {}", jobId);
+        return nfvoJobRepository.findById(jobId);
+    }
+
+    public Optional<NfvoJob> getJobByResourceId(final String resourceId) {
+        logger.info("Querying database for NfvoJob using resourceId: {}", resourceId);
+        return nfvoJobRepository.findByResourceId(resourceId);
+    }
+
+    public boolean isNsInstExists(final String name) {
+        logger.info("Checking if NfvoNsInst entry exists in database using name: {}", name);
+        return nfvoNsInstRepository.existsNfvoNsInstByName(name);
+    }
+
+    public boolean saveNfvoNsInst(final NfvoNsInst nfvoNsInst) {
+        logger.info("Saving NfvoNsInst: {} to database", nfvoNsInst);
+        return nfvoNsInstRepository.save(nfvoNsInst) != null;
+    }
+
+    public Optional<NfvoNsInst> getNfvoNsInst(final String nsInstId) {
+        logger.info("Querying database for NfvoNsInst using nsInstId: {}", nsInstId);
+        return nfvoNsInstRepository.findById(nsInstId);
+    }
+
+    public Optional<NfvoNsInst> getNfvoNsInstByName(final String name) {
+        logger.info("Querying database for NfvoNsInst using name: {}", name);
+        return nfvoNsInstRepository.findByName(name);
+    }
+
+    public Optional<NfvoNsInst> getNfvoNsInstByNsInstId(final String nsInstId) {
+        logger.info("Querying database for NfvoNsInst using nsInstId: {}", nsInstId);
+        return nfvoNsInstRepository.findByNsInstId(nsInstId);
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/DatabaseServiceProviderTest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/DatabaseServiceProviderTest.java
new file mode 100644 (file)
index 0000000..03488e9
--- /dev/null
@@ -0,0 +1,115 @@
+/*-
+ * ============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.database;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import java.time.LocalDateTime;
+import java.util.Optional;
+import java.util.UUID;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+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.NfvoJobStatus;
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+public class DatabaseServiceProviderTest {
+
+    private static final String RANDOM_ID = UUID.randomUUID().toString();
+    private static final String DUMMY_NAME = "NAME";
+    private static final LocalDateTime CURRENT_DATE_TIME = LocalDateTime.now();
+    @Autowired
+    private DatabaseServiceProvider databaseServiceProvider;
+
+    @Test
+    public void testAddJob_StoredInDatabase() {
+        final NfvoJob expected = new NfvoJob().jobType("TYPE").jobAction(JobAction.CREATE).resourceId(RANDOM_ID)
+                .resourceName(DUMMY_NAME).startTime(CURRENT_DATE_TIME).status(JobStatusEnum.STARTED);
+        databaseServiceProvider.addJob(expected);
+
+        final Optional<NfvoJob> actual = databaseServiceProvider.getJob(expected.getJobId());
+        assertEquals(expected, actual.get());
+    }
+
+    @Test
+    public void testAddJobWithJobStatus_StoredInDatabase() {
+        final NfvoJob job = new NfvoJob().jobType("TYPE").jobAction(JobAction.CREATE).resourceId(RANDOM_ID)
+                .resourceName(DUMMY_NAME).startTime(CURRENT_DATE_TIME).status(JobStatusEnum.STARTED);
+        databaseServiceProvider.addJob(job);
+
+        final NfvoJobStatus jobStatus = new NfvoJobStatus().status(JobStatusEnum.STARTED)
+                .description("Create NS workflow process started").updatedTime(CURRENT_DATE_TIME);
+        databaseServiceProvider.addJob(job.nfvoJobStatus(jobStatus));
+
+        final Optional<NfvoJob> actual = databaseServiceProvider.getJob(job.getJobId());
+        final NfvoJob actualNfvoJob = actual.get();
+
+        assertEquals(job.getJobId(), actualNfvoJob.getJobId());
+        assertFalse(actualNfvoJob.getNfvoJobStatuses().isEmpty());
+        assertEquals(job.getJobId(), actualNfvoJob.getNfvoJobStatuses().get(0).getNfvoJob().getJobId());
+
+    }
+
+    @Test
+    public void testAddNsInst_StoredInDatabase_ableTofindByQuery() {
+
+        final NfvoNsInst nsInst = new NfvoNsInst().name(DUMMY_NAME).nsdId(RANDOM_ID).status(State.NOT_INSTANTIATED)
+                .nsdInvariantId(RANDOM_ID).statusUpdatedTime(CURRENT_DATE_TIME);
+
+        databaseServiceProvider.saveNfvoNsInst(nsInst);
+
+        Optional<NfvoNsInst> actual = databaseServiceProvider.getNfvoNsInst(nsInst.getNsInstId());
+        NfvoNsInst actualNfvoNsInst = actual.get();
+        assertEquals(nsInst.getNsInstId(), actualNfvoNsInst.getNsInstId());
+        assertEquals(RANDOM_ID, actualNfvoNsInst.getNsdId());
+        assertEquals(State.NOT_INSTANTIATED, actualNfvoNsInst.getStatus());
+        assertEquals(RANDOM_ID, actualNfvoNsInst.getNsdInvariantId());
+        assertEquals(CURRENT_DATE_TIME, actualNfvoNsInst.getStatusUpdatedTime());
+
+        actual = databaseServiceProvider.getNfvoNsInstByName(DUMMY_NAME);
+        actualNfvoNsInst = actual.get();
+
+        assertEquals(nsInst.getNsInstId(), actualNfvoNsInst.getNsInstId());
+        assertEquals(RANDOM_ID, actualNfvoNsInst.getNsdId());
+        assertEquals(State.NOT_INSTANTIATED, actualNfvoNsInst.getStatus());
+        assertEquals(RANDOM_ID, actualNfvoNsInst.getNsdInvariantId());
+        assertEquals(CURRENT_DATE_TIME, actualNfvoNsInst.getStatusUpdatedTime());
+
+
+        assertTrue(databaseServiceProvider.isNsInstExists(DUMMY_NAME));
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/TestApplication.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/TestApplication.java
new file mode 100644 (file)
index 0000000..921cae2
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ============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.database;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.context.annotation.ComponentScan.Filter;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@SpringBootApplication(scanBasePackages = {"org.onap.so"})
+@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class})
+@ComponentScan(basePackages = {"org.onap"},
+        excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = SpringBootApplication.class)})
+public class TestApplication {
+
+    public static void main(final String[] args) {
+        new SpringApplication(TestApplication.class).run(args);
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/utils/UtilsTest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/utils/UtilsTest.java
new file mode 100644 (file)
index 0000000..632bda9
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============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.database.beans.utils;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Test;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class UtilsTest {
+
+    @Test
+    public void testTwoEmptyLists_equal() {
+        assertTrue(Utils.isEquals(Collections.emptyList(), Collections.emptyList()));
+    }
+
+    @Test
+    public void testEmptyListAndNonEmpty_notEqual() {
+        assertFalse(Utils.isEquals(Collections.emptyList(), Arrays.asList("A")));
+    }
+
+    @Test
+    public void testTwoNullLists_equal() {
+        assertTrue(Utils.isEquals(null, null));
+    }
+
+    @Test
+    public void testNullListAndEmptyList_notEqual() {
+        assertFalse(Utils.isEquals(null, Collections.emptyList()));
+    }
+
+    @Test
+    public void testTwoNotEmptyListsContainSameObjects_equal() {
+        assertTrue(Utils.isEquals(Arrays.asList("A"), Arrays.asList("A")));
+    }
+
+    @Test
+    public void testTwoNotEmptyListsContainsDifferentObjects_equal() {
+        assertFalse(Utils.isEquals(Arrays.asList("A"), Arrays.asList(1)));
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/resources/application.yaml b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/test/resources/application.yaml
new file mode 100644 (file)
index 0000000..8b7550d
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright Â© 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.
+spring:
+   main:
+      web-application-type: none
+   datasource:
+      hikari:
+         nfvo:
+            jdbcUrl: jdbc:h2:mem:nfvo;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS nfvo;
+            driver-class-name: org.h2.Driver
+            pool-name: ns-lcm-bpmn-pool
+            registerMbeans: true
+   jpa:
+      generate-ddl: true
+      hibernate:
+         ddl-auto: create
+         
+logging:
+   level:
+      org.flywaydb: DEBUG
+hibernate:
+   dialect: org.hibernate.dialect.H2Dialect
+   hbm2ddl:
+      auto: create
\ No newline at end of file
index d48acb6..6605602 100644 (file)
       <artifactId>so-etsi-nfvo-ns-lcm-api</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.onap.so.etsi.nfvo</groupId>
+      <artifactId>so-etsi-nfvo-ns-lcm-bpmn-flows</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.h2database</groupId>
+      <artifactId>h2</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
\ No newline at end of file
index 97ad174..d330df3 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Nordix. All rights reserved.
+ *  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=========================================================
  */
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/EtsiSoNsLcmManagerUrlProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/EtsiSoNsLcmManagerUrlProvider.java
new file mode 100644 (file)
index 0000000..baf1119
--- /dev/null
@@ -0,0 +1,53 @@
+/*-
+ * ============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;
+
+import java.net.URI;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Configuration
+public class EtsiSoNsLcmManagerUrlProvider {
+
+    private final String etsiNsLcmManagerEndpoint;
+
+    @Autowired
+    public EtsiSoNsLcmManagerUrlProvider(
+            @Value("${etsi-so-ns-lcm-manager.endpoint}") final String etsiNsLcmManagerEndpoint) {
+        this.etsiNsLcmManagerEndpoint = etsiNsLcmManagerEndpoint;
+    }
+
+    public URI getCreatedNsResourceUri(final String nsInstanceId) {
+        return URI.create(etsiNsLcmManagerEndpoint + Constants.NS_LIFE_CYCLE_MANAGEMENT_BASE_URL + "/ns_instances/"
+                + nsInstanceId);
+    }
+
+    public URI getInstantiatedOccUri(final String nsLcmOpOccId) {
+        return URI.create(etsiNsLcmManagerEndpoint + Constants.NS_LIFE_CYCLE_MANAGEMENT_BASE_URL + "/ns_lcm_op_occs/"
+                + nsLcmOpOccId);
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/GsonSerializerConfiguration.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/GsonSerializerConfiguration.java
new file mode 100644 (file)
index 0000000..2e11ada
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * ============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;
+
+import java.time.LocalDateTime;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.utils.LocalDateTimeTypeAdapter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.google.gson.GsonBuilder;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Configuration
+public class GsonSerializerConfiguration {
+
+    @Bean
+    public GsonBuilder gsonBuilder() {
+        return new GsonBuilder().registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter());
+    }
+
+}
+
+
diff --git a/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 b/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
new file mode 100644 (file)
index 0000000..f295731
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============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.lifecycle;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import java.net.URI;
+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.NsInstancesNsInstance;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class NsLifeCycleManager {
+    private static final Logger logger = getLogger(NsLifeCycleManager.class);
+
+    private final JobExecutorService jobExecutorService;
+
+    @Value("${etsi-so-ns-workflow-engine.requesttimeout.create.timeoutInSeconds:300}")
+    private int timeOutInSeconds;
+
+    private final EtsiSoNsLcmManagerUrlProvider etsiSoNsLcmManagerUrlProvider;
+
+    @Autowired
+    public NsLifeCycleManager(final JobExecutorService jobExecutorService,
+            final EtsiSoNsLcmManagerUrlProvider etsiSoNsLcmManagerUrlProvider) {
+        this.jobExecutorService = jobExecutorService;
+        this.etsiSoNsLcmManagerUrlProvider = etsiSoNsLcmManagerUrlProvider;
+    }
+
+    public ImmutablePair<URI, NsInstancesNsInstance> createNs(final CreateNsRequest createNsRequest,
+            final String globalCustomerId, final String serviceType) {
+        logger.info("Will execute Create Ns for CreateNsRequest: {}, globalCustomerId: {} and serviceType: {}",
+                createNsRequest, globalCustomerId, serviceType);
+        final NsInstancesNsInstance nsInstanceResponse =
+                jobExecutorService.runCreateNsJob(createNsRequest, globalCustomerId, serviceType);
+
+        return ImmutablePair.of(etsiSoNsLcmManagerUrlProvider.getCreatedNsResourceUri(nsInstanceResponse.getId()),
+                nsInstanceResponse);
+    }
+
+}
index aed4f4b..ec79ce6 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Nordix. All rights reserved.
+ *  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=========================================================
  */
index 4dd1258..fb0a250 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Nordix. All rights reserved.
+ *  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=========================================================
  */
@@ -24,12 +24,17 @@ import static org.onap.so.etsi.nfvo.ns.lcm.Constants.HTTP_SERVICETYPE_HEADER_DEF
 import static org.onap.so.etsi.nfvo.ns.lcm.Constants.HTTP_SERVICETYPE_HEADER_PARM_NAME;
 import static org.onap.so.etsi.nfvo.ns.lcm.Constants.NS_LIFE_CYCLE_MANAGEMENT_BASE_URL;
 import static org.slf4j.LoggerFactory.getLogger;
+import java.net.URI;
 import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.onap.so.etsi.nfvo.ns.lcm.lifecycle.NsLifeCycleManager;
 import org.onap.so.etsi.nfvo.ns.lcm.model.Body;
 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.onap.so.etsi.nfvo.ns.lcm.model.TerminateNsRequest;
 import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Controller;
@@ -53,6 +58,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
 public class NsLifecycleManagementController {
     private static final Logger logger = getLogger(NsLifecycleManagementController.class);
 
+    private final NsLifeCycleManager nsLifeCycleManager;
+
+    @Autowired
+    public NsLifecycleManagementController(final NsLifeCycleManager nsLifeCycleManager) {
+        this.nsLifeCycleManager = nsLifeCycleManager;
+    }
 
     /**
      * The POST method creates new {@link Body new NS instance resource} request. See Section Number: 6.3.1 for more
@@ -74,7 +85,17 @@ public class NsLifecycleManagementController {
             @RequestBody final CreateNsRequest createNsRequest) {
         logger.info("Received Create NS Request: {}\n with globalCustomerId: {}\n serviceType: {}\n", createNsRequest,
                 globalCustomerId, serviceType);
-        return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).body("Operation is not supported yet");
+
+        final ImmutablePair<URI, NsInstancesNsInstance> nsInstance =
+                nsLifeCycleManager.createNs(createNsRequest, globalCustomerId, serviceType);
+
+        final URI resourceUri = nsInstance.getLeft();
+        final NsInstancesNsInstance createdNsresponse = nsInstance.getRight();
+
+        logger.info("NS resource created successfully. Resource location: {}, response: {}", resourceUri,
+                createdNsresponse);
+
+        return ResponseEntity.created(resourceUri).body(createdNsresponse);
     }
 
     /**
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/rest/exceptions/NsLcmControllerExceptionHandler.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/rest/exceptions/NsLcmControllerExceptionHandler.java
new file mode 100644 (file)
index 0000000..8d9fdbe
--- /dev/null
@@ -0,0 +1,61 @@
+/*-
+ * ============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.rest.exceptions;
+
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.NsRequestProcessingException;
+import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400;
+import org.onap.so.etsi.nfvo.ns.lcm.rest.NsLifecycleManagementController;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@ControllerAdvice(assignableTypes = NsLifecycleManagementController.class)
+public class NsLcmControllerExceptionHandler {
+
+    @ExceptionHandler(NsRequestProcessingException.class)
+    public ResponseEntity<InlineResponse400> handleNsRequestProcessingException(
+            final NsRequestProcessingException nsRequestProcessingException) {
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+                .body(getInlineResponse400(nsRequestProcessingException));
+    }
+
+    private InlineResponse400 getInlineResponse400(final NsRequestProcessingException nsRequestProcessingException) {
+
+        if (nsRequestProcessingException.getProblemDetails() != null) {
+            return nsRequestProcessingException.getProblemDetails();
+        }
+
+        return new InlineResponse400().status(HttpStatus.INTERNAL_SERVER_ERROR.value())
+                .detail(nsRequestProcessingException.getMessage());
+
+    }
+
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<InlineResponse400> handleNsRequestProcessingException(final Exception exception) {
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new InlineResponse400()
+                .status(HttpStatus.INTERNAL_SERVER_ERROR.value()).detail(exception.getMessage()));
+    }
+
+}
index 6e5f6c0..d6f4a83 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Ericsson. All rights reserved.
+ *  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=========================================================
  */
index ae491b6..9eace92 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Ericsson. All rights reserved.
+ *  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=========================================================
  */
index 6f25092..4ff74ea 100644 (file)
@@ -1,19 +1,19 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Ericsson. All rights reserved.
+ *  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=========================================================
  */
@@ -24,18 +24,30 @@ package org.onap.so.etsi.nfvo.ns.lcm.rest;
  *
  */
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+import java.net.URISyntaxException;
 import java.time.LocalDateTime;
+import java.util.List;
 import java.util.UUID;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.onap.so.etsi.nfvo.ns.lcm.Constants;
-import org.onap.so.etsi.nfvo.ns.lcm.JSON;
 import org.onap.so.etsi.nfvo.ns.lcm.TestApplication;
+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.bpmn.flows.service.JobExecutorService;
 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.onap.so.etsi.nfvo.ns.lcm.model.TerminateNsRequest;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.boot.test.web.client.TestRestTemplate;
 import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.boot.web.server.LocalServerPort;
@@ -57,27 +69,102 @@ import com.google.gson.Gson;
 @SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
 @ActiveProfiles("test")
 public class NsLifecycleManagementControllerTest {
+    private static final String RANDOM_NS_INST_ID = UUID.randomUUID().toString();
+    private static final String SERVICE_TYPE = "NetworkService";
+    private static final String GLOBAL_CUSTOMER_ID = UUID.randomUUID().toString();
+    private static final String EXPECTED_LOCATION_URL = "http://etsi-so-ns-lcm-manager-service:9095"
+            + "/so/so-etsi-nfvo-ns-lcm/v1/" + "api/nslcm/v1/ns_instances/" + RANDOM_NS_INST_ID;
+
     @LocalServerPort
     private int port;
 
     private TestRestTemplate testRestTemplate;
 
+    @Autowired
+    private GsonProvider gsonProvider;
+
+    @MockBean
+    private JobExecutorService mockedJobExecutorService;
+
     @Before
     public void setUp() {
-        final Gson gson = JSON.createGson().create();
+        final Gson gson = gsonProvider.getGson();
         testRestTemplate = new TestRestTemplate(
                 new RestTemplateBuilder().additionalMessageConverters(new GsonHttpMessageConverter(gson)));
     }
 
     @Test
-    public void testCreateNs_ValidCreateNsRequest() {
+    public void testCreateNs_ValidCreateNsRequest() throws URISyntaxException {
+
+        final CreateNsRequest createNsRequest = getCreateNsRequest();
+
+        when(mockedJobExecutorService.runCreateNsJob(eq(createNsRequest), eq(GLOBAL_CUSTOMER_ID), eq(SERVICE_TYPE)))
+                .thenReturn(new NsInstancesNsInstance().id(RANDOM_NS_INST_ID));
+
         final String baseUrl = getNsLcmBaseUrl() + "/ns_instances";
         final HttpHeaders headers = new HttpHeaders();
-        headers.add(Constants.HTTP_GLOBAL_CUSTOMER_ID_HTTP_HEADER_PARM_NAME, "GLOBAL_CUSTOMER_ID");
-        final HttpEntity<?> request = new HttpEntity<>(getCreateNsRequest(), headers);
-        final ResponseEntity<Void> responseEntity =
-                testRestTemplate.exchange(baseUrl, HttpMethod.POST, request, Void.class);
-        assertEquals(HttpStatus.NOT_IMPLEMENTED, responseEntity.getStatusCode());
+        headers.add(Constants.HTTP_GLOBAL_CUSTOMER_ID_HTTP_HEADER_PARM_NAME, GLOBAL_CUSTOMER_ID);
+        final HttpEntity<?> request = new HttpEntity<>(createNsRequest, headers);
+        final ResponseEntity<NsInstancesNsInstance> responseEntity =
+                testRestTemplate.exchange(baseUrl, HttpMethod.POST, request, NsInstancesNsInstance.class);
+        assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
+        assertTrue(responseEntity.hasBody());
+        assertNotNull(responseEntity.getBody());
+
+        final HttpHeaders httpHeaders = responseEntity.getHeaders();
+        assertTrue(httpHeaders.containsKey(HttpHeaders.LOCATION));
+        final List<String> actual = httpHeaders.get(HttpHeaders.LOCATION);
+        assertEquals(1, actual.size());
+        assertEquals(EXPECTED_LOCATION_URL, actual.get(0));
+    }
+
+    @Test
+    public void testCreateNs_createNsRequest_nsRequestProcessingExceptionThrown_returnInlineResponse400()
+            throws URISyntaxException {
+
+        final CreateNsRequest createNsRequest = getCreateNsRequest();
+
+        final String message = "Unable to process request";
+        when(mockedJobExecutorService.runCreateNsJob(eq(createNsRequest), eq(GLOBAL_CUSTOMER_ID), eq(SERVICE_TYPE)))
+                .thenThrow(new NsRequestProcessingException(message, new InlineResponse400().detail(message)));
+
+        final String baseUrl = getNsLcmBaseUrl() + "/ns_instances";
+        final HttpHeaders headers = new HttpHeaders();
+        headers.add(Constants.HTTP_GLOBAL_CUSTOMER_ID_HTTP_HEADER_PARM_NAME, GLOBAL_CUSTOMER_ID);
+        final HttpEntity<?> request = new HttpEntity<>(createNsRequest, headers);
+        final ResponseEntity<InlineResponse400> responseEntity =
+                testRestTemplate.exchange(baseUrl, HttpMethod.POST, request, InlineResponse400.class);
+        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+        assertTrue(responseEntity.hasBody());
+        assertNotNull(responseEntity.getBody());
+
+        final InlineResponse400 body = responseEntity.getBody();
+        assertEquals(message, body.getDetail());
+
+    }
+
+    @Test
+    public void testCreateNs_createNsRequest_exceptionThrown_returnInlineResponse400() throws URISyntaxException {
+
+        final CreateNsRequest createNsRequest = getCreateNsRequest();
+
+        final String message = "Unable to process request";
+        when(mockedJobExecutorService.runCreateNsJob(eq(createNsRequest), eq(GLOBAL_CUSTOMER_ID), eq(SERVICE_TYPE)))
+                .thenThrow(new RuntimeException(message));
+
+        final String baseUrl = getNsLcmBaseUrl() + "/ns_instances";
+        final HttpHeaders headers = new HttpHeaders();
+        headers.add(Constants.HTTP_GLOBAL_CUSTOMER_ID_HTTP_HEADER_PARM_NAME, GLOBAL_CUSTOMER_ID);
+        final HttpEntity<?> request = new HttpEntity<>(createNsRequest, headers);
+        final ResponseEntity<InlineResponse400> responseEntity =
+                testRestTemplate.exchange(baseUrl, HttpMethod.POST, request, InlineResponse400.class);
+        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode());
+        assertTrue(responseEntity.hasBody());
+        assertNotNull(responseEntity.getBody());
+
+        final InlineResponse400 body = responseEntity.getBody();
+        assertEquals(message, body.getDetail());
+
     }
 
     @Test
@@ -116,7 +203,7 @@ public class NsLifecycleManagementControllerTest {
     }
 
     private CreateNsRequest getCreateNsRequest() {
-        return new CreateNsRequest().nsdId(UUID.randomUUID().toString());
+        return new CreateNsRequest().nsdId(RANDOM_NS_INST_ID);
     }
 
     private String getNsLcmBaseUrl() {
index 255ed2f..6c8a799 100644 (file)
@@ -18,11 +18,24 @@ spring:
       baseline-on-migrate: false
    datasource:
       hikari:
+         camunda:
+            jdbcUrl: jdbc:h2:mem:example-simple;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+            driver-class-name: org.h2.Driver
+            pool-name: ns-lcm-bpmn-pool
+            registerMbeans: true
          nfvo:
-            jdbcUrl: jdbc:h2:mem:NFVO;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATe SCHEMA IF NOT EXISTS NFVO;
+            jdbcUrl: jdbc:h2:mem:NFVO;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS NFVO;
             driver-class-name: org.h2.Driver
             pool-name: ns-lcm-bpmn-pool
             registerMbeans: true
    jpa:
       hibernate:
-         ddl-auto: none
\ No newline at end of file
+         ddl-auto: none
+logging:
+   level:
+      org.reflections.Reflections: ERROR
+etsi-catalog-manager:
+   base:
+      endpoint: http://modeling-etsicatalog.onap:8806/api
+etsi-so-ns-lcm-manager:
+   endpoint: http://etsi-so-ns-lcm-manager-service:9095
\ No newline at end of file