summaryrefslogtreecommitdiffstats
path: root/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main
diff options
context:
space:
mode:
authorwaqas.ikram <waqas.ikram@est.tech>2023-01-23 11:58:29 +0000
committerwaqas.ikram <waqas.ikram@est.tech>2023-01-23 11:58:40 +0000
commitbd591af78a4ab97af4f65d6b7094d9c60f7879c4 (patch)
treed16a23906298c6b1875712ab2acae64716531ff5 /so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main
parent80d8598e1013ddee747957adf7d96ec7fb901f0b (diff)
Adding common classes for workflows
Change-Id: Id86256ee21ee8c78da82ae3141f7936191593597 Issue-ID: SO-4068 Signed-off-by: waqas.ikram <waqas.ikram@est.tech>
Diffstat (limited to 'so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main')
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaCustomConfiguration.java49
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaDatabaseConfiguration.java89
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaVariableNameConstants.java53
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/Constants.java45
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/GsonProvider.java45
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/AsRequestProcessingException.java55
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/BasicAuthConfigException.java37
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/FileNotFoundInCsarException.java44
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/PropertyNotFoundException.java44
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/SdcPackageRequestFailureException.java42
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java34
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java108
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java68
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java211
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesResource.java209
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/DeploymentItem.java143
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcClientConfigurationProvider.java79
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPackageParser.java201
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPropertiesConstants.java37
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcHttpRestServiceProviderConfiguration.java108
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProvider.java33
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProviderImpl.java80
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/JobExecutorService.java376
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowExecutorService.java59
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowQueryService.java111
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java59
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/OffsetDateTimeTypeAdapter.java68
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/PropertiesToYamlConverter.java59
-rw-r--r--so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/META-INF/services/org.onap.so.client.RestProperties1
29 files changed, 2547 insertions, 0 deletions
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaCustomConfiguration.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaCustomConfiguration.java
new file mode 100644
index 0000000..765d25b
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaCustomConfiguration.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows;
+
+import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.AS_WORKFLOW_ENGINE;
+import static org.onap.so.cnfm.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, AS_WORKFLOW_ENGINE);
+ processEngineConfiguration.setDeploymentTenantId(TENANT_ID);
+ processEngineConfiguration.setDeploymentName(AS_WORKFLOW_ENGINE);
+ super.preInit(processEngineConfiguration);
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaDatabaseConfiguration.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaDatabaseConfiguration.java
new file mode 100644
index 0000000..cc8bb01
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaDatabaseConfiguration.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows;
+
+
+import static org.slf4j.LoggerFactory.getLogger;
+import javax.sql.DataSource;
+import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration;
+import org.camunda.bpm.spring.boot.starter.util.SpringBootProcessEnginePlugin;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.jmx.export.MBeanExporter;
+import org.springframework.transaction.PlatformTransactionManager;
+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
+public class CamundaDatabaseConfiguration {
+
+ private static final String CAMUNDA_TRANSACTION_MANAGER_BEAN_NAME = "camundaTransactionManager";
+
+ private static final String CAMUNDA_DATA_SOURCE_BEAN_NAME = "camundaBpmDataSource";
+
+ private static final Logger logger = getLogger(CamundaDatabaseConfiguration.class);
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.hikari.camunda")
+ public HikariConfig camundaDbConfig() {
+ logger.debug("Creating Camunda HikariConfig bean ... ");
+ return new HikariConfig();
+ }
+
+ @Bean(name = CAMUNDA_DATA_SOURCE_BEAN_NAME)
+ public DataSource camundaDataSource(@Autowired(required = false) final MBeanExporter mBeanExporter) {
+ if (mBeanExporter != null) {
+ mBeanExporter.addExcludedBean(CAMUNDA_DATA_SOURCE_BEAN_NAME);
+ }
+ logger.debug("Creating Camunda HikariDataSource bean ... ");
+ final HikariConfig hikariConfig = this.camundaDbConfig();
+ return new HikariDataSource(hikariConfig);
+ }
+
+ @Bean(name = CAMUNDA_TRANSACTION_MANAGER_BEAN_NAME)
+ public PlatformTransactionManager camundaTransactionManager(
+ @Qualifier(CAMUNDA_DATA_SOURCE_BEAN_NAME) final DataSource dataSource) {
+ return new DataSourceTransactionManager(dataSource);
+ }
+
+ @Bean
+ public SpringBootProcessEnginePlugin transactionManagerProcessEnginePlugin(
+ @Qualifier(CAMUNDA_TRANSACTION_MANAGER_BEAN_NAME) final PlatformTransactionManager camundaTransactionManager) {
+ return new SpringBootProcessEnginePlugin() {
+ @Override
+ public void preInit(final SpringProcessEngineConfiguration processEngineConfiguration) {
+ logger.info("Setting Camunda TransactionManager ...");
+ processEngineConfiguration.setTransactionManager(camundaTransactionManager);
+
+ }
+ };
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaVariableNameConstants.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaVariableNameConstants.java
new file mode 100644
index 0000000..47c5795
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/CamundaVariableNameConstants.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class CamundaVariableNameConstants {
+
+ public static final String AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME = "asDeploymentItemInstId";
+ public static final String KUBE_KINDS_RESULT_PARAM_NAME = "kubeKindsResult";
+ public static final String KUBE_CONFIG_FILE_PATH_PARAM_NAME = "kubeConfigFilePath";
+ public static final String KUBE_KINDS_PARAM_NAME = "kubeKinds";
+ public static final String KIND_PARAM_NAME = "kind";
+ public static final String RELEASE_NAME_PARAM_NAME = "releaseName";
+ public static final String JOB_ID_PARAM_NAME = "jobId";
+ public static final String JOB_BUSINESS_KEY_PARAM_NAME = "jobBusinessKey";
+ public static final String CREATE_AS_REQUEST_PARAM_NAME = "createAsRequest";
+
+ public static final String AS_PACKAGE_MODEL_PARAM_NAME = "AsPackageModel";
+ public static final String AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME = "AsWorkflowProcessingException";
+ public static final String CREATE_AS_RESPONSE_PARAM_NAME = "createAsResponse";
+
+ public static final String INSTANTIATE_AS_REQUEST_PARAM_NAME = "instantiateAsRequest";
+ public static final String AS_INSTANCE_ID_PARAM_NAME = "AsInstanceId";
+ public static final String OCC_ID_PARAM_NAME = "occId";
+
+ public static final String DEPLOYMENT_ITEM_INSTANTIATE_REQUESTS = "deploymentItemInstantiateRequests";
+ public static final String DEPLOYMENT_ITEM_TERMINATE_REQUESTS = "deploymentItemTerminateRequests";
+
+ public static final String TERMINATE_AS_REQUEST_PARAM_NAME = "terminateAsRequest";
+
+ private CamundaVariableNameConstants() {}
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/Constants.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/Constants.java
new file mode 100644
index 0000000..45c36be
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/Constants.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class Constants {
+
+ public static final String TENANT_ID = "as-workflow-engine-tenant";
+ public static final String AS_WORKFLOW_ENGINE = "AS-WORKFLOW-ENGINE";
+ public static final String CREATE_AS_WORKFLOW_NAME = "CreateAs";
+ public static final String INSTANTIATE_AS_WORKFLOW_NAME = "InstantiateAs";
+ public static final String TERMINATE_AS_WORKFLOW_NAME = "TerminateAs";
+ public static final String DELETE_AS_WORKFLOW_NAME = "DeleteAs";
+
+ public static final String KIND_STATEFUL_SET = "StatefulSet";
+ public static final String KIND_DAEMON_SET = "DaemonSet";
+ public static final String KIND_REPLICA_SET = "ReplicaSet";
+ public static final String KIND_DEPLOYMENT = "Deployment";
+ public static final String KIND_SERVICE = "Service";
+ public static final String KIND_POD = "Pod";
+ public static final String KIND_JOB = "Job";
+
+ private Constants() {}
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/GsonProvider.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/GsonProvider.java
new file mode 100644
index 0000000..486c528
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/GsonProvider.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import org.onap.so.cnfm.lcm.bpmn.flows.utils.LocalDateTimeTypeAdapter;
+import org.onap.so.cnfm.lcm.bpmn.flows.utils.OffsetDateTimeTypeAdapter;
+import org.springframework.stereotype.Component;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Component
+public class GsonProvider {
+
+ private final OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
+
+ public Gson getGson() {
+ return new GsonBuilder().registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter)
+ .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()).create();
+ }
+
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/AsRequestProcessingException.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/AsRequestProcessingException.java
new file mode 100644
index 0000000..991c3c3
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/AsRequestProcessingException.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.exceptions;
+
+import org.onap.so.cnfm.lcm.model.ErrorDetails;
+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 AsRequestProcessingException extends RuntimeException {
+
+ private static final long serialVersionUID = 66862444537194516L;
+ private final ErrorDetails errorDetails;
+
+ public AsRequestProcessingException(final String message) {
+ super(message);
+ errorDetails = null;
+ }
+
+ public AsRequestProcessingException(final String message, final ErrorDetails errorContents) {
+ super(message);
+ this.errorDetails = errorContents;
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+
+ public ErrorDetails getErrorDetails() {
+ return errorDetails;
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/BasicAuthConfigException.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/BasicAuthConfigException.java
new file mode 100644
index 0000000..4b9bfb1
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/BasicAuthConfigException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.exceptions;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ */
+public class BasicAuthConfigException extends RuntimeException {
+
+ private static final long serialVersionUID = -6317913344782441364L;
+
+ public BasicAuthConfigException(final String message) {
+ super(message);
+ }
+
+ public BasicAuthConfigException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/FileNotFoundInCsarException.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/FileNotFoundInCsarException.java
new file mode 100644
index 0000000..4bad50c
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/FileNotFoundInCsarException.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.exceptions;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class FileNotFoundInCsarException extends RuntimeException {
+
+ private static final long serialVersionUID = -3294117029811603499L;
+
+ public FileNotFoundInCsarException(final String message) {
+ super(message);
+ }
+
+ public FileNotFoundInCsarException(final String message, final Throwable cause) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/PropertyNotFoundException.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/PropertyNotFoundException.java
new file mode 100644
index 0000000..908a04d
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/PropertyNotFoundException.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.exceptions;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class PropertyNotFoundException extends RuntimeException {
+
+ private static final long serialVersionUID = 684205374040870233L;
+
+ public PropertyNotFoundException(final String message) {
+ super(message);
+ }
+
+ public PropertyNotFoundException(final String message, final Throwable cause) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/SdcPackageRequestFailureException.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/SdcPackageRequestFailureException.java
new file mode 100644
index 0000000..d33c51f
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/exceptions/SdcPackageRequestFailureException.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.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 SdcPackageRequestFailureException extends RuntimeException {
+
+ private static final long serialVersionUID = 5816306976965772635L;
+
+ public SdcPackageRequestFailureException(final String message) {
+ super(message);
+ }
+
+ public SdcPackageRequestFailureException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java
new file mode 100644
index 0000000..aceafe7
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.cnfm.lcm.bpmn.flows.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-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java
new file mode 100644
index 0000000..b0986d8
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai;
+
+import org.onap.aaiclient.client.aai.AAIProperties;
+import org.onap.aaiclient.client.aai.AAIVersion;
+import org.onap.so.client.CacheProperties;
+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;
+ private final Long readTimeout;
+ private final Long connectionTimeout;
+ private final boolean enableCaching;
+ private final Long cacheMaxAge;
+
+ 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");
+ this.readTimeout = context.getEnvironment().getProperty("aai.readTimeout", Long.class, 60000L);
+ this.connectionTimeout = context.getEnvironment().getProperty("aai.connectionTimeout", Long.class, 60000L);
+ this.enableCaching = context.getEnvironment().getProperty("aai.caching.enabled", Boolean.class, false);
+ this.cacheMaxAge = context.getEnvironment().getProperty("aai.caching.maxAge", Long.class, 60000L);
+ }
+
+ @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;
+ }
+
+ @Override
+ public Long getReadTimeout() {
+ return this.readTimeout;
+ }
+
+ @Override
+ public Long getConnectionTimeout() {
+ return this.connectionTimeout;
+ }
+
+ @Override
+ public boolean isCachingEnabled() {
+ return this.enableCaching;
+ }
+
+ @Override
+ public CacheProperties getCacheProperties() {
+ return new AAICacheProperties() {
+ @Override
+ public Long getMaxAge() {
+ return cacheMaxAge;
+ }
+ };
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java
new file mode 100644
index 0000000..fae677d
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java
@@ -0,0 +1,68 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai;
+
+import java.util.List;
+import java.util.Optional;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.K8SResource;
+import org.onap.aai.domain.yang.VfModule;
+import org.onap.so.beans.nsmf.OrchestrationStatusEnum;
+import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesResource;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface AaiServiceProvider {
+
+ 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);
+
+ void deleteGenericVnf(final String vnfId);
+
+ void updateGenericVnf(final String vnfId, final GenericVnf vnf);
+
+ void createVfModule(final String vnfId, final String vfModuleId, final VfModule vfModule);
+
+ void createK8sResource(final String k8sResourceId, final String cloudOwner, final String cloudRegion,
+ final String tenantId, K8SResource k8sResource);
+
+ void connectK8sResourceToVfModule(final String k8sResourceId, final String cloudOwner, final String cloudRegion,
+ final String tenantId, final String vnfId, final String vfModuleId);
+
+ void connectK8sResourceToGenericVnf(final String k8sResourceId, final String cloudOwner, final String cloudRegion,
+ final String tenantId, final String vnfId);
+
+ List<KubernetesResource> getK8sResources(final String vnfId, final String vfModuleId);
+
+ void deleteK8SResource(final String k8sResourceId, final String cloudOwner, final String cloudRegion,
+ final String tenantId);
+
+ void deleteVfModule(final String vnfId, final String vfModuleId);
+
+ boolean updateGenericVnfStatus(final String vnfId, final OrchestrationStatusEnum status);
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java
new file mode 100644
index 0000000..4f5ec8d
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java
@@ -0,0 +1,211 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.K8SResource;
+import org.onap.aai.domain.yang.VfModule;
+import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
+import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
+import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
+import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
+import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types;
+import org.onap.so.beans.nsmf.OrchestrationStatusEnum;
+import org.onap.so.cnfm.lcm.bpmn.flows.GsonProvider;
+import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.google.gson.Gson;
+
+/**
+ * @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;
+ private final Gson gson;
+
+ @Autowired
+ public AaiServiceProviderImpl(final AaiClientProvider aaiClientProvider, final GsonProvider gsonProvider) {
+ this.aaiClientProvider = aaiClientProvider;
+ this.gson = gsonProvider.getGson();
+ }
+
+ @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(AAIFluentTypeBuilder.network().genericVnf(vnfId));
+ final AAIResourceUri serviceInstanceURI =
+ AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(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(
+ AAIFluentTypeBuilder.cloudInfrastructure().cloudRegion(cloudOwner, cloudRegion).tenant(tenantId));
+ final AAIResourceUri genericVnfURI =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId));
+ aaiClientProvider.getAaiClient().connect(tenantURI, genericVnfURI);
+ }
+
+ @Override
+ public Optional<GenericVnf> getGenericVnf(final String vnfId) {
+ return aaiClientProvider.getAaiClient().get(GenericVnf.class,
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId)));
+ }
+
+ @Override
+ public void deleteGenericVnf(final String vnfId) {
+ logger.info("Deleting GenericVnf with id: {} from AAI.", vnfId);
+ final AAIResourceUri aaiResourceUri =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId));
+ aaiClientProvider.getAaiClient().delete(aaiResourceUri);
+ }
+
+ @Override
+ public void updateGenericVnf(final String vnfId, final GenericVnf vnf) {
+ logger.info("Updating GenericVnf of id: {} in AAI.", vnfId);
+ final AAIResourceUri aaiResourceUri =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId));
+ aaiClientProvider.getAaiClient().update(aaiResourceUri, vnf);
+ }
+
+ @Override
+ public void createVfModule(final String vnfId, final String vfModuleId, final VfModule vfModule) {
+ logger.info("Creating VfModule in AAI: {}", vfModule);
+
+ final AAIResourceUri vfModuleURI =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId).vfModule(vfModuleId));
+ aaiClientProvider.getAaiClient().createIfNotExists(vfModuleURI, Optional.of(vfModule));
+
+ }
+
+ @Override
+ public void createK8sResource(final String k8sResourceId, final String cloudOwner, final String cloudRegion,
+ final String tenantId, final K8SResource k8sResource) {
+ logger.info("Creating K8SResource in AAI: {} using {}/{}/{}/{}", k8sResource, k8sResourceId, cloudOwner,
+ cloudRegion, tenantId);
+
+ final AAIResourceUri k8sResourceURI = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
+ .cloudRegion(cloudOwner, cloudRegion).tenant(tenantId).k8sResource(k8sResourceId));
+
+ final String payload = gson.toJson(k8sResource);
+ logger.debug("Creating K8sResource in A&AI: {}", payload);
+
+ aaiClientProvider.getAaiClient().createIfNotExists(k8sResourceURI, Optional.of(payload));
+
+ }
+
+ @Override
+ public void connectK8sResourceToVfModule(final String k8sResourceId, final String cloudOwner,
+ final String cloudRegion, final String tenantId, final String vnfId, final String vfModuleId) {
+ logger.info("Connecting K8sResource {}/{}/{}/{} to VF Moudle {}/{} in AAI", cloudOwner, cloudRegion, tenantId,
+ k8sResourceId, vnfId, vfModuleId);
+
+ final AAIResourceUri k8sResourceURI = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
+ .cloudRegion(cloudOwner, cloudRegion).tenant(tenantId).k8sResource(k8sResourceId));
+
+ final AAIResourceUri vfModuleURI =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId).vfModule(vfModuleId));
+ aaiClientProvider.getAaiClient().connect(k8sResourceURI, vfModuleURI);
+
+ }
+
+ @Override
+ public void connectK8sResourceToGenericVnf(final String k8sResourceId, final String cloudOwner,
+ final String cloudRegion, final String tenantId, final String vnfId) {
+ logger.info("Connecting K8sResource {}/{}/{}/{} to Generic Vnf {} in AAI", cloudOwner, cloudRegion, tenantId,
+ k8sResourceId, vnfId);
+ final AAIResourceUri k8sResourceURI = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
+ .cloudRegion(cloudOwner, cloudRegion).tenant(tenantId).k8sResource(k8sResourceId));
+ final AAIResourceUri genericVnfURI =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId));
+ aaiClientProvider.getAaiClient().connect(k8sResourceURI, genericVnfURI);
+
+ }
+
+ @Override
+ public List<KubernetesResource> getK8sResources(final String vnfId, final String vfModuleId) {
+ logger.info("Getting K8S resources related to VfModule: {} from AAI", vfModuleId);
+ final AAIResourceUri vfModuleURI =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId).vfModule(vfModuleId));
+ final AAIResultWrapper vfModuleInstance = aaiClientProvider.getAaiClient().get(vfModuleURI);
+ if (vfModuleInstance.hasRelationshipsTo(Types.K8S_RESOURCE)
+ && vfModuleInstance.getRelationships().isPresent()) {
+ logger.debug("VfModule has relations of type K8SResource");
+ return vfModuleInstance.getRelationships().get().getByType(Types.K8S_RESOURCE).stream()
+ .map(relation -> relation.asBean(KubernetesResource.class)).filter(Optional::isPresent)
+ .map(Optional::get).collect(Collectors.toList());
+ }
+ logger.info("No K8S resources found for VfModule :{}", vfModuleId);
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void deleteK8SResource(final String k8sResourceId, final String cloudOwner, final String cloudRegion,
+ final String tenantId) {
+ logger.info("Deleting K8sResource {} from AAI", k8sResourceId);
+
+ final AAIResourceUri k8sResourceURI = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
+ .cloudRegion(cloudOwner, cloudRegion).tenant(tenantId).k8sResource(k8sResourceId));
+ aaiClientProvider.getAaiClient().deleteIfExists(k8sResourceURI);
+
+ logger.info("K8S resource removed from AAI using URI: {}", k8sResourceURI);
+ }
+
+ @Override
+ public void deleteVfModule(final String vnfId, final String vfModuleId) {
+ logger.info("Deleting VfModule {} from AAI", vfModuleId);
+
+ final AAIResourceUri vfModuleURI =
+ AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId).vfModule(vfModuleId));
+ aaiClientProvider.getAaiClient().deleteIfExists(vfModuleURI);
+ logger.info("VfModule deleted from AAI using URI: {}", vfModuleId);
+ }
+
+ @Override
+ public boolean updateGenericVnfStatus(final String vnfId, final OrchestrationStatusEnum status) {
+ logger.info("Updating GenericVnf status to deactivated for vnfID: {}", vnfId);
+ final Optional<GenericVnf> optionalVnf = getGenericVnf(vnfId);
+ if (optionalVnf.isPresent()) {
+ final GenericVnf vnf = optionalVnf.get();
+ vnf.setOrchestrationStatus(status.getValue());
+ updateGenericVnf(vnfId, vnf);
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesResource.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesResource.java
new file mode 100644
index 0000000..7ec50f0
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesResource.java
@@ -0,0 +1,209 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes;
+
+import static org.onap.so.cnfm.lcm.database.beans.utils.Utils.toIndentedString;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class KubernetesResource implements Serializable {
+
+ private static final long serialVersionUID = -4342437130757578686L;
+
+ private String id;
+ private String name;
+ private String group;
+ private String version;
+ private String kind;
+ private String namespace;
+ private String selflink;
+ private String resourceVersion;
+ private List<String> labels;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(final String id) {
+ this.id = id;
+ }
+
+ public KubernetesResource id(final String id) {
+ this.id = id;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public KubernetesResource name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(final String group) {
+ this.group = group;
+ }
+
+ public KubernetesResource group(final String group) {
+ this.group = group;
+ return this;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(final String version) {
+ this.version = version;
+ }
+
+ public KubernetesResource version(final String version) {
+ this.version = version;
+ return this;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public void setKind(final String kind) {
+ this.kind = kind;
+ }
+
+ public KubernetesResource kind(final String kind) {
+ this.kind = kind;
+ return this;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(final String namespace) {
+ this.namespace = namespace;
+ }
+
+ public KubernetesResource namespace(final String namespace) {
+ this.namespace = namespace;
+ return this;
+ }
+
+ public String getSelflink() {
+ return selflink;
+ }
+
+ public void setSelflink(final String selflink) {
+ this.selflink = selflink;
+ }
+
+ public KubernetesResource selflink(final String selflink) {
+ this.selflink = selflink;
+ return this;
+ }
+
+ public String getResourceVersion() {
+ return resourceVersion;
+ }
+
+ public void setResourceVersion(final String resourceVersion) {
+ this.resourceVersion = resourceVersion;
+ }
+
+ public KubernetesResource resourceVersion(final String resourceVersion) {
+ this.resourceVersion = resourceVersion;
+ return this;
+ }
+
+ public List<String> getLabels() {
+ return labels;
+ }
+
+ public void setLabels(final List<String> labels) {
+ this.labels = labels;
+ }
+
+ public KubernetesResource labels(final List<String> labels) {
+ this.labels = labels;
+ return this;
+ }
+
+ public KubernetesResource label(final String label) {
+ if (this.labels == null) {
+ this.labels = new ArrayList<>();
+ }
+
+ this.labels.add(label);
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name, group, version, kind, namespace, selflink, resourceVersion, labels);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof KubernetesResource) {
+ final KubernetesResource other = (KubernetesResource) obj;
+ return Objects.equals(id, other.id) && Objects.equals(name, other.name)
+ && Objects.equals(group, other.group) && Objects.equals(version, other.version)
+ && Objects.equals(kind, other.kind) && Objects.equals(namespace, other.namespace)
+ && Objects.equals(selflink, other.selflink)
+ && Objects.equals(resourceVersion, other.resourceVersion) && Objects.equals(labels, other.labels);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class KubernetesResource {\n");
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" group: ").append(toIndentedString(group)).append("\n");
+ sb.append(" version: ").append(toIndentedString(version)).append("\n");
+ sb.append(" kind: ").append(toIndentedString(kind)).append("\n");
+ sb.append(" namespace: ").append(toIndentedString(namespace)).append("\n");
+ sb.append(" selflink: ").append(toIndentedString(selflink)).append("\n");
+ sb.append(" resourceVersion: ").append(toIndentedString(resourceVersion)).append("\n");
+ sb.append(" labels: ").append(toIndentedString(labels)).append("\n");
+
+ sb.append("}");
+ return sb.toString();
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/DeploymentItem.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/DeploymentItem.java
new file mode 100644
index 0000000..1062cb7
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/DeploymentItem.java
@@ -0,0 +1,143 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
+
+import static org.onap.so.cnfm.lcm.database.beans.utils.Utils.toIndentedString;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class DeploymentItem implements Serializable {
+
+ private static final long serialVersionUID = -1974244669409099225L;
+ private String name;
+ private String file;
+ private String itemId;
+ private String deploymentOrder;
+
+ private List<String> lifecycleParameters;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public DeploymentItem name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+
+ public String getFile() {
+ return file;
+ }
+
+ public void setFile(final String file) {
+ this.file = file;
+ }
+
+ public DeploymentItem file(final String file) {
+ this.file = file;
+ return this;
+ }
+
+
+ public String getItemId() {
+ return itemId;
+ }
+
+ public void setItemId(final String itemId) {
+ this.itemId = itemId;
+ }
+
+ public DeploymentItem itemId(final String itemId) {
+ this.itemId = itemId;
+ return this;
+ }
+
+ public String getDeploymentOrder() {
+ return deploymentOrder;
+ }
+
+ public void setDeploymentOrder(String deploymentOrder) {
+ this.deploymentOrder = deploymentOrder;
+ }
+
+ public DeploymentItem deploymentOrder(final String deploymentOrder) {
+ this.deploymentOrder = deploymentOrder;
+ return this;
+ }
+
+
+ public List<String> getLifecycleParameters() {
+ return lifecycleParameters;
+ }
+
+ public void setLifecycleParameters(final List<String> lifecycleParameters) {
+ this.lifecycleParameters = lifecycleParameters;
+ }
+
+ public DeploymentItem lifecycleParameters(final List<String> lifecycleParameters) {
+ this.lifecycleParameters = lifecycleParameters;
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, file, itemId, deploymentOrder, lifecycleParameters);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ if (obj instanceof DeploymentItem) {
+ final DeploymentItem other = (DeploymentItem) obj;
+ return Objects.equals(name, other.name) && Objects.equals(file, other.file)
+ && Objects.equals(itemId, other.itemId) && Objects.equals(deploymentOrder, other.deploymentOrder)
+ && Objects.equals(lifecycleParameters, other.lifecycleParameters);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class DeploymentItem {\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" file: ").append(toIndentedString(file)).append("\n");
+ sb.append(" itemId: ").append(toIndentedString(itemId)).append("\n");
+ sb.append(" deploymentOrder: ").append(toIndentedString(deploymentOrder)).append("\n");
+ sb.append(" lifecycleParameters: ").append(toIndentedString(lifecycleParameters)).append("\n");
+ sb.append("}");
+ return sb.toString();
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcClientConfigurationProvider.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcClientConfigurationProvider.java
new file mode 100644
index 0000000..4ae1d43
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcClientConfigurationProvider.java
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
+
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import org.apache.commons.codec.binary.Base64;
+import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.BasicAuthConfigException;
+import org.onap.so.utils.CryptoUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Configuration
+public class SdcClientConfigurationProvider {
+
+ private static final Logger logger = LoggerFactory.getLogger(SdcClientConfigurationProvider.class);
+
+ @Value("${sdc.username:mso}")
+ private String sdcUsername;
+
+ @Value("${sdc.password:76966BDD3C7414A03F7037264FF2E6C8EEC6C28F2B67F2840A1ED857C0260FEE731D73F47F828E5527125D29FD25D3E0DE39EE44C058906BF1657DE77BF897EECA93BDC07FA64F}")
+ private String sdcPassword;
+
+ @Value("${sdc.key:566B754875657232314F5548556D3665}")
+ private String sdcKey;
+
+ @Value("${sdc.endpoint:https://sdc-be.onap:8443}")
+ private String baseUrl;
+
+ private static String basicAuth = null;
+
+
+ public String getBasicAuth() {
+ if (basicAuth == null) {
+ synchronized (this) {
+ if (basicAuth == null) {
+ try {
+ final String auth = sdcUsername + ":" + CryptoUtils.decrypt(sdcPassword, sdcKey);
+ final byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
+ basicAuth = "Basic " + new String(encodedAuth);
+ } catch (final GeneralSecurityException exception) {
+ logger.error("Unable to process basic auth information", exception);
+ throw new BasicAuthConfigException("Unable to process basic auth information", exception);
+ }
+ }
+ }
+ }
+ return basicAuth;
+ }
+
+ public String getSdcPackageUrl(final String packageId) {
+ return baseUrl + "/sdc/v1/catalog/resources/" + packageId + "/toscaModel";
+
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPackageParser.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPackageParser.java
new file mode 100644
index 0000000..0ade7bf
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPackageParser.java
@@ -0,0 +1,201 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
+
+import static com.google.common.base.Splitter.on;
+import static com.google.common.collect.Iterables.filter;
+import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.APPLICATION_NAME_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.APPLICATION_VERSION_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DEPLOYMENT_ITEMS_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DESCRIPTOR_ID_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.DESCRIPTOR_INVARIANT_ID_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcCsarPropertiesConstants.PROVIDER_PARAM_NAME;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import com.google.gson.JsonArray;
+import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.FileNotFoundInCsarException;
+import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.PropertyNotFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.yaml.snakeyaml.Yaml;
+import com.google.common.io.ByteStreams;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class SdcCsarPackageParser {
+ private static final String TOCSA_METADATA_FILE_PATH = "TOSCA-Metadata/TOSCA.meta";
+ private static final String ENTRY_DEFINITIONS_ENTRY = "Entry-Definitions";
+
+ private static final Logger logger = LoggerFactory.getLogger(SdcCsarPackageParser.class);
+
+ public Map<String, Object> getAsdProperties(final byte[] onapPackage) {
+
+ try (final ByteArrayInputStream stream = new ByteArrayInputStream(onapPackage);
+ final ZipInputStream zipInputStream = new ZipInputStream(stream);) {
+ final String asdLocation = getAsdLocation(zipInputStream);
+ final String onapAsdContent = getFileInZip(zipInputStream, asdLocation).toString();
+ logger.debug("ASD CONTENTS: {}", onapAsdContent);
+ final JsonObject root = new Gson().toJsonTree(new Yaml().load(onapAsdContent)).getAsJsonObject();
+
+ final JsonObject topologyTemplates = child(root, "topology_template");
+ final JsonObject nodeTemplates = child(topologyTemplates, "node_templates");
+ for (final JsonObject child : children(nodeTemplates)) {
+ final String type = childElement(child, "type").getAsString();
+ if ("tosca.nodes.asd".equals(type)) {
+ final JsonObject properties = child(child, "properties");
+ logger.debug("properties: {}", properties.toString());
+ final Map<String, Object> propertiesValues = new HashMap<>();
+ propertiesValues.put(DESCRIPTOR_ID_PARAM_NAME,
+ getStringValue(properties, DESCRIPTOR_ID_PARAM_NAME));
+ propertiesValues.put(DESCRIPTOR_INVARIANT_ID_PARAM_NAME,
+ getStringValue(properties, DESCRIPTOR_INVARIANT_ID_PARAM_NAME));
+ propertiesValues.put(PROVIDER_PARAM_NAME, getStringValue(properties, PROVIDER_PARAM_NAME));
+ propertiesValues.put(APPLICATION_NAME_PARAM_NAME,
+ getStringValue(properties, APPLICATION_NAME_PARAM_NAME));
+ propertiesValues.put(APPLICATION_VERSION_PARAM_NAME,
+ getStringValue(properties, APPLICATION_VERSION_PARAM_NAME));
+ propertiesValues.put(DEPLOYMENT_ITEMS_PARAM_NAME, getDeploymentItems(child));
+
+ return propertiesValues;
+
+ }
+ }
+
+
+ } catch (final Exception exception) {
+ throw new IllegalArgumentException("Unable to parser CSAR package", exception);
+ }
+ return Collections.emptyMap();
+ }
+
+ private String getStringValue(final JsonObject properties, final String key) {
+ final JsonElement element = properties.get(key);
+ if (element != null && element.isJsonPrimitive()) {
+ return element.getAsString();
+ }
+ logger.warn("'{}' value is not Primitive or null val:{}", key, element != null ? element.toString() : null);
+ return null;
+ }
+
+ private List<DeploymentItem> getDeploymentItems(final JsonObject child) {
+ final List<DeploymentItem> items = new ArrayList<>();
+
+ final JsonObject artifacts = child(child, "artifacts");
+ artifacts.keySet().forEach(key -> {
+ final JsonObject element = artifacts.getAsJsonObject(key);
+ final JsonObject artifactsProperties = child(element, "properties");
+ final List<String> lcp = getLifecycleParameters(artifactsProperties);
+ items.add(new DeploymentItem().name(key).itemId(getStringValue(artifactsProperties, "itemId"))
+ .file(getStringValue(element, "file"))
+ .deploymentOrder(getStringValue(artifactsProperties, "deployment_order")).lifecycleParameters(lcp));
+ });
+ return items;
+ }
+
+ private List<String> getLifecycleParameters(final JsonObject artifactsProperties) {
+ final JsonArray lcParameters = childElement(artifactsProperties, "lifecycle_parameters").getAsJsonArray();
+ final List<String> lifecycleParameters = new ArrayList<>();
+ if(lcParameters != null) {
+ final Iterator<JsonElement> it = lcParameters.iterator();
+ while(it.hasNext()){
+ lifecycleParameters.add(it.next().getAsString());
+ }
+ }
+ return lifecycleParameters;
+ }
+
+ private String getAsdLocation(final ZipInputStream zipInputStream) throws IOException {
+
+ try (final ByteArrayOutputStream fileContent = getFileInZip(zipInputStream, TOCSA_METADATA_FILE_PATH);) {
+ final String toscaMetadata = new String(fileContent.toByteArray());
+ if (!toscaMetadata.isEmpty()) {
+ final String entry =
+ filter(on("\n").split(toscaMetadata), line -> line.contains(ENTRY_DEFINITIONS_ENTRY)).iterator()
+ .next();
+ return entry.replace(ENTRY_DEFINITIONS_ENTRY + ":", "").trim();
+ }
+ final String message = "Unable to find valid Tosca Path";
+ logger.error(message);
+ throw new FileNotFoundInCsarException(message);
+ }
+ }
+
+ public ByteArrayOutputStream getFileInZip(final ZipInputStream zipInputStream, final String path)
+ throws IOException {
+ ZipEntry zipEntry;
+ final Set<String> items = new HashSet<>();
+ while ((zipEntry = zipInputStream.getNextEntry()) != null) {
+ items.add(zipEntry.getName());
+ if (zipEntry.getName().matches(path)) {
+ final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ByteStreams.copy(zipInputStream, byteArrayOutputStream);
+ return byteArrayOutputStream;
+ }
+ }
+ logger.error("Unable to find the {} in archive found: {}", path, items);
+ throw new NoSuchElementException("Unable to find the " + path + " in archive found: " + items);
+ }
+
+ private JsonObject child(final JsonObject parent, final String name) {
+ return childElement(parent, name).getAsJsonObject();
+ }
+
+ private JsonElement childElement(final JsonObject parent, final String name) {
+ final JsonElement child = parent.get(name);
+ if (child == null) {
+ final String message = "Missing child " + name;
+ logger.error(message);
+ throw new PropertyNotFoundException(message);
+ }
+ return child;
+ }
+
+ private Collection<JsonObject> children(final JsonObject parent) {
+ final ArrayList<JsonObject> childElements = new ArrayList<>();
+ parent.keySet().stream().forEach(childKey -> {
+ if (parent.get(childKey).isJsonObject()) {
+ childElements.add(parent.get(childKey).getAsJsonObject());
+ }
+ });
+ return childElements;
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPropertiesConstants.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPropertiesConstants.java
new file mode 100644
index 0000000..40a0d0d
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcCsarPropertiesConstants.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class SdcCsarPropertiesConstants {
+ public static final String DEPLOYMENT_ITEMS_PARAM_NAME = "deployment_items";
+ public static final String APPLICATION_VERSION_PARAM_NAME = "application_version";
+ public static final String APPLICATION_NAME_PARAM_NAME = "application_name";
+ public static final String PROVIDER_PARAM_NAME = "provider";
+ public static final String DESCRIPTOR_INVARIANT_ID_PARAM_NAME = "descriptor_invariant_id";
+ public static final String DESCRIPTOR_ID_PARAM_NAME = "descriptor_id";
+
+ private SdcCsarPropertiesConstants() {}
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcHttpRestServiceProviderConfiguration.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcHttpRestServiceProviderConfiguration.java
new file mode 100644
index 0000000..f727e07
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcHttpRestServiceProviderConfiguration.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
+
+import java.util.Iterator;
+import javax.net.ssl.SSLContext;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClients;
+import org.onap.logging.filter.spring.SpringClientPayloadFilter;
+import org.onap.so.cnfm.lcm.bpmn.flows.GsonProvider;
+import org.onap.so.configuration.rest.HttpComponentsClientConfiguration;
+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.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+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;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Configuration
+public class SdcHttpRestServiceProviderConfiguration {
+
+ private static final Logger logger = LoggerFactory.getLogger(SdcHttpRestServiceProviderConfiguration.class);
+
+ public static final String SDC_REST_TEMPLATE_CLIENT_BEAN = "SdcRestTemplateClientBean";
+ public static final String SDC_HTTP_REST_SERVICE_PROVIDER_BEAN = "SdcHttpRestServiceProviderBean";
+
+ @Autowired
+ private GsonProvider gsonProvider;
+
+ @Bean
+ @Qualifier(SDC_REST_TEMPLATE_CLIENT_BEAN)
+ public RestTemplate sdcAdapterRestTemplate(
+ @Autowired final HttpComponentsClientConfiguration httpComponentsClientConfiguration) {
+
+ final HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
+ httpComponentsClientConfiguration.httpComponentsClientHttpRequestFactory();
+
+ final RestTemplate restTemplate =
+ new RestTemplate(new BufferingClientHttpRequestFactory(clientHttpRequestFactory));
+ restTemplate.getInterceptors().add(new SOSpringClientFilter());
+ restTemplate.getInterceptors().add((new SpringClientPayloadFilter()));
+ return restTemplate;
+
+ }
+
+ @Bean
+ @Qualifier(SDC_HTTP_REST_SERVICE_PROVIDER_BEAN)
+ public HttpRestServiceProvider sdcHttpRestServiceProvider(
+ @Qualifier(SDC_REST_TEMPLATE_CLIENT_BEAN) @Autowired final RestTemplate restTemplate) {
+
+ try {
+ logger.info("Setting SSLConnectionSocketFactory with Default SSL ...");
+ final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(SSLContext.getDefault());
+ final HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
+ final HttpComponentsClientHttpRequestFactory factory =
+ new HttpComponentsClientHttpRequestFactory(httpClient);
+ restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(factory));
+ } catch (final Exception exception) {
+ logger.error("Error reading truststore, TLS connection to SDC will fail.", exception);
+ }
+ setGsonMessageConverter(restTemplate);
+
+
+ return new HttpRestServiceProviderImpl(restTemplate);
+ }
+
+ private 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-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProvider.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProvider.java
new file mode 100644
index 0000000..f75d5f5
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProvider.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
+
+import java.util.Optional;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface SdcPackageProvider {
+
+ Optional<byte[]> getSdcResourcePackage(final String packageId);
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProviderImpl.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProviderImpl.java
new file mode 100644
index 0000000..5e69661
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/sdc/SdcPackageProviderImpl.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc;
+
+import static org.onap.so.cnfm.lcm.bpmn.flows.extclients.sdc.SdcHttpRestServiceProviderConfiguration.SDC_HTTP_REST_SERVICE_PROVIDER_BEAN;
+import java.util.Optional;
+import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.SdcPackageRequestFailureException;
+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.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class SdcPackageProviderImpl implements SdcPackageProvider {
+ private static final Logger logger = LoggerFactory.getLogger(SdcPackageProviderImpl.class);
+ private final SdcClientConfigurationProvider sdcClientConfigurationProvider;
+ private final HttpRestServiceProvider httpServiceProvider;
+ private static final String SERVICE_NAME = "SO-CNFM";
+
+ @Autowired
+ public SdcPackageProviderImpl(final SdcClientConfigurationProvider sdcClientConfigurationProvider,
+ @Qualifier(SDC_HTTP_REST_SERVICE_PROVIDER_BEAN) final HttpRestServiceProvider httpServiceProvider) {
+ this.sdcClientConfigurationProvider = sdcClientConfigurationProvider;
+ this.httpServiceProvider = httpServiceProvider;
+ }
+
+ @Override
+ public Optional<byte[]> getSdcResourcePackage(final String packageId) {
+ try {
+ final HttpHeaders headers = new HttpHeaders();
+ headers.add(HttpHeaders.AUTHORIZATION, sdcClientConfigurationProvider.getBasicAuth());
+ headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM_VALUE);
+ headers.add("X-ECOMP-InstanceID", SERVICE_NAME);
+ headers.add("X-FromAppId", SERVICE_NAME);
+
+ logger.info("Will retrieve resource package with id: {} from SDC", packageId);
+ final String url = sdcClientConfigurationProvider.getSdcPackageUrl(packageId);
+
+ final ResponseEntity<byte[]> response = httpServiceProvider.getHttpResponse(url, headers, byte[].class);
+ if (response.getStatusCode().is2xxSuccessful()) {
+ if (response.hasBody()) {
+ return Optional.of(response.getBody());
+ }
+ logger.error("Received response without body ...");
+ }
+ return Optional.empty();
+ } catch (final Exception restProcessingException) {
+ final String message = "Caught exception while getting resource package content for: " + packageId;
+ throw new SdcPackageRequestFailureException(message, restProcessingException);
+ }
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/JobExecutorService.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/JobExecutorService.java
new file mode 100644
index 0000000..c4bd210
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/JobExecutorService.java
@@ -0,0 +1,376 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.service;
+
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_INSTANCE_ID_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_AS_REQUEST_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.INSTANTIATE_AS_REQUEST_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.JOB_ID_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.OCC_ID_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.TERMINATE_AS_REQUEST_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.CREATE_AS_WORKFLOW_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.DELETE_AS_WORKFLOW_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.INSTANTIATE_AS_WORKFLOW_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.TERMINATE_AS_WORKFLOW_NAME;
+import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.ERROR;
+import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.FINISHED;
+import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.FINISHED_WITH_ERROR;
+import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.IN_PROGRESS;
+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.cnfm.lcm.bpmn.flows.GsonProvider;
+import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.AsRequestProcessingException;
+import org.onap.so.cnfm.lcm.database.beans.AsInst;
+import org.onap.so.cnfm.lcm.database.beans.AsLcmOpOcc;
+import org.onap.so.cnfm.lcm.database.beans.AsLcmOpType;
+import org.onap.so.cnfm.lcm.database.beans.Job;
+import org.onap.so.cnfm.lcm.database.beans.JobAction;
+import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum;
+import org.onap.so.cnfm.lcm.database.beans.OperationStateEnum;
+import org.onap.so.cnfm.lcm.database.beans.State;
+import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider;
+import org.onap.so.cnfm.lcm.model.AsInstance;
+import org.onap.so.cnfm.lcm.model.CreateAsRequest;
+import org.onap.so.cnfm.lcm.model.ErrorDetails;
+import org.onap.so.cnfm.lcm.model.InstantiateAsRequest;
+import org.onap.so.cnfm.lcm.model.TerminateAsRequest;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import com.google.common.collect.ImmutableSet;
+import com.google.gson.Gson;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@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-cnfm-lcm.requesttimeout.timeoutInSeconds:300}")
+ private int timeOutInSeconds;
+
+ private final DatabaseServiceProvider databaseServiceProvider;
+ private final WorkflowExecutorService workflowExecutorService;
+ private final WorkflowQueryService workflowQueryService;
+ private final Gson gson;
+
+ @Autowired
+ public JobExecutorService(final DatabaseServiceProvider databaseServiceProvider,
+ final WorkflowExecutorService workflowExecutorService, final WorkflowQueryService workflowQueryService,
+ final GsonProvider gsonProvider) {
+ this.databaseServiceProvider = databaseServiceProvider;
+ this.workflowExecutorService = workflowExecutorService;
+ this.workflowQueryService = workflowQueryService;
+ this.gson = gsonProvider.getGson();
+ }
+
+ public AsInstance runCreateAsJob(final CreateAsRequest createAsRequest) {
+ logger.info("Starting 'Create AS' workflow job for request:\n{}", createAsRequest);
+ final Job newJob = new Job().startTime(LocalDateTime.now()).jobType("AS").jobAction(JobAction.CREATE)
+ .resourceId(createAsRequest.getAsdId()).resourceName(createAsRequest.getAsInstanceName())
+ .status(JobStatusEnum.STARTING);
+ databaseServiceProvider.addJob(newJob);
+
+ logger.info("New job created in database :\n{}", newJob);
+
+ workflowExecutorService.executeWorkflow(newJob.getJobId(), CREATE_AS_WORKFLOW_NAME,
+ getVariables(newJob.getJobId(), createAsRequest));
+
+ final ImmutablePair<String, JobStatusEnum> immutablePair =
+ waitForJobToFinish(newJob.getJobId(), JOB_FINISHED_STATES);
+
+ if (immutablePair.getRight() == null) {
+ final String message = "Failed to create AS for request: \n" + createAsRequest;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+ final JobStatusEnum finalJobStatus = immutablePair.getRight();
+ final String processInstanceId = immutablePair.getLeft();
+
+ if (!FINISHED.equals(finalJobStatus)) {
+
+ final Optional<ErrorDetails> optional = workflowQueryService.getErrorDetails(processInstanceId);
+ if (optional.isPresent()) {
+ final ErrorDetails errorDetails = optional.get();
+ final String message =
+ "Failed to create AS for request: \n" + createAsRequest + " due to \n" + errorDetails;
+ logger.error(message);
+ throw new AsRequestProcessingException(message, errorDetails);
+ }
+
+ final String message = "Received unexpected Job Status: " + finalJobStatus
+ + " Failed to Create AS for request: \n" + createAsRequest;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+
+ logger.debug("Will query for CreateAsResponse using processInstanceId:{}", processInstanceId);
+ final Optional<AsInstance> optional = workflowQueryService.getCreateNsResponse(processInstanceId);
+ if (optional.isEmpty()) {
+ final String message =
+ "Unable to find CreateAsReponse in Camunda History for process instance: " + processInstanceId;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+ return optional.get();
+ }
+
+ public String runInstantiateAsJob(final String asInstanceId, final InstantiateAsRequest instantiateAsRequest) {
+ final Job newJob = new Job().startTime(LocalDateTime.now()).jobType("AS").jobAction(JobAction.INSTANTIATE)
+ .resourceId(asInstanceId).status(JobStatusEnum.STARTING);
+ databaseServiceProvider.addJob(newJob);
+ logger.info("New job created in database :\n{}", newJob);
+
+ final LocalDateTime currentDateTime = LocalDateTime.now();
+ final AsLcmOpOcc newAsLcmOpOcc = new AsLcmOpOcc().id(asInstanceId).operation(AsLcmOpType.INSTANTIATE)
+ .operationState(OperationStateEnum.PROCESSING).stateEnteredTime(currentDateTime)
+ .startTime(currentDateTime).asInst(getAsInst(asInstanceId)).isAutoInvocation(false)
+ .isCancelPending(false).operationParams(gson.toJson(instantiateAsRequest));
+ databaseServiceProvider.addAsLcmOpOcc(newAsLcmOpOcc);
+ logger.info("New AsLcmOpOcc created in database :\n{}", newAsLcmOpOcc);
+
+ workflowExecutorService.executeWorkflow(newJob.getJobId(), INSTANTIATE_AS_WORKFLOW_NAME,
+ getVariables(asInstanceId, newJob.getJobId(), newAsLcmOpOcc.getId(), instantiateAsRequest));
+
+ final ImmutableSet<JobStatusEnum> jobFinishedStates =
+ ImmutableSet.of(FINISHED, ERROR, FINISHED_WITH_ERROR, IN_PROGRESS);
+ final ImmutablePair<String, JobStatusEnum> immutablePair =
+ waitForJobToFinish(newJob.getJobId(), jobFinishedStates);
+
+ if (immutablePair.getRight() == null) {
+ final String message = "Failed to Instantiate AS for request: \n" + instantiateAsRequest;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+
+ final JobStatusEnum finalJobStatus = immutablePair.getRight();
+ if (IN_PROGRESS.equals(finalJobStatus) || FINISHED.equals(finalJobStatus)) {
+ logger.info("Instantiation Job status: {}", finalJobStatus);
+ return newAsLcmOpOcc.getId();
+ }
+
+ final String message = "Received unexpected Job Status: " + finalJobStatus
+ + " Failed to instantiate AS for request: \n" + instantiateAsRequest;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+
+ public String runTerminateAsJob(final String asInstanceId, final TerminateAsRequest terminateAsRequest) {
+ doInitialTerminateChecks(asInstanceId, terminateAsRequest);
+
+ final Job newJob = new Job().startTime(LocalDateTime.now()).jobType("AS").jobAction(JobAction.TERMINATE)
+ .resourceId(asInstanceId).status(JobStatusEnum.STARTING);
+ databaseServiceProvider.addJob(newJob);
+ logger.info("New job created in database :\n{}", newJob);
+
+ final LocalDateTime currentDateTime = LocalDateTime.now();
+ final AsLcmOpOcc newAsLcmOpOcc = new AsLcmOpOcc().id(asInstanceId).operation(AsLcmOpType.TERMINATE)
+ .operationState(OperationStateEnum.PROCESSING).stateEnteredTime(currentDateTime)
+ .startTime(currentDateTime).asInst(getAsInst(asInstanceId)).isAutoInvocation(false)
+ .isCancelPending(false).operationParams(gson.toJson(terminateAsRequest));
+ databaseServiceProvider.addAsLcmOpOcc(newAsLcmOpOcc);
+ logger.info("New AsLcmOpOcc created in database :\n{}", newAsLcmOpOcc);
+
+ workflowExecutorService.executeWorkflow(newJob.getJobId(), TERMINATE_AS_WORKFLOW_NAME,
+ getVariables(asInstanceId, newJob.getJobId(), newAsLcmOpOcc.getId(), terminateAsRequest));
+
+ final ImmutableSet<JobStatusEnum> jobFinishedStates =
+ ImmutableSet.of(FINISHED, ERROR, FINISHED_WITH_ERROR, IN_PROGRESS);
+ final ImmutablePair<String, JobStatusEnum> immutablePair =
+ waitForJobToFinish(newJob.getJobId(), jobFinishedStates);
+
+ if (immutablePair.getRight() == null) {
+ final String message =
+ "Failed to Terminate AS with id: " + asInstanceId + " for request: \n" + terminateAsRequest;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+
+ final JobStatusEnum finalJobStatus = immutablePair.getRight();
+
+ if (IN_PROGRESS.equals(finalJobStatus) || FINISHED.equals(finalJobStatus)) {
+ logger.info("Termination Job status: {}", finalJobStatus);
+ return newAsLcmOpOcc.getId();
+ }
+
+ final String message = "Received unexpected Job Status: " + finalJobStatus + " Failed to Terminate AS with id: "
+ + asInstanceId + " for request: \n" + terminateAsRequest;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+
+ public void runDeleteAsJob(final String asInstanceId) {
+ final Job newJob = new Job().startTime(LocalDateTime.now()).jobType("AS").jobAction(JobAction.DELETE)
+ .resourceId(asInstanceId).status(JobStatusEnum.STARTING);
+ databaseServiceProvider.addJob(newJob);
+ logger.info("New job created in database :\n{}", newJob);
+
+ workflowExecutorService.executeWorkflow(newJob.getJobId(), DELETE_AS_WORKFLOW_NAME,
+ getVariables(asInstanceId, newJob.getJobId()));
+
+ final ImmutablePair<String, JobStatusEnum> immutablePair =
+ waitForJobToFinish(newJob.getJobId(), JOB_FINISHED_STATES);
+
+ if (immutablePair.getRight() == null) {
+ final String message = "Failed to Delete AS with id: " + asInstanceId;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+
+ final JobStatusEnum finalJobStatus = immutablePair.getRight();
+ final String processInstanceId = immutablePair.getLeft();
+
+ logger.info("Delete Job status: {}", finalJobStatus);
+
+ if (!FINISHED.equals(finalJobStatus)) {
+
+ final Optional<ErrorDetails> optional = workflowQueryService.getErrorDetails(processInstanceId);
+ if (optional.isPresent()) {
+ final ErrorDetails errorDetails = optional.get();
+ final String message = "Failed to Delete AS with id: " + asInstanceId + " due to \n" + errorDetails;
+ logger.error(message);
+ throw new AsRequestProcessingException(message, errorDetails);
+ }
+
+ final String message = "Received unexpected Job Status: " + finalJobStatus
+ + " Failed to Delete AS with id: " + asInstanceId;
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+
+ logger.debug("Delete AS finished successfully ...");
+ }
+
+ private AsInst getAsInst(final String asInstId) {
+ logger.info("Getting AsInst with nsInstId: {}", asInstId);
+ final Optional<AsInst> optionalNfvoNsInst = databaseServiceProvider.getAsInst(asInstId);
+
+ if (optionalNfvoNsInst.isEmpty()) {
+ final String message = "No matching AS Instance for id: " + asInstId + " found in database.";
+ throw new AsRequestProcessingException(message);
+ }
+
+ return optionalNfvoNsInst.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<Job> optional = databaseServiceProvider.getRefreshedJob(jobId);
+
+ if (optional.isEmpty()) {
+ logger.error("Unable to find Job using jobId: {}", jobId);
+ return ImmutablePair.nullPair();
+ }
+
+ final Job job = optional.get();
+ currentJobStatus = job.getStatus();
+ logger.debug("Received job status response: \n {}", job);
+ if (jobFinishedStates.contains(currentJobStatus)) {
+ logger.info("Job finished \n {}", currentJobStatus);
+ return ImmutablePair.of(job.getProcessInstanceId(), currentJobStatus);
+ }
+
+ logger.info("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 void doInitialTerminateChecks(final String asInstanceId, final TerminateAsRequest terminateAsRequest) {
+ final AsInst asInst = getAsInst(asInstanceId);
+ if (isNotInstantiated(asInst)) {
+ final String message = "TerminateAsRequest received: " + terminateAsRequest + " for asInstanceId: "
+ + asInstanceId + "\nUnable to terminate. AS Instance is already in " + State.NOT_INSTANTIATED
+ + " state." + "\nThis method can only be used with an AS instance in the " + State.INSTANTIATED
+ + " state.";
+ logger.error(message);
+ throw new AsRequestProcessingException(message);
+ }
+ }
+
+ private boolean isNotInstantiated(final AsInst asInst) {
+ return State.NOT_INSTANTIATED.equals(asInst.getStatus());
+ }
+
+ private Map<String, Object> getVariables(final String jobId, final CreateAsRequest createAsRequest) {
+ final Map<String, Object> variables = new HashMap<>();
+ variables.put(JOB_ID_PARAM_NAME, jobId);
+ variables.put(CREATE_AS_REQUEST_PARAM_NAME, createAsRequest);
+ return variables;
+ }
+
+ private Map<String, Object> getVariables(final String asInstanceId, final String jobId, final String occId,
+ final InstantiateAsRequest instantiateAsRequest) {
+ final Map<String, Object> variables = new HashMap<>();
+ variables.put(AS_INSTANCE_ID_PARAM_NAME, asInstanceId);
+ variables.put(JOB_ID_PARAM_NAME, jobId);
+ variables.put(OCC_ID_PARAM_NAME, occId);
+ variables.put(INSTANTIATE_AS_REQUEST_PARAM_NAME, instantiateAsRequest);
+ return variables;
+ }
+
+ private Map<String, Object> getVariables(final String asInstanceId, final String jobId, final String occId,
+ final TerminateAsRequest terminateAsRequest) {
+ final Map<String, Object> variables = new HashMap<>();
+ variables.put(AS_INSTANCE_ID_PARAM_NAME, asInstanceId);
+ variables.put(JOB_ID_PARAM_NAME, jobId);
+ variables.put(OCC_ID_PARAM_NAME, occId);
+ variables.put(TERMINATE_AS_REQUEST_PARAM_NAME, terminateAsRequest);
+ return variables;
+ }
+
+ private Map<String, Object> getVariables(final String asInstanceId, final String jobId) {
+ final Map<String, Object> variables = new HashMap<>();
+ variables.put(AS_INSTANCE_ID_PARAM_NAME, asInstanceId);
+ variables.put(JOB_ID_PARAM_NAME, jobId);
+ return variables;
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowExecutorService.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowExecutorService.java
new file mode 100644
index 0000000..57a8a41
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowExecutorService.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.service;
+
+import static org.onap.so.cnfm.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-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowQueryService.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowQueryService.java
new file mode 100644
index 0000000..b6dbd77
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/service/WorkflowQueryService.java
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.service;
+
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME;
+import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_AS_RESPONSE_PARAM_NAME;
+import static org.onap.so.cnfm.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.cnfm.lcm.model.AsInstance;
+import org.onap.so.cnfm.lcm.model.ErrorDetails;
+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<AsInstance> getCreateNsResponse(final String processInstanceId) {
+ try {
+
+ if (Strings.isNullOrEmpty(processInstanceId)) {
+ logger.error("Invalid processInstanceId: {}", processInstanceId);
+ return Optional.empty();
+ }
+
+ final HistoricVariableInstance historicVariableInstance =
+ getVariable(processInstanceId, CREATE_AS_RESPONSE_PARAM_NAME);
+
+ if (historicVariableInstance != null) {
+ logger.info("Found HistoricVariableInstance : {}", historicVariableInstance);
+ final Object variableValue = historicVariableInstance.getValue();
+ if (variableValue instanceof AsInstance) {
+ return Optional.ofNullable((AsInstance) variableValue);
+ }
+ logger.error("Unknown CreateAsResponse object type {} received value: {}",
+ historicVariableInstance.getValue() != null ? variableValue.getClass() : null, variableValue);
+ }
+ } catch (final ProcessEngineException processEngineException) {
+ logger.error("Unable to find {} variable using processInstanceId: {}", CREATE_AS_RESPONSE_PARAM_NAME,
+ processInstanceId, processEngineException);
+ }
+ logger.error("Unable to find {} variable using processInstanceId: {}", CREATE_AS_RESPONSE_PARAM_NAME,
+ processInstanceId);
+ return Optional.empty();
+
+ }
+
+ public Optional<ErrorDetails> getErrorDetails(final String processInstanceId) {
+ try {
+ final HistoricVariableInstance historicVariableInstance =
+ getVariable(processInstanceId, AS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME);
+
+ logger.info("Found HistoricVariableInstance : {}", historicVariableInstance);
+ if (historicVariableInstance != null) {
+ final Object variableValue = historicVariableInstance.getValue();
+ if (variableValue instanceof ErrorDetails) {
+ return Optional.ofNullable((ErrorDetails) variableValue);
+ }
+ logger.error("Unknown ErrorContents object type {} received value: {}",
+ historicVariableInstance.getValue() != null ? variableValue.getClass() : null, variableValue);
+ }
+ logger.error("Unable to retrieve HistoricVariableInstance value was null");
+ } catch (final ProcessEngineException processEngineException) {
+ logger.error("Unable to find {} variable using processInstanceId: {}",
+ AS_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-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java
new file mode 100644
index 0000000..57a4dd6
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.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.JsonToken;
+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 {
+ if (JsonToken.NULL == in.peek()) {
+ in.nextNull();
+ return null;
+
+ }
+ final String dateTime = in.nextString();
+ return LocalDateTime.parse(dateTime, FORMATTER);
+
+ }
+
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/OffsetDateTimeTypeAdapter.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/OffsetDateTimeTypeAdapter.java
new file mode 100644
index 0000000..1f63cc1
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/OffsetDateTimeTypeAdapter.java
@@ -0,0 +1,68 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.utils;
+
+import java.io.IOException;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class OffsetDateTimeTypeAdapter extends TypeAdapter<OffsetDateTime> {
+
+ private DateTimeFormatter formatter;
+
+ public OffsetDateTimeTypeAdapter() {
+ this(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ }
+
+ public OffsetDateTimeTypeAdapter(final DateTimeFormatter formatter) {
+ this.formatter = formatter;
+ }
+
+ @Override
+ public void write(final JsonWriter out, final OffsetDateTime date) throws IOException {
+ if (date == null) {
+ out.nullValue();
+ } else {
+ out.value(formatter.format(date));
+ }
+ }
+
+ @Override
+ public OffsetDateTime read(final JsonReader in) throws IOException {
+ if (JsonToken.NULL == in.peek()) {
+ in.nextNull();
+ return null;
+
+ }
+ String date = in.nextString();
+ if (date.endsWith("+0000")) {
+ date = date.substring(0, date.length() - 5) + "Z";
+ }
+ return OffsetDateTime.parse(date, formatter);
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/PropertiesToYamlConverter.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/PropertiesToYamlConverter.java
new file mode 100644
index 0000000..4cc1f8a
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/utils/PropertiesToYamlConverter.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.cnfm.lcm.bpmn.flows.utils;
+
+import java.util.Map;
+import java.util.TreeMap;
+import org.springframework.stereotype.Service;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+
+@Service
+public class PropertiesToYamlConverter {
+ public String getValuesYamlFileContent(final Map<String, String> lifeCycleParams) {
+ final Map<String, Object> root = new TreeMap<>();
+ lifeCycleParams.entrySet().stream().forEach(entry -> processProperty(root, entry.getKey(), entry.getValue()));
+ final Yaml yaml = new Yaml();
+ return yaml.dumpAsMap(root);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void processProperty(final Map<String, Object> root, final String key, final String value) {
+ Map<String, Object> local = root;
+ final String[] keys = key.split("\\.");
+ final int lastIndex = keys.length - 1;
+ for (int index = 0; index < lastIndex; index++) {
+ final String currentKey = keys[index];
+ if (!local.containsKey(currentKey)) {
+ final Map<String, Object> subMap = new TreeMap<>();
+ local.put(currentKey, subMap);
+ local = subMap;
+ continue;
+ } else {
+ local = (Map<String, Object>) local.get(currentKey);
+ }
+ }
+ local.put(keys[lastIndex], value);
+ }
+}
diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/META-INF/services/org.onap.so.client.RestProperties b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/META-INF/services/org.onap.so.client.RestProperties
new file mode 100644
index 0000000..90c1ca7
--- /dev/null
+++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/META-INF/services/org.onap.so.client.RestProperties
@@ -0,0 +1 @@
+org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai.AaiPropertiesImpl \ No newline at end of file