From 21a476895dc40402dced615cb0f1b112b1796355 Mon Sep 17 00:00:00 2001 From: "waqas.ikram" Date: Thu, 20 Aug 2020 09:59:05 +0100 Subject: Implementing Create NS Change-Id: Ib54e7476820fe716137e6d5e08e4d0deb9f104b9 Issue-ID: SO-3179 Signed-off-by: waqas.ikram --- .../lcm/bpmn/flows/CamundaCustomConfiguration.java | 49 +++++ .../bpmn/flows/CamundaDatabaseConfiguration.java | 69 +++++++ .../bpmn/flows/CamundaVariableNameConstants.java | 48 +++++ .../so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java | 36 ++++ .../etsi/nfvo/ns/lcm/bpmn/flows/GsonProvider.java | 44 ++++ .../EtsiCatalogManagerRequestFailureException.java | 41 ++++ .../exceptions/NsRequestProcessingException.java | 53 +++++ .../flows/extclients/aai/AaiClientProvider.java | 34 ++++ .../flows/extclients/aai/AaiPropertiesImpl.java | 76 +++++++ .../flows/extclients/aai/AaiServiceProvider.java | 44 ++++ .../extclients/aai/AaiServiceProviderImpl.java | 83 ++++++++ ...tsiCatalogPackageManagementServiceProvider.java | 36 ++++ ...atalogPackageManagementServiceProviderImpl.java | 86 ++++++++ .../EtsiCatalogServiceProviderConfiguration.java | 188 ++++++++++++++++++ .../etsicatalog/EtsiCatalogUrlProvider.java | 51 +++++ .../lcm/bpmn/flows/service/JobExecutorService.java | 182 +++++++++++++++++ .../flows/service/WorkflowExecutorService.java | 59 ++++++ .../bpmn/flows/service/WorkflowQueryService.java | 108 ++++++++++ .../flows/tasks/AbstractNetworkServiceTask.java | 117 +++++++++++ .../nfvo/ns/lcm/bpmn/flows/tasks/CreateNsTask.java | 221 +++++++++++++++++++++ .../bpmn/flows/utils/LocalDateTimeTypeAdapter.java | 58 ++++++ 21 files changed, 1683 insertions(+) create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaCustomConfiguration.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaDatabaseConfiguration.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/GsonProvider.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/EtsiCatalogManagerRequestFailureException.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/NsRequestProcessingException.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogUrlProvider.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowExecutorService.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowQueryService.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateNsTask.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java (limited to 'so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java') diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaCustomConfiguration.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaCustomConfiguration.java new file mode 100644 index 0000000000..33923f400e --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaCustomConfiguration.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows; + +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.NS_WORKFLOW_ENGINE; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.TENANT_ID; +import static org.slf4j.LoggerFactory.getLogger; +import org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration; +import org.camunda.bpm.spring.boot.starter.configuration.Ordering; +import org.camunda.bpm.spring.boot.starter.configuration.impl.AbstractCamundaConfiguration; +import org.slf4j.Logger; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Component +@Order(Ordering.DEFAULT_ORDER + 1) +public class CamundaCustomConfiguration extends AbstractCamundaConfiguration { + private static final Logger logger = getLogger(CamundaCustomConfiguration.class); + + @Override + public void preInit(final SpringProcessEngineConfiguration processEngineConfiguration) { + logger.info("Setting DeploymentTenantId to {} and DeploymentName to {}", TENANT_ID, NS_WORKFLOW_ENGINE); + processEngineConfiguration.setDeploymentTenantId(TENANT_ID); + processEngineConfiguration.setDeploymentName(NS_WORKFLOW_ENGINE); + super.preInit(processEngineConfiguration); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaDatabaseConfiguration.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaDatabaseConfiguration.java new file mode 100644 index 0000000000..946bd38cbe --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaDatabaseConfiguration.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows; + + +import static org.slf4j.LoggerFactory.getLogger; +import javax.sql.DataSource; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; +import org.springframework.jmx.export.MBeanExporter; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Configuration +@EnableTransactionManagement +@Profile({"!test"}) +public class CamundaDatabaseConfiguration { + + private static final Logger logger = getLogger(CamundaDatabaseConfiguration.class); + + @Autowired(required = false) + private MBeanExporter mBeanExporter; + + @Bean + @ConfigurationProperties(prefix = "spring.datasource.hikari.camunda") + public HikariConfig camundaDbConfig() { + logger.debug("Creating HikariConfig bean ... "); + return new HikariConfig(); + } + + @Primary + @Bean(name = "dataSource") + public DataSource dataSource() { + if (mBeanExporter != null) { + mBeanExporter.addExcludedBean("dataSource"); + } + logger.debug("Creating HikariDataSource bean ... "); + final HikariConfig hikariConfig = this.camundaDbConfig(); + return new HikariDataSource(hikariConfig); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java new file mode 100644 index 0000000000..ed6da5430e --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public class CamundaVariableNameConstants { + + public static final String JOB_ID_PARAM_NAME = "jobId"; + public static final String JOB_BUSINESS_KEY_PARAM_NAME = "jobBusinessKey"; + public static final String CREATE_NS_REQUEST_PARAM_NAME = "createNsRequest"; + public static final String GLOBAL_CUSTOMER_ID_PARAM_NAME = "globalCustomerId"; + public static final String SERVICE_TYPE_PARAM_NAME = "serviceType"; + + + public static final String NS_PACKAGE_MODEL_PARAM_NAME = "NSPackageModel"; + public static final String CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME = + "CreateNsWorkflowProcessingException"; + public static final String CREATE_NS_RESPONSE_PARAM_NAME = "createNsResponse"; + + public static final String INSTANTIATE_NS_REQUEST_PARAM_NAME = "instantiateNsRequest"; + public static final String OCC_ID_PARAM_NAME = "occId"; + public static final String NS_INSTANCE_ID_PARAM_NAME = "NsInstanceId"; + public static final String NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME = "NetworkServiceDescriptor"; + public static final String VNF_CREATE_INSTANTIATE_REQUESTS = "vnfCreateInstantiateRequests"; + + private CamundaVariableNameConstants() {} + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java new file mode 100644 index 0000000000..46115a753b --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public class Constants { + + public static final String TENANT_ID = "ns-workflow-engine-tenant"; + public static final String NS_WORKFLOW_ENGINE = "NS-WORKFLOW-ENGINE"; + public static final String CREATE_NS_WORKFLOW_NAME = "CreateNs"; + public static final String INSTANTIATE_NS_WORKFLOW_NAME = "InstantiateNs"; + public static final String GET_NS_OCCURRENCE_OPERATION_STATUS_NAME = "GetNsOccurrenceOperationStatus"; + + private Constants() {} + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/GsonProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/GsonProvider.java new file mode 100644 index 0000000000..31961d5b86 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/GsonProvider.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows; + +import java.time.LocalDateTime; +import org.onap.so.etsi.nfvo.ns.lcm.JSON; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.utils.LocalDateTimeTypeAdapter; +import org.springframework.stereotype.Component; +import org.threeten.bp.OffsetDateTime; +import com.google.gson.Gson; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Component +public class GsonProvider { + + private final JSON.OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new JSON.OffsetDateTimeTypeAdapter(); + + public Gson getGson() { + return JSON.createGson().registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()).create(); + } + + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/EtsiCatalogManagerRequestFailureException.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/EtsiCatalogManagerRequestFailureException.java new file mode 100644 index 0000000000..553d2f1cf8 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/EtsiCatalogManagerRequestFailureException.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) +public class EtsiCatalogManagerRequestFailureException extends RuntimeException { + + private static final long serialVersionUID = 66862444537194516L; + + public EtsiCatalogManagerRequestFailureException(final String message) { + super(message); + } + + public EtsiCatalogManagerRequestFailureException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/NsRequestProcessingException.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/NsRequestProcessingException.java new file mode 100644 index 0000000000..0dcadfd4d8 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/exceptions/NsRequestProcessingException.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions; + +import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +/** + * + * @author Waqas Ikram (waqas.ikram@est.tech) + */ +@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) +public class NsRequestProcessingException extends RuntimeException { + + private static final long serialVersionUID = 66862444537194516L; + private InlineResponse400 problemDetails; + + public NsRequestProcessingException(final String message) { + super(message); + } + + public NsRequestProcessingException(final String message, final InlineResponse400 problemDetails) { + super(message); + this.problemDetails = problemDetails; + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + + public InlineResponse400 getProblemDetails() { + return problemDetails; + } +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java new file mode 100644 index 0000000000..673662aae8 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiClientProvider.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai; + +import org.onap.aaiclient.client.aai.AAIResourcesClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AaiClientProvider { + + @Bean + public AAIResourcesClient getAaiClient() { + return new AAIResourcesClient(); + } +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java new file mode 100644 index 0000000000..3df3580907 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiPropertiesImpl.java @@ -0,0 +1,76 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai; + +import org.onap.aaiclient.client.aai.AAIProperties; +import org.onap.aaiclient.client.aai.AAIVersion; +import org.onap.so.spring.SpringContextHelper; +import org.springframework.context.ApplicationContext; +import java.net.MalformedURLException; +import java.net.URL; + +public class AaiPropertiesImpl implements AAIProperties { + + private final String endpoint; + private final String encryptedBasicAuth; + private final String encryptionKey; + private final String aaiVersion; + + public AaiPropertiesImpl() { + + final ApplicationContext context = SpringContextHelper.getAppContext(); + this.endpoint = context.getEnvironment().getProperty("aai.endpoint"); + this.encryptedBasicAuth = context.getEnvironment().getProperty("aai.auth"); + this.encryptionKey = context.getEnvironment().getProperty("mso.key"); + this.aaiVersion = context.getEnvironment().getProperty("aai.version"); + } + + @Override + public URL getEndpoint() throws MalformedURLException { + return new URL(endpoint); + } + + @Override + public String getSystemName() { + return "MSO"; + } + + @Override + public AAIVersion getDefaultVersion() { + for (final AAIVersion version : AAIVersion.values()) { + if (version.toString().equalsIgnoreCase(this.aaiVersion)) { + return version; + } ; + + } + return AAIVersion.LATEST; + } + + @Override + public String getAuth() { + return encryptedBasicAuth; + } + + @Override + public String getKey() { + return encryptionKey; + } +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java new file mode 100644 index 0000000000..53062395cf --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai; + +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ServiceInstance; +import java.util.Optional; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public interface AaiServiceProvider { + + void createServiceInstance(final String globalCustomerId, final String serviceType, + final ServiceInstance aaiServiceInstance); + + void createGenericVnfAndConnectServiceInstance(final String serviceInstanceId, final String vnfId, + final GenericVnf genericVnf); + + void connectGenericVnfToTenant(final String vnfId, final String cloudOwner, final String cloudRegion, + final String tenantId); + + Optional getGenericVnf(final String vnfId); + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java new file mode 100644 index 0000000000..049746c6ab --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai; + +import java.util.Optional; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aaiclient.client.aai.AAIObjectType; +import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri; +import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + */ +@Service +public class AaiServiceProviderImpl implements AaiServiceProvider { + private static final Logger logger = LoggerFactory.getLogger(AaiServiceProviderImpl.class); + private final AaiClientProvider aaiClientProvider; + + @Autowired + public AaiServiceProviderImpl(final AaiClientProvider aaiClientProvider) { + this.aaiClientProvider = aaiClientProvider; + } + + @Override + public void createServiceInstance(final String globalCustomerId, final String serviceType, + final ServiceInstance aaiServiceInstance) { + logger.info("Creating service instance in AAI: {}", aaiServiceInstance); + final AAIResourceUri serviceInstanceURI = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, + globalCustomerId, serviceType, aaiServiceInstance.getServiceInstanceId()); + aaiClientProvider.getAaiClient().createIfNotExists(serviceInstanceURI, Optional.of(aaiServiceInstance)); + + } + + @Override + public void createGenericVnfAndConnectServiceInstance(final String serviceInstanceId, final String vnfId, + final GenericVnf genericVnf) { + logger.info("Creating GenericVnf in AAI: {}", genericVnf); + final AAIResourceUri genericVnfURI = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId); + final AAIResourceUri serviceInstanceURI = + AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, serviceInstanceId); + aaiClientProvider.getAaiClient().createIfNotExists(genericVnfURI, Optional.of(genericVnf)) + .connect(genericVnfURI, serviceInstanceURI); + + } + + @Override + public void connectGenericVnfToTenant(final String vnfId, final String cloudOwner, final String cloudRegion, + final String tenantId) { + logger.info("Connecting GenericVnf {} to {}/{}/{} in AAI", vnfId, cloudOwner, cloudRegion, tenantId); + final AAIResourceUri tenantURI = + AAIUriFactory.createResourceUri(AAIObjectType.TENANT, cloudOwner, cloudRegion, tenantId); + final AAIResourceUri genericVnfURI = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId); + aaiClientProvider.getAaiClient().connect(tenantURI, genericVnfURI); + } + + @Override + public Optional getGenericVnf(final String vnfId) { + return aaiClientProvider.getAaiClient().get(GenericVnf.class, + AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)); + } +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java new file mode 100644 index 0000000000..a373df43e7 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProvider.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog; + +import java.util.Optional; +import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo; +import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public interface EtsiCatalogPackageManagementServiceProvider { + + Optional getNSPackageModel(final String nsdId); + + Optional getVnfPkgInfo(final String vnfPkgId); + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.java new file mode 100644 index 0000000000..32f7cc1182 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogPackageManagementServiceProviderImpl.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog; + +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_SERVICE_PROVIDER_BEAN; +import java.util.Optional; +import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo; +import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.EtsiCatalogManagerRequestFailureException; +import org.onap.so.rest.service.HttpRestServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Service +public class EtsiCatalogPackageManagementServiceProviderImpl implements EtsiCatalogPackageManagementServiceProvider { + + private static final Logger logger = LoggerFactory.getLogger(EtsiCatalogPackageManagementServiceProviderImpl.class); + + private final HttpRestServiceProvider httpServiceProvider; + private final EtsiCatalogUrlProvider etsiCatalogUrlProvider; + + @Autowired + public EtsiCatalogPackageManagementServiceProviderImpl(final EtsiCatalogUrlProvider etsiCatalogUrlProvider, + @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN) final HttpRestServiceProvider httpServiceProvider) { + this.etsiCatalogUrlProvider = etsiCatalogUrlProvider; + this.httpServiceProvider = httpServiceProvider; + } + + @Override + public Optional getNSPackageModel(final String nsdId) { + try { + final ResponseEntity response = + httpServiceProvider.getHttpResponse(etsiCatalogUrlProvider.getNsPackageUrl(nsdId), NsdInfo.class); + if (response.getStatusCode().is2xxSuccessful()) { + return Optional.ofNullable(response.getBody()); + } + return Optional.empty(); + } catch (final Exception restProcessingException) { + logger.error("Caught exception while getting NS package model for: {}", nsdId, restProcessingException); + throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.", + restProcessingException); + } + } + + @Override + public Optional getVnfPkgInfo(final String vnfPkgId) { + try { + final ResponseEntity response = httpServiceProvider + .getHttpResponse(etsiCatalogUrlProvider.getVnfPackageUrl(vnfPkgId), VnfPkgInfo.class); + if (response.getStatusCode().is2xxSuccessful()) { + return Optional.ofNullable(response.getBody()); + } + return Optional.empty(); + } catch (final Exception restProcessingException) { + logger.error("Caught exception while getting VNF package model for: {}", vnfPkgId, restProcessingException); + throw new EtsiCatalogManagerRequestFailureException("Internal Server Error Occurred.", + restProcessingException); + } + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java new file mode 100644 index 0000000000..8c6ea92428 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogServiceProviderConfiguration.java @@ -0,0 +1,188 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.util.Iterator; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.ssl.SSLContextBuilder; +import org.onap.logging.filter.spring.SpringClientPayloadFilter; +import org.onap.so.configuration.rest.BasicHttpHeadersProvider; +import org.onap.so.configuration.rest.HttpClientConnectionConfiguration; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider; +import org.onap.so.logging.jaxrs.filter.SOSpringClientFilter; +import org.onap.so.rest.service.HttpRestServiceProvider; +import org.onap.so.rest.service.HttpRestServiceProviderImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.GsonHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +/** + * Configures the HttpRestServiceProvider to make REST calls to the ETSI Catalog Manager + * + * @author gareth.roper@est.tech + */ + +@Configuration +public class EtsiCatalogServiceProviderConfiguration { + public static final String ETSI_CATALOG_REST_TEMPLATE_BEAN = "etsiCatalogRestTemplate"; + + public static final String ETSI_CATALOG_SERVICE_PROVIDER_BEAN = "etsiCatalogServiceProvider"; + + private final static Logger LOGGER = LoggerFactory.getLogger(EtsiCatalogServiceProviderConfiguration.class); + + private final HttpClientConnectionConfiguration clientConnectionConfiguration; + + @Value("${etsi-catalog-manager.http.client.ssl.trust-store:#{null}}") + private Resource trustStore; + @Value("${etsi-catalog-manager.http.client.ssl.trust-store-password:#{null}}") + private String trustStorePassword; + + private final GsonProvider gsonProvider; + + @Autowired + public EtsiCatalogServiceProviderConfiguration( + final HttpClientConnectionConfiguration clientConnectionConfiguration, final GsonProvider gsonProvider) { + this.clientConnectionConfiguration = clientConnectionConfiguration; + this.gsonProvider = gsonProvider; + } + + @Bean + @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN) + public RestTemplate etsiCatalogRestTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.getInterceptors().add(new SOSpringClientFilter()); + restTemplate.getInterceptors().add((new SpringClientPayloadFilter())); + return restTemplate; + } + + @Bean + @Qualifier(ETSI_CATALOG_SERVICE_PROVIDER_BEAN) + public HttpRestServiceProvider etsiCatalogHttpRestServiceProvider( + @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN) final RestTemplate restTemplate) { + setGsonMessageConverter(restTemplate); + + final HttpClientBuilder httpClientBuilder = getHttpClientBuilder(); + if (trustStore != null) { + try { + LOGGER.debug("Setting up HttpComponentsClientHttpRequestFactory with SSL Context"); + LOGGER.debug("Setting client trust-store: {}", trustStore.getURL()); + LOGGER.debug("Creating SSLConnectionSocketFactory with AllowAllHostsVerifier ... "); + final SSLContext sslContext = new SSLContextBuilder() + .loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray()).build(); + final SSLConnectionSocketFactory sslConnectionSocketFactory = + new SSLConnectionSocketFactory(sslContext, AllowAllHostsVerifier.INSTANCE); + httpClientBuilder.setSSLSocketFactory(sslConnectionSocketFactory); + final Registry socketFactoryRegistry = RegistryBuilder + .create().register("http", PlainConnectionSocketFactory.INSTANCE) + .register("https", sslConnectionSocketFactory).build(); + + httpClientBuilder.setConnectionManager(getConnectionManager(socketFactoryRegistry)); + } catch (final KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException + | IOException exception) { + LOGGER.error("Error reading truststore, TLS connection will fail.", exception); + } + + } else { + LOGGER.debug("Setting connection manager without SSL ConnectionSocketFactory ..."); + httpClientBuilder.setConnectionManager(getConnectionManager()); + } + + final HttpComponentsClientHttpRequestFactory factory = + new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build()); + restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(factory)); + + return new HttpRestServiceProviderImpl(restTemplate, new BasicHttpHeadersProvider().getHttpHeaders()); + } + + private PoolingHttpClientConnectionManager getConnectionManager( + final Registry socketFactoryRegistry) { + return new PoolingHttpClientConnectionManager(socketFactoryRegistry, null, null, null, + clientConnectionConfiguration.getTimeToLiveInMins(), TimeUnit.MINUTES); + } + + private PoolingHttpClientConnectionManager getConnectionManager() { + return new PoolingHttpClientConnectionManager(clientConnectionConfiguration.getTimeToLiveInMins(), + TimeUnit.MINUTES); + } + + private HttpClientBuilder getHttpClientBuilder() { + return HttpClientBuilder.create().setMaxConnPerRoute(clientConnectionConfiguration.getMaxConnectionsPerRoute()) + .setMaxConnTotal(clientConnectionConfiguration.getMaxConnections()) + .setDefaultRequestConfig(getRequestConfig()); + } + + private RequestConfig getRequestConfig() { + return RequestConfig.custom().setSocketTimeout(clientConnectionConfiguration.getSocketTimeOutInMiliSeconds()) + .setConnectTimeout(clientConnectionConfiguration.getConnectionTimeOutInMilliSeconds()).build(); + } + + private static final class AllowAllHostsVerifier implements HostnameVerifier { + + private static final AllowAllHostsVerifier INSTANCE = new AllowAllHostsVerifier(); + + @Override + public boolean verify(final String hostname, final SSLSession session) { + LOGGER.debug("Skipping hostname verification ..."); + return true; + } + + } + + public void setGsonMessageConverter(final RestTemplate restTemplate) { + final Iterator> iterator = restTemplate.getMessageConverters().iterator(); + while (iterator.hasNext()) { + if (iterator.next() instanceof MappingJackson2HttpMessageConverter) { + iterator.remove(); + } + } + restTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gsonProvider.getGson())); + } + + + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogUrlProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogUrlProvider.java new file mode 100644 index 0000000000..e3c159c7b0 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/etsicatalog/EtsiCatalogUrlProvider.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Service +public class EtsiCatalogUrlProvider { + + @Value("${etsi-catalog-manager.base.endpoint}") + private String etsiCatalogManagerEndpoint; + + public EtsiCatalogUrlProvider() {} + + public String getNsPackageUrl(final String nsdId) { + return etsiCatalogManagerEndpoint + "/nsd/v1/ns_descriptors/" + nsdId; + } + + public String getNsPackageContentUrl(final String nsdId) { + return etsiCatalogManagerEndpoint + "/nsd/v1/ns_descriptors/" + nsdId + "/nsd_content"; + } + + public String getVnfPackageUrl(final String vnfPkgId) { + return etsiCatalogManagerEndpoint + "/vnfpkgm/v1/vnf_packages/" + vnfPkgId; + } + + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java new file mode 100644 index 0000000000..692aff62cd --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java @@ -0,0 +1,182 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service; + +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_REQUEST_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.GLOBAL_CUSTOMER_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.JOB_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.SERVICE_TYPE_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.CREATE_NS_WORKFLOW_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.ERROR; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED_WITH_ERROR; +import static org.slf4j.LoggerFactory.getLogger; +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.NsRequestProcessingException; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobAction; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob; +import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.model.CreateNsRequest; +import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400; +import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import com.google.common.collect.ImmutableSet; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Service +public class JobExecutorService { + + private static final Logger logger = getLogger(JobExecutorService.class); + + private static final ImmutableSet JOB_FINISHED_STATES = + ImmutableSet.of(FINISHED, ERROR, FINISHED_WITH_ERROR); + + private static final int SLEEP_TIME_IN_SECONDS = 5; + + @Value("${so-etsi-ns-lcm-workflow-engine.requesttimeout.timeoutInSeconds:300}") + private int timeOutInSeconds; + + private final DatabaseServiceProvider databaseServiceProvider; + private final WorkflowExecutorService workflowExecutorService; + private final WorkflowQueryService workflowQueryService; + + @Autowired + public JobExecutorService(final DatabaseServiceProvider databaseServiceProvider, + final WorkflowExecutorService workflowExecutorService, final WorkflowQueryService workflowQueryService) { + this.databaseServiceProvider = databaseServiceProvider; + this.workflowExecutorService = workflowExecutorService; + this.workflowQueryService = workflowQueryService; + } + + public NsInstancesNsInstance runCreateNsJob(final CreateNsRequest createNsRequest, final String globalCustomerId, + final String serviceType) { + logger.info("Starting 'Create NS' workflow job for request:\n{}", createNsRequest); + final NfvoJob newJob = new NfvoJob().startTime(LocalDateTime.now()).jobType("NS").jobAction(JobAction.CREATE) + .resourceId(createNsRequest.getNsdId()).resourceName(createNsRequest.getNsName()) + .status(JobStatusEnum.STARTING).progress(5); + databaseServiceProvider.addJob(newJob); + + logger.info("New job created in database :\n{}", newJob); + + workflowExecutorService.executeWorkflow(newJob.getJobId(), CREATE_NS_WORKFLOW_NAME, + getVariables(newJob.getJobId(), createNsRequest, globalCustomerId, serviceType)); + + final ImmutablePair immutablePair = + waitForJobToFinish(newJob.getJobId(), JOB_FINISHED_STATES); + + if (immutablePair.getRight() == null) { + final String message = "Failed to create NS for request: \n" + createNsRequest; + logger.error(message); + throw new NsRequestProcessingException(message); + } + final JobStatusEnum finalJobStatus = immutablePair.getRight(); + final String processInstanceId = immutablePair.getLeft(); + + if (!FINISHED.equals(finalJobStatus)) { + + final Optional optional = workflowQueryService.getProblemDetails(processInstanceId); + if (optional.isPresent()) { + final InlineResponse400 problemDetails = optional.get(); + final String message = + "Failed to create NS for request: \n" + createNsRequest + " due to \n" + problemDetails; + logger.error(message); + throw new NsRequestProcessingException(message, problemDetails); + } + + final String message = "Received unexpected Job Status: " + finalJobStatus + + " Failed to Create NS for request: \n" + createNsRequest; + logger.error(message); + throw new NsRequestProcessingException(message); + } + + logger.debug("Will query for CreateNsResponse using processInstanceId:{}", processInstanceId); + final Optional optional = workflowQueryService.getCreateNsResponse(processInstanceId); + if (optional.isEmpty()) { + final String message = + "Unable to find CreateNsReponse in Camunda History for process instance: " + processInstanceId; + logger.error(message); + throw new NsRequestProcessingException(message); + } + return optional.get(); + } + + private ImmutablePair waitForJobToFinish(final String jobId, + final ImmutableSet 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 optional = databaseServiceProvider.getJob(jobId); + + if (optional.isEmpty()) { + logger.error("Unable to find Job using jobId: {}", jobId); + return ImmutablePair.nullPair(); + } + + final NfvoJob nfvoJob = optional.get(); + currentJobStatus = nfvoJob.getStatus(); + logger.debug("Received job status response: \n ", nfvoJob); + if (jobFinishedStates.contains(nfvoJob.getStatus())) { + logger.info("Job finished \n {}", currentJobStatus); + return ImmutablePair.of(nfvoJob.getProcessInstanceId(), currentJobStatus); + } + + logger.debug("Haven't received one of finish state {} yet, will try again in {} seconds", + jobFinishedStates, SLEEP_TIME_IN_SECONDS); + TimeUnit.SECONDS.sleep(SLEEP_TIME_IN_SECONDS); + + } + logger.warn("Timeout current job status: {}", currentJobStatus); + return ImmutablePair.nullPair(); + } catch (final InterruptedException interruptedException) { + Thread.currentThread().interrupt(); + logger.error("Sleep was interrupted", interruptedException); + return ImmutablePair.nullPair(); + } + } + + private Map getVariables(final String jobId, final CreateNsRequest createNsRequest, + final String globalCustomerId, final String serviceType) { + final Map variables = new HashMap<>(); + variables.put(JOB_ID_PARAM_NAME, jobId); + variables.put(CREATE_NS_REQUEST_PARAM_NAME, createNsRequest); + variables.put(GLOBAL_CUSTOMER_ID_PARAM_NAME, globalCustomerId); + variables.put(SERVICE_TYPE_PARAM_NAME, serviceType); + return variables; + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowExecutorService.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowExecutorService.java new file mode 100644 index 0000000000..fa2b8d5507 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowExecutorService.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service; + +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.TENANT_ID; +import static org.slf4j.LoggerFactory.getLogger; +import java.util.Map; +import org.camunda.bpm.engine.RuntimeService; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Service +public class WorkflowExecutorService { + + private static final Logger logger = getLogger(WorkflowExecutorService.class); + + private final RuntimeService runtimeService; + + @Autowired + public WorkflowExecutorService(final RuntimeService runtimeService) { + this.runtimeService = runtimeService; + } + + @Async + public void executeWorkflow(final String jobId, final String processDefinitionKey, + final Map variables) { + logger.info("Executing {} workflow with business key: {}", processDefinitionKey, jobId); + final ProcessInstance processInstance = runtimeService.createProcessInstanceByKey(processDefinitionKey) + .businessKey(jobId).setVariables(variables).processDefinitionTenantId(TENANT_ID).execute(); + + logger.info("Workflow running with processInstanceId: {} and business key: {}", + processInstance.getProcessInstanceId(), processInstance.getBusinessKey()); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowQueryService.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowQueryService.java new file mode 100644 index 0000000000..297e9c34af --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/WorkflowQueryService.java @@ -0,0 +1,108 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service; + +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_RESPONSE_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.TENANT_ID; +import static org.slf4j.LoggerFactory.getLogger; +import java.util.Optional; +import org.camunda.bpm.engine.HistoryService; +import org.camunda.bpm.engine.ProcessEngineException; +import org.camunda.bpm.engine.history.HistoricVariableInstance; +import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400; +import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.google.common.base.Strings; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Service +public class WorkflowQueryService { + + private static final Logger logger = getLogger(WorkflowQueryService.class); + + private final HistoryService camundaHistoryService; + + @Autowired + public WorkflowQueryService(final HistoryService camundaHistoryService) { + this.camundaHistoryService = camundaHistoryService; + } + + public Optional getCreateNsResponse(final String processInstanceId) { + try { + + if (Strings.isNullOrEmpty(processInstanceId)) { + logger.error("Invalid processInstanceId: {}", processInstanceId); + return Optional.empty(); + } + + final HistoricVariableInstance historicVariableInstance = + getVariable(processInstanceId, CREATE_NS_RESPONSE_PARAM_NAME); + + if (historicVariableInstance != null) { + logger.info("Found HistoricVariableInstance : {}", historicVariableInstance); + final Object variableValue = historicVariableInstance.getValue(); + if (variableValue instanceof NsInstancesNsInstance) { + return Optional.ofNullable((NsInstancesNsInstance) variableValue); + } + logger.error("Unknown CreateNsResponse object type {} received value: {}", + historicVariableInstance.getValue() != null ? variableValue.getClass() : null, variableValue); + } + } catch (final ProcessEngineException processEngineException) { + logger.error("Unable to find {} variable using processInstanceId: {}", CREATE_NS_RESPONSE_PARAM_NAME, + processInstanceId, processEngineException); + } + logger.error("Unable to find {} variable using processInstanceId: {}", CREATE_NS_RESPONSE_PARAM_NAME, + processInstanceId); + return Optional.empty(); + + } + + public Optional getProblemDetails(final String processInstanceId) { + try { + final HistoricVariableInstance historicVariableInstance = + getVariable(processInstanceId, CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME); + + logger.info("Found HistoricVariableInstance : {}", historicVariableInstance); + final Object variableValue = historicVariableInstance.getValue(); + if (variableValue instanceof InlineResponse400) { + return Optional.ofNullable((InlineResponse400) variableValue); + } + logger.error("Unknown ProblemDetails object type {} received value: {}", + historicVariableInstance.getValue() != null ? variableValue.getClass() : null, variableValue); + } catch (final ProcessEngineException processEngineException) { + logger.error("Unable to find {} variable using processInstanceId: {}", + CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, processInstanceId, processEngineException); + } + return Optional.empty(); + } + + + private HistoricVariableInstance getVariable(final String processInstanceId, final String name) { + return camundaHistoryService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId) + .variableName(name).tenantIdIn(TENANT_ID).singleResult(); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java new file mode 100644 index 0000000000..99116dacad --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java @@ -0,0 +1,117 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.tasks; + +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.JOB_ID_PARAM_NAME; +import java.time.LocalDateTime; +import java.util.Optional; +import org.camunda.bpm.engine.delegate.BpmnError; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJobStatus; +import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public abstract class AbstractNetworkServiceTask { + private final Logger logger = LoggerFactory.getLogger(getClass()); + protected final DatabaseServiceProvider databaseServiceProvider; + + public AbstractNetworkServiceTask(final DatabaseServiceProvider jobServiceProvider) { + this.databaseServiceProvider = jobServiceProvider; + } + + public void setJobStatus(final DelegateExecution execution, final JobStatusEnum jobStatus, + final String description) { + logger.info("Setting Job Status to {}", jobStatus); + final NfvoJob nfvoJob = getNfvoJob(execution); + nfvoJob.status(jobStatus); + if (JobStatusEnum.STARTED.equals(jobStatus)) { + nfvoJob.processInstanceId(execution.getProcessInstanceId()); + } + + if (JobStatusEnum.FINISHED.equals(jobStatus)) { + nfvoJob.endTime(LocalDateTime.now()); + } + + nfvoJob.nfvoJobStatus( + new NfvoJobStatus().status(jobStatus).description(description).updatedTime(LocalDateTime.now())); + databaseServiceProvider.addJob(nfvoJob); + + } + + public void setJobStatusToError(final DelegateExecution execution, final String description) { + logger.info("Setting Job Status to {}", JobStatusEnum.ERROR); + + final String jobId = (String) execution.getVariable(JOB_ID_PARAM_NAME); + final Optional optional = databaseServiceProvider.getJob(jobId); + if (optional.isPresent()) { + final InlineResponse400 problemDetails = + (InlineResponse400) execution.getVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME); + + final NfvoJob nfvoJob = optional.get(); + nfvoJob.status(JobStatusEnum.ERROR).endTime(LocalDateTime.now()); + + if (problemDetails != null) { + logger.error("Found failed reason: {}", problemDetails); + nfvoJob.nfvoJobStatus(new NfvoJobStatus().status(JobStatusEnum.ERROR) + .description(problemDetails.getDetail()).updatedTime(LocalDateTime.now())); + } + nfvoJob.nfvoJobStatus(new NfvoJobStatus().status(JobStatusEnum.ERROR).description(description) + .updatedTime(LocalDateTime.now())); + + databaseServiceProvider.addJob(nfvoJob); + } + logger.info("Finished setting Job Status to {}", JobStatusEnum.ERROR); + + } + + protected void abortOperation(final DelegateExecution execution, final String message) { + abortOperation(execution, message, new InlineResponse400().detail(message)); + } + + protected void abortOperation(final DelegateExecution execution, final String message, + final InlineResponse400 problemDetails) { + logger.error(message); + execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, problemDetails); + throw new BpmnError("WORKFLOW_FAILED"); + } + + private NfvoJob getNfvoJob(final DelegateExecution execution) { + final String jobId = (String) execution.getVariable(JOB_ID_PARAM_NAME); + final Optional optional = databaseServiceProvider.getJob(jobId); + if (!optional.isPresent()) { + final String message = "Unable to find job using job id: " + jobId; + logger.error(message); + execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, + new InlineResponse400().detail(message)); + throw new BpmnError("WORKFLOW_FAILED"); + + } + return optional.get(); + } +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateNsTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateNsTask.java new file mode 100644 index 0000000000..19cac68f9b --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateNsTask.java @@ -0,0 +1,221 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.tasks; + +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_REQUEST_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_RESPONSE_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.GLOBAL_CUSTOMER_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_INSTANCE_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_PACKAGE_MODEL_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.SERVICE_TYPE_PARAM_NAME; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.UUID; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.EtsiCatalogManagerRequestFailureException; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai.AaiServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogPackageManagementServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State; +import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.model.CreateNsRequest; +import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400; +import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance; +import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance.NsStateEnum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Component +public class CreateNsTask extends AbstractNetworkServiceTask { + private static final String NETWORK_SERVICE_NAME = "NetworkService"; + private static final String NETWORK_SERVICE_ROLE = "NetworkService"; + private static final String DOES_NS_PACKAGE_EXISTS_PARAM_NAME = "doesNsPackageExists"; + private static final String DOES_NS_INSTANCE_EXISTS_PARAM_NAME = "doesNsInstanceExists"; + private static final Logger logger = LoggerFactory.getLogger(CreateNsTask.class); + private final EtsiCatalogPackageManagementServiceProvider etsiCatalogPackageManagementServiceProvider; + private final AaiServiceProvider aaiServiceProvider; + + @Autowired + public CreateNsTask(final DatabaseServiceProvider databaseServiceProvider, + final AaiServiceProvider aaiServiceProvider, + final EtsiCatalogPackageManagementServiceProvider etsiCatalogPackageManagementServiceProvider) { + super(databaseServiceProvider); + this.aaiServiceProvider = aaiServiceProvider; + this.etsiCatalogPackageManagementServiceProvider = etsiCatalogPackageManagementServiceProvider; + } + + public void setJobStatusToStarted(final DelegateExecution execution) { + setJobStatus(execution, JobStatusEnum.STARTED, "Create NS workflow process started"); + } + + public void setJobStatusToFinished(final DelegateExecution execution) { + setJobStatus(execution, JobStatusEnum.FINISHED, "Create NS workflow process finished"); + } + + public void setJobStatusToError(final DelegateExecution execution) { + setJobStatusToError(execution, "Create NS workflow process failed"); + } + + public void getNsPackage(final DelegateExecution execution) { + logger.info("Retrieving NS package from ETSI Catalog Manager ..."); + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Retrieving NS package from ETSI Catalog Manager"); + + final CreateNsRequest createNsRequest = (CreateNsRequest) execution.getVariable(CREATE_NS_REQUEST_PARAM_NAME); + + try { + final Optional optional = + etsiCatalogPackageManagementServiceProvider.getNSPackageModel(createNsRequest.getNsdId()); + + if (optional.isPresent()) { + final NsdInfo packageModel = optional.get(); + logger.info("NS Package exists {}", packageModel); + execution.setVariable(NS_PACKAGE_MODEL_PARAM_NAME, packageModel); + execution.setVariable(DOES_NS_PACKAGE_EXISTS_PARAM_NAME, true); + } else { + final String message = "Unable to find NS package using NsdId: " + createNsRequest.getNsdId(); + logger.error(message); + execution.setVariable(DOES_NS_PACKAGE_EXISTS_PARAM_NAME, false); + execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, + new InlineResponse400().detail(message)); + } + + } catch (final EtsiCatalogManagerRequestFailureException failureException) { + final String message = + "Unexpected exception occured while getting ns package using nsdId: " + createNsRequest.getNsdId(); + logger.error(message, failureException); + + execution.setVariable(DOES_NS_PACKAGE_EXISTS_PARAM_NAME, false); + + execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, + new InlineResponse400().title(message).detail(message)); + } + + } + + public void doesNsInstanceExistsInDb(final DelegateExecution execution) { + logger.info("Executing doesNsInstanceExistsInDb ..."); + + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Checking if NS package exists in database"); + + final CreateNsRequest createNsRequest = + (CreateNsRequest) execution.getVariables().get(CREATE_NS_REQUEST_PARAM_NAME); + + final boolean exists = databaseServiceProvider.isNsInstExists(createNsRequest.getNsName()); + logger.info("Ns Instance entry {} exists in database", exists ? "does" : "doesn't"); + execution.setVariable(DOES_NS_INSTANCE_EXISTS_PARAM_NAME, exists); + + if (exists) { + final Optional optional = + databaseServiceProvider.getNfvoNsInstByName(createNsRequest.getNsName()); + final NfvoNsInst nfvoNsInst = optional.get(); + execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, new InlineResponse400() + .detail("Ns Instance already exists in database : " + nfvoNsInst.toString())); + } + + logger.info("Finished executing doesNsInstanceExistsInDb ..."); + + } + + public void createNsInstanceInDb(final DelegateExecution execution) { + logger.info("Executing createNsInstanceInDb ..."); + + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Checking if NS package exists"); + + final CreateNsRequest createNsRequest = (CreateNsRequest) execution.getVariable(CREATE_NS_REQUEST_PARAM_NAME); + final NsdInfo packageMode = (NsdInfo) execution.getVariable(NS_PACKAGE_MODEL_PARAM_NAME); + + final String globalCustomerId = (String) execution.getVariable(GLOBAL_CUSTOMER_ID_PARAM_NAME); + final String serviceType = (String) execution.getVariable(SERVICE_TYPE_PARAM_NAME); + + final String nsInstId = UUID.randomUUID().toString(); + execution.setVariable(NS_INSTANCE_ID_PARAM_NAME, nsInstId); + + databaseServiceProvider.saveNfvoNsInst(new NfvoNsInst().nsInstId(nsInstId).name(createNsRequest.getNsName()) + .nsPackageId(packageMode.getId()).nsdId(packageMode.getNsdId()) + .nsdInvariantId(packageMode.getNsdInvariantId()).description(createNsRequest.getNsDescription()) + .status(State.NOT_INSTANTIATED).statusUpdatedTime(LocalDateTime.now()) + .globalCustomerId(globalCustomerId).serviceType(serviceType)); + logger.info("Finished executing createNsInstanceInDb ..."); + + } + + + public void createNsInstanceInAai(final DelegateExecution execution) { + logger.info("Executing createNsInstanceInAai ..."); + try { + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Creating NS Instance in AAI"); + + final CreateNsRequest createNsRequest = + (CreateNsRequest) execution.getVariable(CREATE_NS_REQUEST_PARAM_NAME); + final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME); + + final String globalCustomerId = (String) execution.getVariable(GLOBAL_CUSTOMER_ID_PARAM_NAME); + final String serviceType = (String) execution.getVariable(SERVICE_TYPE_PARAM_NAME); + + final ServiceInstance aaiServiceInstance = new ServiceInstance(); + aaiServiceInstance.setServiceInstanceId(nsInstId); + aaiServiceInstance.setServiceInstanceName(createNsRequest.getNsName()); + aaiServiceInstance.setServiceType(NETWORK_SERVICE_NAME); + aaiServiceInstance.setServiceRole(NETWORK_SERVICE_ROLE); + + aaiServiceProvider.createServiceInstance(globalCustomerId, serviceType, aaiServiceInstance); + } catch (final Exception exception) { + final String message = "Unable to Create Service Instance in AAI"; + logger.error(message, exception); + abortOperation(execution, message, new InlineResponse400().detail(message)); + } + logger.info("Finished executing createNsInstanceInAai ..."); + + } + + public void setCreateNsResponse(final DelegateExecution execution) { + logger.info("Executing setCreateNsResponse ..."); + final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME); + final Optional optional = databaseServiceProvider.getNfvoNsInstByNsInstId(nsInstId); + + if (optional.isPresent()) { + final NfvoNsInst nfvoNsInst = optional.get(); + final NsInstancesNsInstance response = new NsInstancesNsInstance().id(nfvoNsInst.getNsInstId()) + .nsInstanceName(nfvoNsInst.getName()).nsdId(nfvoNsInst.getNsdId()) + .nsdInfoId(nfvoNsInst.getNsPackageId()).nsInstanceDescription(nfvoNsInst.getDescription()) + .nsState(NsStateEnum.fromValue(nfvoNsInst.getStatus().toString())); + logger.info("Saving CreateNsResponse: {} in Execution ...", response); + execution.setVariable(CREATE_NS_RESPONSE_PARAM_NAME, response); + } else { + final String message = "Unable to find NS Instance in datababse using id: " + nsInstId; + logger.error(message); + abortOperation(execution, message); + } + + logger.info("Finished executing setCreateNsResponse ..."); + + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java new file mode 100644 index 0000000000..34959ee0f0 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/utils/LocalDateTimeTypeAdapter.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.utils; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public class LocalDateTimeTypeAdapter extends TypeAdapter { + + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + @Override + public void write(final JsonWriter out, final LocalDateTime localDateTime) throws IOException { + if (localDateTime == null) { + out.nullValue(); + } else { + out.value(FORMATTER.format(localDateTime)); + } + } + + @Override + public LocalDateTime read(final JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + final String dateTime = in.nextString(); + return LocalDateTime.parse(dateTime, FORMATTER); + } + } + +} -- cgit 1.2.3-korg