From 2b612c3f375b8c2d5aec263a2dba54f0799e4acb Mon Sep 17 00:00:00 2001 From: sourabh_sourabh Date: Thu, 21 Sep 2023 15:56:19 +0100 Subject: Refactoring persistence classes - Created a common ncmppersistence pkg inside ncmp service "api/impl" pkg". - Move "inventery" into "api/impl" pkg. - Created common class named as "NcmpPersistence" inside "ncmppersistence" pkg. - Move all the commin constants and methods into "NcmpPersistence". - SubscriptionPersistence and InventoryPersistence extends "NcmpPersistence". - Find and replace all the constants of NCMP. Issue-ID: CPS-1883 Signed-off-by: sourabh_sourabh Change-Id: Id3e678109766d680589fa7aab965ea251a55f075 Signed-off-by: sourabh_sourabh --- .../cps/ncmp/api/NetworkCmProxyDataService.java | 2 +- .../NetworkCmProxyCmHandleQueryServiceImpl.java | 11 +- .../api/impl/NetworkCmProxyDataServiceImpl.java | 22 +- .../NetworkCmProxyDataServicePropertyHandler.java | 4 +- .../api/impl/NetworkCmProxyQueryServiceImpl.java | 4 +- .../api/impl/constants/DmiRegistryConstants.java | 36 --- .../CmSubscriptionNcmpInEventForwarder.java | 2 +- .../events/lcm/LcmEventsCmHandleStateHandler.java | 2 +- .../lcm/LcmEventsCmHandleStateHandlerImpl.java | 16 +- .../impl/events/lcm/LcmEventsCreatorHelper.java | 2 +- .../ncmp/api/impl/inventory/CmHandleQueries.java | 87 +++++++ .../api/impl/inventory/CmHandleQueriesImpl.java | 145 ++++++++++++ .../cps/ncmp/api/impl/inventory/CmHandleState.java | 25 +++ .../ncmp/api/impl/inventory/CompositeState.java | 144 ++++++++++++ .../api/impl/inventory/CompositeStateBuilder.java | 154 +++++++++++++ .../api/impl/inventory/CompositeStateUtils.java | 107 +++++++++ .../api/impl/inventory/DataStoreSyncState.java | 25 +++ .../api/impl/inventory/InventoryPersistence.java | 126 +++++++++++ .../impl/inventory/InventoryPersistenceImpl.java | 177 +++++++++++++++ .../api/impl/inventory/LockReasonCategory.java | 25 +++ .../impl/inventory/ModelledDmiServiceLeaves.java | 38 ++++ .../api/impl/inventory/NcmpPersistenceImpl.java | 120 ++++++++++ .../api/impl/inventory/enums/PropertyType.java | 34 +++ .../api/impl/inventory/sync/DataSyncWatchdog.java | 102 +++++++++ .../api/impl/inventory/sync/ModuleSyncService.java | 97 ++++++++ .../api/impl/inventory/sync/ModuleSyncTasks.java | 122 ++++++++++ .../impl/inventory/sync/ModuleSyncWatchdog.java | 139 ++++++++++++ .../ncmp/api/impl/inventory/sync/SyncUtils.java | 201 +++++++++++++++++ .../sync/config/WatchdogSchedulingConfigurer.java | 56 +++++ .../inventory/sync/executor/AsyncTaskExecutor.java | 77 +++++++ .../api/impl/ncmppersistence/NcmpPersistence.java | 116 ++++++++++ .../api/impl/operations/DmiDataOperations.java | 4 +- .../api/impl/operations/DmiModelOperations.java | 2 +- .../ncmp/api/impl/operations/DmiOperations.java | 2 +- .../subscriptions/SubscriptionPersistence.java | 3 +- .../subscriptions/SubscriptionPersistenceImpl.java | 51 ++--- .../cps/ncmp/api/impl/utils/YangDataConverter.java | 4 +- .../ResourceDataOperationRequestUtils.java | 2 +- .../api/impl/yangmodels/YangModelCmHandle.java | 2 +- .../cps/ncmp/api/inventory/CmHandleQueries.java | 87 ------- .../ncmp/api/inventory/CmHandleQueriesImpl.java | 144 ------------ .../onap/cps/ncmp/api/inventory/CmHandleState.java | 25 --- .../cps/ncmp/api/inventory/CompositeState.java | 144 ------------ .../ncmp/api/inventory/CompositeStateBuilder.java | 154 ------------- .../ncmp/api/inventory/CompositeStateUtils.java | 107 --------- .../cps/ncmp/api/inventory/DataStoreSyncState.java | 25 --- .../ncmp/api/inventory/InventoryPersistence.java | 203 ----------------- .../api/inventory/InventoryPersistenceImpl.java | 250 --------------------- .../cps/ncmp/api/inventory/LockReasonCategory.java | 25 --- .../api/inventory/ModelledDmiServiceLeaves.java | 38 ---- .../cps/ncmp/api/inventory/enums/PropertyType.java | 34 --- .../ncmp/api/inventory/sync/DataSyncWatchdog.java | 100 --------- .../ncmp/api/inventory/sync/ModuleSyncService.java | 97 -------- .../ncmp/api/inventory/sync/ModuleSyncTasks.java | 122 ---------- .../api/inventory/sync/ModuleSyncWatchdog.java | 139 ------------ .../cps/ncmp/api/inventory/sync/SyncUtils.java | 203 ----------------- .../sync/config/WatchdogSchedulingConfigurer.java | 56 ----- .../inventory/sync/executor/AsyncTaskExecutor.java | 77 ------- .../cps/ncmp/api/models/NcmpServiceCmHandle.java | 4 +- .../onap/cps/ncmp/init/InventoryModelLoader.java | 13 +- .../cps/ncmp/init/SubscriptionModelLoader.java | 11 +- 61 files changed, 2200 insertions(+), 2146 deletions(-) delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/constants/DmiRegistryConstants.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java create mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueries.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleState.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeState.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/LockReasonCategory.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/ModelledDmiServiceLeaves.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/enums/PropertyType.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncService.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasks.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurer.java delete mode 100644 cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutor.java (limited to 'cps-ncmp-service/src/main/java') diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java index a65e3c4be..e7ffaa624 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java @@ -25,8 +25,8 @@ package org.onap.cps.ncmp.api; import java.util.Collection; import java.util.Map; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; import org.onap.cps.ncmp.api.impl.operations.OperationType; -import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; import org.onap.cps.ncmp.api.models.DataOperationRequest; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java index 1d390f8d1..58732b207 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java @@ -20,6 +20,7 @@ package org.onap.cps.ncmp.api.impl; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES; import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH; @@ -41,12 +42,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.cpspath.parser.PathParsingException; import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType; import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleQueries; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.inventory.enums.PropertyType; import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.exceptions.DataValidationException; @@ -198,12 +199,12 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH } private Collection getAllCmHandles() { - final DataNode dataNode = inventoryPersistence.getDataNode("/dmi-registry").iterator().next(); + final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next(); return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet()); } private Collection getAllCmHandleIds() { - final DataNode dataNode = inventoryPersistence.getDataNode("/dmi-registry", DIRECT_CHILDREN_ONLY) + final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY) .iterator().next(); return collectCmHandleIdsFromDataNodes(dataNode.getChildDataNodes()); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index f8b4b3326..f8adde85f 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -24,7 +24,8 @@ package org.onap.cps.ncmp.api.impl; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCmHandleQueryParameters; import com.google.common.collect.Lists; @@ -44,6 +45,12 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils; +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; import org.onap.cps.ncmp.api.impl.operations.OperationType; import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel; @@ -51,12 +58,6 @@ import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions; import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleQueries; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; @@ -377,7 +378,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private void deleteCmHandleFromDbAndModuleSyncMap(final String cmHandleId) { inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId); - inventoryPersistence.deleteDataNode("/dmi-registry/cm-handles[@id='" + cmHandleId + "']"); + inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + + "']"); removeDeletedCmHandleFromModuleSyncMap(cmHandleId); } @@ -389,8 +391,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private Collection mapCmHandleIdsToXpaths(final Collection cmHandles) { return cmHandles.stream() - .map(cmHandleId -> "/dmi-registry/cm-handles[@id='" + cmHandleId + "']") - .collect(Collectors.toSet()); + .map(cmHandleId -> NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']") + .collect(Collectors.toSet()); } // CPS-1239 Robustness cleaning of in progress cache diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java index bbb2c0f56..2f61b228b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-2023 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * Modifications Copyright (C) 2023 TechMahindra Ltd. * ================================================================================ @@ -36,7 +36,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java index 5540ecd21..d8353f302 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation + * Copyright (C) 2022-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. @@ -20,7 +20,7 @@ package org.onap.cps.ncmp.api.impl; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/constants/DmiRegistryConstants.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/constants/DmiRegistryConstants.java deleted file mode 100644 index a133cfb80..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/constants/DmiRegistryConstants.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.impl.constants; - -import java.time.OffsetDateTime; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -/** - * DmiRegistryConstants class to be strictly used for DMI Related constants only. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class DmiRegistryConstants { - - public static final String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational"; - - public static final OffsetDateTime NO_TIMESTAMP = null; -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java index ea2d17d3a..5f26db335 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java @@ -36,13 +36,13 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.config.embeddedcache.ForwardedSubscriptionEventCacheConfig; import org.onap.cps.ncmp.api.impl.events.EventsPublisher; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence; import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus; import org.onap.cps.ncmp.api.impl.utils.CmSubscriptionEventCloudMapper; import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.CmSubscriptionEvent; import org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent; import org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_dmi.CmHandle; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java index 2ae118872..fdee28e33 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java @@ -21,8 +21,8 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import java.util.Map; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; /** * The implementation of it should handle the persisting of composite state and delegate the request to publish the diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java index ce19712c0..02368b857 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java @@ -20,10 +20,10 @@ package org.onap.cps.ncmp.api.impl.events.lcm; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.LOCKED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY; import io.micrometer.core.annotation.Timed; import java.util.ArrayList; @@ -36,12 +36,12 @@ import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java index d3b45d4a6..19d9ba5c0 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java @@ -23,7 +23,7 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.CREATE; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.DELETE; import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.UPDATE; -import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETED; +import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED; import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java new file mode 100644 index 000000000..4776788c8 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java @@ -0,0 +1,87 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; + +public interface CmHandleQueries { + + /** + * Query CmHandles based on additional (private) properties. + * + * @param additionalPropertyQueryPairs private properties for query + * @return Ids of CmHandles which have these private properties + */ + Collection queryCmHandleAdditionalProperties(Map additionalPropertyQueryPairs); + + /** + * Query CmHandles based on public properties. + * + * @param publicPropertyQueryPairs public properties for query + * @return CmHandles which have these public properties + */ + Collection queryCmHandlePublicProperties(Map publicPropertyQueryPairs); + + /** + * Method which returns cm handles by the cm handles state. + * + * @param cmHandleState cm handle state + * @return a list of cm handles + */ + List queryCmHandlesByState(CmHandleState cmHandleState); + + /** + * Method to return data nodes representing the cm handles. + * + * @param cpsPath cps path for which the cmHandle is requested + * @return a list of data nodes representing the cm handles. + */ + List queryCmHandleDataNodesByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption); + + /** + * Method to check the state of a cm handle with given id. + * + * @param cmHandleId cm handle id + * @param requiredCmHandleState the required state of the cm handle + * @return a boolean, true if the state is equal to the required state + */ + boolean cmHandleHasState(String cmHandleId, CmHandleState requiredCmHandleState); + + /** + * Method which returns cm handles by the operational sync state of cm handle. + * + * @param dataStoreSyncState sync state + * @return a list of cm handles + */ + List queryCmHandlesByOperationalSyncState(DataStoreSyncState dataStoreSyncState); + + /** + * Get all cm handles ids by DMI plugin identifier. + * + * @param dmiPluginIdentifier DMI plugin identifier + * @return collection of cm handles + */ + Collection getCmHandleIdsByDmiPluginIdentifier(String dmiPluginIdentifier); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java new file mode 100644 index 000000000..b3ade4f1c --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java @@ -0,0 +1,145 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * Modifications Copyright (C) 2023 TechMahindra Ltd. + * ================================================================================ + * 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.cps.ncmp.api.impl.inventory; + +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType; +import org.onap.cps.spi.CpsDataPersistenceService; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +public class CmHandleQueriesImpl implements CmHandleQueries { + + private static final String DESCENDANT_PATH = "//"; + + private final CpsDataPersistenceService cpsDataPersistenceService; + private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles"; + + @Override + public Collection queryCmHandleAdditionalProperties(final Map privatePropertyQueryPairs) { + return queryCmHandleAnyProperties(privatePropertyQueryPairs, PropertyType.ADDITIONAL); + } + + @Override + public Collection queryCmHandlePublicProperties(final Map publicPropertyQueryPairs) { + return queryCmHandleAnyProperties(publicPropertyQueryPairs, PropertyType.PUBLIC); + } + + @Override + public List queryCmHandlesByState(final CmHandleState cmHandleState) { + return queryCmHandleDataNodesByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]", + INCLUDE_ALL_DESCENDANTS); + } + + @Override + public List queryCmHandleDataNodesByCpsPath(final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption); + } + + @Override + public boolean cmHandleHasState(final String cmHandleId, final CmHandleState requiredCmHandleState) { + final DataNode stateDataNode = getCmHandleState(cmHandleId); + final String cmHandleStateAsString = (String) stateDataNode.getLeaves().get("cm-handle-state"); + return CmHandleState.valueOf(cmHandleStateAsString).equals(requiredCmHandleState); + } + + @Override + public List queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) { + return queryCmHandleDataNodesByCpsPath("//state/datastores" + "/operational[@sync-state=\"" + + dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS); + } + + @Override + public Collection getCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) { + final Collection cmHandleIds = new HashSet<>(); + for (final ModelledDmiServiceLeaves modelledDmiServiceLeaf : ModelledDmiServiceLeaves.values()) { + for (final DataNode cmHandleAsDataNode: getCmHandlesByDmiPluginIdentifierAndDmiProperty( + dmiPluginIdentifier, + modelledDmiServiceLeaf.getLeafName())) { + cmHandleIds.add(cmHandleAsDataNode.getLeaves().get("id").toString()); + } + } + return cmHandleIds; + } + + private Collection collectCmHandleIdsFromDataNodes(final Collection dataNodes) { + return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); + } + + private Collection queryCmHandleAnyProperties( + final Map propertyQueryPairs, + final PropertyType propertyType) { + if (propertyQueryPairs.isEmpty()) { + return Collections.emptySet(); + } + Collection cmHandleIds = null; + for (final Map.Entry publicPropertyQueryPair : propertyQueryPairs.entrySet()) { + final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\"" + + publicPropertyQueryPair.getKey() + + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; + + final Collection dataNodes = queryCmHandleDataNodesByCpsPath(cpsPath, OMIT_DESCENDANTS); + if (cmHandleIds == null) { + cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes); + } else { + final Collection cmHandleIdsToRetain = collectCmHandleIdsFromDataNodes(dataNodes); + cmHandleIds.retainAll(cmHandleIdsToRetain); + } + if (cmHandleIds.isEmpty()) { + break; + } + } + return cmHandleIds; + } + + private List getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier, + final String dmiProperty) { + return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']", + OMIT_DESCENDANTS); + } + + private DataNode getCmHandleState(final String cmHandleId) { + final String xpath = NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']/state"; + return cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + xpath, OMIT_DESCENDANTS).iterator().next(); + } +} + + diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java new file mode 100644 index 000000000..5485ee7e8 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java @@ -0,0 +1,25 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +public enum CmHandleState { + ADVISED, READY, LOCKED, DELETING, DELETED +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java new file mode 100644 index 000000000..5b88f560e --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java @@ -0,0 +1,144 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * State Model to store state corresponding to the Yang resource dmi-registry model. + */ +@Getter +@Setter +@NoArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CompositeState { + + @JsonProperty("cm-handle-state") + private CmHandleState cmHandleState; + + @JsonProperty("lock-reason") + private LockReason lockReason; + + @JsonProperty("last-update-time") + private String lastUpdateTime; + + @JsonProperty("data-sync-enabled") + private Boolean dataSyncEnabled; + + @JsonProperty("datastores") + private DataStores dataStores; + + /** + * Date and Time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ + */ + private static final DateTimeFormatter dateTimeFormatter = + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + + /** + * Composite State copy constructor. + * + * @param compositeState Composite State + */ + public CompositeState(final CompositeState compositeState) { + this.cmHandleState = compositeState.getCmHandleState(); + this.lockReason = compositeState.getLockReason(); + this.lastUpdateTime = compositeState.getLastUpdateTime(); + this.dataSyncEnabled = compositeState.getDataSyncEnabled(); + this.dataStores = compositeState.getDataStores(); + } + + + /** + * This will specify the latest lock reason for a specific cm handle. If a cm handle is in a state other than LOCKED + * it specifies the last lock reason. + * This can be used to track retry attempts as part of the lock details. + */ + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class LockReason { + + @JsonProperty("reason") + private LockReasonCategory lockReasonCategory; + + @JsonProperty("details") + private String details; + + } + + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class DataStores { + + @JsonProperty("operational") + private Operational operationalDataStore; + } + + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Operational { + + @JsonProperty("sync-state") + private DataStoreSyncState dataStoreSyncState; + + @JsonProperty("last-sync-time") + private String lastSyncTime; + } + + @Data + @Builder + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Running { + + @JsonProperty("sync-state") + private String syncState; + + @JsonProperty("last-sync-time") + private String lastSyncTime; + } + + /** + * The date and time format used for the cm handle sync state. + * + * @return the date and time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ + */ + public static String nowInSyncTimeFormat() { + return dateTimeFormatter.format(OffsetDateTime.now()); + } + + /** + * Sets the last updated date and time for the cm handle sync state. + */ + public void setLastUpdateTimeNow() { + lastUpdateTime = CompositeState.nowInSyncTimeFormat(); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java new file mode 100644 index 000000000..2fbe2b2f7 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java @@ -0,0 +1,154 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Bell Canada + * Modifications Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +import org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState.LockReason; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational; +import org.onap.cps.spi.model.DataNode; + +public class CompositeStateBuilder { + + private CmHandleState cmHandleState; + private LockReason lockReason; + private DataStores datastores; + private String lastUpdatedTime; + private Boolean dataSyncEnabled; + + /** + * To create the {@link CompositeState}. + * + * @return {@link DataNode} + */ + public CompositeState build() { + final CompositeState compositeState = new CompositeState(); + compositeState.setCmHandleState(cmHandleState); + compositeState.setLockReason(lockReason); + compositeState.setDataStores(datastores); + compositeState.setLastUpdateTime(lastUpdatedTime); + compositeState.setDataSyncEnabled(dataSyncEnabled); + return compositeState; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param cmHandleState for the data node + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withCmHandleState(final CmHandleState cmHandleState) { + this.cmHandleState = cmHandleState; + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param reason for the locked state + * @param details for the locked state + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withLockReason(final LockReasonCategory reason, final String details) { + this.lockReason = LockReason.builder().lockReasonCategory(reason).details(details).build(); + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param time for the state change + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withLastUpdatedTime(final String time) { + this.lastUpdatedTime = time; + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @return composite state builder + */ + public CompositeStateBuilder withLastUpdatedTimeNow() { + this.lastUpdatedTime = CompositeState.nowInSyncTimeFormat(); + return this; + } + + /** + * To use attributes for creating {@link CompositeState}. + * + * @param dataStoreSyncState for the locked state + * @param lastSyncTime for the locked state + * @return CompositeStateBuilder + */ + public CompositeStateBuilder withOperationalDataStores(final DataStoreSyncState dataStoreSyncState, + final String lastSyncTime) { + this.datastores = DataStores.builder().operationalDataStore( + Operational.builder().dataStoreSyncState(dataStoreSyncState).lastSyncTime(lastSyncTime).build()).build(); + return this; + } + + /** + * To use dataNode for creating {@link CompositeState}. + * + * @param dataNode for the dataNode + * @return CompositeState + */ + public CompositeStateBuilder fromDataNode(final DataNode dataNode) { + this.cmHandleState = CmHandleState.valueOf((String) dataNode.getLeaves() + .get("cm-handle-state")); + this.lastUpdatedTime = (String) dataNode.getLeaves().get("last-update-time"); + if (this.cmHandleState == CmHandleState.READY) { + this.dataSyncEnabled = (Boolean) dataNode.getLeaves().get("data-sync-enabled"); + } + for (final DataNode stateChildNode : dataNode.getChildDataNodes()) { + if (stateChildNode.getXpath().endsWith("/lock-reason")) { + this.lockReason = getLockReason(stateChildNode); + } + if (stateChildNode.getXpath().endsWith("/datastores")) { + for (final DataNode dataStoreNodes : stateChildNode.getChildDataNodes()) { + Operational operationalDataStore = null; + if (dataStoreNodes.getXpath().contains("/operational")) { + operationalDataStore = getOperationalDataStore(dataStoreNodes); + } + this.datastores = DataStores.builder().operationalDataStore(operationalDataStore).build(); + } + } + } + return this; + } + + private Operational getOperationalDataStore(final DataNode dataStoreNodes) { + return Operational.builder() + .dataStoreSyncState(DataStoreSyncState.valueOf((String) dataStoreNodes.getLeaves().get("sync-state"))) + .lastSyncTime((String) dataStoreNodes.getLeaves().get("last-sync-time")) + .build(); + } + + private LockReason getLockReason(final DataNode stateChildNode) { + final boolean isLockReasonExists = stateChildNode.getLeaves().containsKey("reason"); + return new LockReason(isLockReasonExists + ? LockReasonCategory.valueOf((String) stateChildNode.getLeaves().get("reason")) + : null, (String) stateChildNode.getLeaves().get("details")); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java new file mode 100644 index 000000000..ef4b299e1 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java @@ -0,0 +1,107 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +import java.util.function.Consumer; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * It will have all the utility method responsible for handling the composite state. + */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class CompositeStateUtils { + + /** + * Sets the cmHandleState to the provided state and updates the timestamp. + * + * @return Updated CompositeState + */ + public static Consumer setCompositeState(final CmHandleState cmHandleState) { + return compositeState -> { + compositeState.setCmHandleState(cmHandleState); + compositeState.setLastUpdateTimeNow(); + }; + } + + /** + * Set the Operational datastore sync state based on the global flag. + * + * @return Updated CompositeState + */ + public static Consumer setInitialDataStoreSyncState() { + + return compositeState -> { + compositeState.setDataSyncEnabled(false); + final CompositeState.Operational operational = + getInitialDataStoreSyncState(compositeState.getDataSyncEnabled()); + final CompositeState.DataStores dataStores = + CompositeState.DataStores.builder().operationalDataStore(operational).build(); + compositeState.setDataStores(dataStores); + }; + } + + /** + * Set the data sync enabled flag, along with the data store sync state based on this flag. + * + * @param dataSyncEnabled data sync enabled flag + * @param compositeState cm handle composite state + */ + public static void setDataSyncEnabledFlagWithDataSyncState(final boolean dataSyncEnabled, + final CompositeState compositeState) { + compositeState.setDataSyncEnabled(dataSyncEnabled); + compositeState.setLastUpdateTimeNow(); + final CompositeState.Operational operational = getInitialDataStoreSyncState(dataSyncEnabled); + final CompositeState.DataStores dataStores = + CompositeState.DataStores.builder().operationalDataStore(operational).build(); + compositeState.setDataStores(dataStores); + } + + /** + * Get initial data sync state based on data sync enabled boolean flag. + * + * @param dataSyncEnabled data sync enabled boolean flag + * @return the data store sync state + */ + private static CompositeState.Operational getInitialDataStoreSyncState(final boolean dataSyncEnabled) { + final DataStoreSyncState dataStoreSyncState = + dataSyncEnabled ? DataStoreSyncState.UNSYNCHRONIZED : DataStoreSyncState.NONE_REQUESTED; + return CompositeState.Operational.builder().dataStoreSyncState(dataStoreSyncState).build(); + } + + /** + * Sets the cmHandleState to ADVISED and retain the lock details. Used in retry scenarios. + * + * @return Updated CompositeState + */ + public static Consumer setCompositeStateForRetry() { + return compositeState -> { + compositeState.setCmHandleState(CmHandleState.ADVISED); + compositeState.setLastUpdateTimeNow(); + final String oldLockReasonDetails = compositeState.getLockReason().getDetails(); + final CompositeState.LockReason lockReason = + CompositeState.LockReason.builder().details(oldLockReasonDetails).build(); + compositeState.setLockReason(lockReason); + }; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java new file mode 100644 index 000000000..b92d152bf --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java @@ -0,0 +1,25 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +public enum DataStoreSyncState { + SYNCHRONIZED, UNSYNCHRONIZED, NONE_REQUESTED +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java new file mode 100644 index 000000000..09de9a7bf --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java @@ -0,0 +1,126 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * Modifications Copyright (C) 2023 TechMahindra Ltd. + * ================================================================================ + * 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.cps.ncmp.api.impl.inventory; + +import java.util.Collection; +import java.util.Map; +import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.ModuleDefinition; +import org.onap.cps.spi.model.ModuleReference; + +public interface InventoryPersistence extends NcmpPersistence { + + /** + * Get the Cm Handle Composite State from the data node. + * + * @param cmHandleId cm handle id + * @return the cm handle composite state + */ + CompositeState getCmHandleState(String cmHandleId); + + /** + * Save the cm handles state. + * + * @param cmHandleId cm handle id + * @param compositeState composite state + */ + void saveCmHandleState(String cmHandleId, CompositeState compositeState); + + /** + * Save all cm handles states in batch. + * + * @param cmHandleStatePerCmHandleId contains cm handle id and updated state + */ + void saveCmHandleStateBatch(Map cmHandleStatePerCmHandleId); + + /** + * This method retrieves DMI service name, DMI properties and the state for a given cm handle. + * + * @param cmHandleId the id of the cm handle + * @return yang model cm handle + */ + YangModelCmHandle getYangModelCmHandle(String cmHandleId); + + /** + * This method retrieves DMI service name, DMI properties and the state for a given cm handle. + * + * @param cmHandleIds a list of the ids of the cm handles + * @return collection of yang model cm handles + */ + Collection getYangModelCmHandles(Collection cmHandleIds); + + /** + * Method to return module definitions by cmHandleId. + * + * @param cmHandleId cm handle ID + * @return a collection of module definitions (moduleName, revision and yang resource content) + */ + Collection getModuleDefinitionsByCmHandleId(String cmHandleId); + + /** + * Method to return module references by cmHandleId. + * + * @param cmHandleId cm handle ID + * @return a collection of module references (moduleName and revision) + */ + Collection getYangResourcesModuleReferences(String cmHandleId); + + /** + * Method to save cmHandle. + * + * @param yangModelCmHandle cmHandle represented as Yang Model + */ + void saveCmHandle(YangModelCmHandle yangModelCmHandle); + + /** + * Method to save batch of cm handles. + * + * @param yangModelCmHandles cm handle represented as Yang Models + */ + void saveCmHandleBatch(Collection yangModelCmHandles); + + /** + * Get data node of given cm handle. + * + * @param cmHandleId cmHandle ID + * @return data node + */ + Collection getCmHandleDataNode(String cmHandleId); + + /** + * Get collection of data nodes of given cm handles. + * + * @param cmHandleIds collection of cmHandle IDs + * @return collection of data nodes + */ + Collection getCmHandleDataNodes(Collection cmHandleIds); + + /** + * get CM handles that has given module names. + * + * @param moduleNamesForQuery module names + * @return Collection of CM handle Ids + */ + Collection getCmHandleIdsWithGivenModules(Collection moduleNamesForQuery); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java new file mode 100644 index 000000000..159d8f345 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java @@ -0,0 +1,177 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada + * Modifications Copyright (C) 2023 TechMahindra Ltd. + * ================================================================================ + * 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.cps.ncmp.api.impl.inventory; + +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsAdminService; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.exceptions.DataValidationException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.model.ModuleDefinition; +import org.onap.cps.spi.model.ModuleReference; +import org.onap.cps.spi.utils.CpsValidator; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements InventoryPersistence { + + private final CpsModuleService cpsModuleService; + private final CpsAdminService cpsAdminService; + private final CpsValidator cpsValidator; + + /** + * initialize an inventory persistence object. + * + * @param jsonObjectMapper json mapper object + * @param cpsDataService cps data service instance + * @param cpsModuleService cps module service instance + * @param cpsValidator cps validation service instance + * @param cpsAdminService cps admin service instance + */ + public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService, + final CpsModuleService cpsModuleService, final CpsValidator cpsValidator, + final CpsAdminService cpsAdminService) { + super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator); + this.cpsModuleService = cpsModuleService; + this.cpsAdminService = cpsAdminService; + this.cpsValidator = cpsValidator; + } + + + @Override + public CompositeState getCmHandleState(final String cmHandleId) { + final DataNode stateAsDataNode = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + createCmHandleXPath(cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + .iterator().next(); + cpsValidator.validateNameCharacters(cmHandleId); + return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build(); + } + + @Override + public void saveCmHandleState(final String cmHandleId, final CompositeState compositeState) { + final String cmHandleJsonData = createStateJsonData(jsonObjectMapper.asJsonString(compositeState)); + cpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + createCmHandleXPath(cmHandleId), cmHandleJsonData, OffsetDateTime.now()); + } + + @Override + public void saveCmHandleStateBatch(final Map cmHandleStatePerCmHandleId) { + final Map cmHandlesJsonDataMap = new HashMap<>(); + cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> cmHandlesJsonDataMap.put( + createCmHandleXPath(cmHandleId), + createStateJsonData(jsonObjectMapper.asJsonString(compositeState)))); + cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + cmHandlesJsonDataMap, OffsetDateTime.now()); + } + + @Override + public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { + cpsValidator.validateNameCharacters(cmHandleId); + final DataNode dataNode = getCmHandleDataNode(cmHandleId).iterator().next(); + return YangDataConverter.convertCmHandleToYangModel(dataNode, cmHandleId); + } + + @Override + public Collection getYangModelCmHandles(final Collection cmHandleIds) { + final Collection validCmHandleIds = new ArrayList<>(cmHandleIds.size()); + cmHandleIds.forEach(cmHandleId -> { + try { + cpsValidator.validateNameCharacters(cmHandleId); + validCmHandleIds.add(cmHandleId); + } catch (final DataValidationException dataValidationException) { + log.error("DataValidationException in CmHandleId {} to be ignored", + dataValidationException.getMessage()); + } + }); + return YangDataConverter.convertDataNodesToYangModelCmHandles(getCmHandleDataNodes(validCmHandleIds)); + } + + @Override + public Collection getModuleDefinitionsByCmHandleId(final String cmHandleId) { + return cpsModuleService.getModuleDefinitionsByAnchorName(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); + } + + @Override + public Collection getYangResourcesModuleReferences(final String cmHandleId) { + cpsValidator.validateNameCharacters(cmHandleId); + return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); + } + + @Override + public void saveCmHandle(final YangModelCmHandle yangModelCmHandle) { + final String cmHandleJsonData = + createCmHandleJsonData(jsonObjectMapper.asJsonString(yangModelCmHandle)); + cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, + cmHandleJsonData, NO_TIMESTAMP); + } + + @Override + public void saveCmHandleBatch(final Collection yangModelCmHandles) { + final List cmHandlesJsonData = new ArrayList<>(); + yangModelCmHandles.forEach(yangModelCmHandle -> cmHandlesJsonData.add( + createCmHandleJsonData(jsonObjectMapper.asJsonString(yangModelCmHandle)))); + cpsDataService.saveListElementsBatch(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, + NCMP_DMI_REGISTRY_PARENT, cmHandlesJsonData, NO_TIMESTAMP); + } + + @Override + public Collection getCmHandleDataNode(final String cmHandleId) { + return this.getDataNode(createCmHandleXPath(cmHandleId)); + } + + @Override + public Collection getCmHandleDataNodes(final Collection cmHandleIds) { + final Collection xpaths = new ArrayList<>(cmHandleIds.size()); + cmHandleIds.forEach(cmHandleId -> xpaths.add(createCmHandleXPath(cmHandleId))); + return this.getDataNodes(xpaths); + } + + @Override + public Collection getCmHandleIdsWithGivenModules(final Collection moduleNamesForQuery) { + return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery); + } + + private static String createCmHandleXPath(final String cmHandleId) { + return NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"; + } + + private static String createStateJsonData(final String state) { + return "{\"state\":" + state + "}"; + } + + private static String createCmHandleJsonData(final String yangModelCmHandleAsJson) { + return "{\"cm-handles\":[" + yangModelCmHandleAsJson + "]}"; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java new file mode 100644 index 000000000..8306619f2 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java @@ -0,0 +1,25 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +public enum LockReasonCategory { + MODULE_SYNC_FAILED, MODULE_UPGRADE, MODULE_UPGRADE_FAILED +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java new file mode 100644 index 000000000..b8a1ba02d --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory; + +public enum ModelledDmiServiceLeaves { + DMI_SERVICE_NAME("dmi-service-name"), + DMI_DATA_SERVICE_NAME("dmi-data-service-name"), + DMI_MODEL_SERVICE_NAME("dmi-model-service-name"); + + private String leafName; + + ModelledDmiServiceLeaves(final String dmiPluginIdentifierKey) { + this.leafName = dmiPluginIdentifierKey; + } + + public String getLeafName() { + return leafName; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java new file mode 100644 index 000000000..6a2d6d810 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java @@ -0,0 +1,120 @@ +/* + * ============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.cps.ncmp.api.impl.inventory; + +import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; + +import io.micrometer.core.annotation.Timed; +import java.util.Collection; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.utils.CpsValidator; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class NcmpPersistenceImpl implements NcmpPersistence { + + protected final JsonObjectMapper jsonObjectMapper; + protected final CpsDataService cpsDataService; + private final CpsModuleService cpsModuleService; + private final CpsValidator cpsValidator; + + @Override + public void deleteListOrListElement(final String listElementXpath) { + cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, listElementXpath, + NO_TIMESTAMP); + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete", + description = "Time taken to delete a schemaset") + public void deleteSchemaSetWithCascade(final String schemaSetName) { + try { + cpsValidator.validateNameCharacters(schemaSetName); + cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, + CASCADE_DELETE_ALLOWED); + } catch (final SchemaSetNotFoundException schemaSetNotFoundException) { + log.warn("Schema set {} does not exist or already deleted", schemaSetName); + } + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete.batch", + description = "Time taken to delete multiple schemaset") + public void deleteSchemaSetsWithCascade(final Collection schemaSetNames) { + cpsValidator.validateNameCharacters(schemaSetNames); + cpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetNames); + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", + description = "Time taken to get a data node (from ncmp dmi registry)") + public Collection getDataNode(final String xpath) { + return getDataNode(xpath, INCLUDE_ALL_DESCENDANTS); + } + + @Override + @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", + description = "Time taken to get a data node (from ncmp dmi registry)") + public Collection getDataNode(final String xpath, final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpath, + fetchDescendantsOption); + } + + @Override + public Collection getDataNodes(final Collection xpaths) { + return getDataNodes(xpaths, INCLUDE_ALL_DESCENDANTS); + } + + @Override + public Collection getDataNodes(final Collection xpaths, + final FetchDescendantsOption fetchDescendantsOption) { + return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, xpaths, + fetchDescendantsOption); + } + + @Override + public void replaceListContent(final String parentNodeXpath, final Collection dataNodes) { + cpsDataService.replaceListContent(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, parentNodeXpath, dataNodes, + NO_TIMESTAMP); + } + + @Override + public void deleteDataNode(final String dataNodeXpath) { + cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath, NO_TIMESTAMP); + } + + @Override + public void deleteDataNodes(final Collection dataNodeXpaths) { + cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP); + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java new file mode 100644 index 000000000..08bfe98e5 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum PropertyType { + ADDITIONAL("additional-properties"), + PUBLIC("public-properties"), + DMI_PLUGIN("dmiPluginName"); + + private final String yangContainerName; +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java new file mode 100644 index 000000000..49804adc1 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java @@ -0,0 +1,102 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory.sync; + +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; + +import com.hazelcast.map.IMap; +import java.time.OffsetDateTime; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsDataService; +import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +public class DataSyncWatchdog { + + private static final boolean DATA_SYNC_IN_PROGRESS = false; + private static final boolean DATA_SYNC_DONE = true; + + private final InventoryPersistence inventoryPersistence; + + private final CpsDataService cpsDataService; + + private final SyncUtils syncUtils; + + private final IMap dataSyncSemaphores; + + /** + * Execute Cm Handle poll which queries the cm handle state in 'READY' and Operational Datastore Sync State in + * 'UNSYNCHRONIZED'. + */ + @Scheduled(fixedDelayString = "${ncmp.timers.cm-handle-data-sync.sleep-time-ms:30000}") + public void executeUnSynchronizedReadyCmHandlePoll() { + syncUtils.getUnsynchronizedReadyCmHandles().forEach(unSynchronizedReadyCmHandle -> { + final String cmHandleId = unSynchronizedReadyCmHandle.getId(); + if (hasPushedIntoSemaphoreMap(cmHandleId)) { + log.debug("Executing data sync on {}", cmHandleId); + final CompositeState compositeState = inventoryPersistence + .getCmHandleState(cmHandleId); + final String resourceData = syncUtils.getResourceData(cmHandleId); + if (resourceData == null) { + log.debug("Error retrieving resource data for Cm-Handle: {}", cmHandleId); + } else { + cpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, + resourceData, OffsetDateTime.now()); + setSyncStateToSynchronized().accept(compositeState); + inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); + updateDataSyncSemaphoreMap(cmHandleId); + } + } else { + log.debug("{} already processed by another instance", cmHandleId); + } + }); + log.debug("No Cm-Handles currently found in READY State and Operational Sync State is UNSYNCHRONIZED"); + } + + private Consumer setSyncStateToSynchronized() { + return compositeState -> { + compositeState.setLastUpdateTimeNow(); + compositeState.getDataStores() + .setOperationalDataStore(CompositeState.Operational.builder() + .dataStoreSyncState(DataStoreSyncState.SYNCHRONIZED) + .lastSyncTime(CompositeState.nowInSyncTimeFormat()).build()); + }; + } + + private void updateDataSyncSemaphoreMap(final String cmHandleId) { + dataSyncSemaphores.replace(cmHandleId, DATA_SYNC_DONE); + } + + private boolean hasPushedIntoSemaphoreMap(final String cmHandleId) { + return dataSyncSemaphores.putIfAbsent(cmHandleId, DATA_SYNC_IN_PROGRESS, + SynchronizationCacheConfig.DATA_SYNC_SEMAPHORE_TTL_SECS, TimeUnit.SECONDS) == null; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java new file mode 100644 index 000000000..b2949c278 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java @@ -0,0 +1,97 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory.sync; + +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsAdminService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.spi.CascadeDeleteAllowed; +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; +import org.onap.cps.spi.model.ModuleReference; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ModuleSyncService { + + private final DmiModelOperations dmiModelOperations; + private final CpsModuleService cpsModuleService; + + private final CpsAdminService cpsAdminService; + + /** + * This method registers a cm handle and initiates modules sync. + * + * @param yangModelCmHandle the yang model of cm handle. + */ + public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { + + final Collection allModuleReferencesFromCmHandle = + dmiModelOperations.getModuleReferences(yangModelCmHandle); + + final Collection identifiedNewModuleReferencesFromCmHandle = cpsModuleService + .identifyNewModuleReferences(allModuleReferencesFromCmHandle); + + final Map newModuleNameToContentMap; + if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) { + newModuleNameToContentMap = Collections.emptyMap(); + } else { + newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, + identifiedNewModuleReferencesFromCmHandle); + } + createSchemaSetAndAnchor(yangModelCmHandle, newModuleNameToContentMap, allModuleReferencesFromCmHandle); + } + + private void createSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle, + final Map newModuleNameToContentMap, + final Collection allModuleReferencesFromCmHandle) { + final String schemaSetAndAnchorName = yangModelCmHandle.getId(); + cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName, + newModuleNameToContentMap, allModuleReferencesFromCmHandle); + cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName, + schemaSetAndAnchorName); + } + + /** + * Deletes the SchemaSet for schema set id if the SchemaSet Exists. + * + * @param schemaSetId the schema set id to be deleted + */ + public void deleteSchemaSetIfExists(final String schemaSetId) { + try { + cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetId, + CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED); + log.debug("SchemaSet for {} has been deleted. Ready to be recreated.", schemaSetId); + } catch (final SchemaSetNotFoundException e) { + log.debug("No SchemaSet for {}. Assuming CmHandle has not been previously Module Synced.", schemaSetId); + } + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java new file mode 100644 index 000000000..7306f7174 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java @@ -0,0 +1,122 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory.sync; + +import com.hazelcast.map.IMap; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.spi.model.DataNode; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Slf4j +public class ModuleSyncTasks { + private final InventoryPersistence inventoryPersistence; + private final SyncUtils syncUtils; + private final ModuleSyncService moduleSyncService; + private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; + private final IMap moduleSyncStartedOnCmHandles; + + /** + * Perform module sync on a batch of cm handles. + * + * @param cmHandlesAsDataNodes a batch of Data nodes representing cm handles to perform module sync on + * @param batchCounter the number of batches currently being processed, will be decreased when + * task is finished or fails + * @return completed future to handle post-processing + */ + public CompletableFuture performModuleSync(final Collection cmHandlesAsDataNodes, + final AtomicInteger batchCounter) { + try { + final Map cmHandelStatePerCmHandle = new HashMap<>(); + for (final DataNode cmHandleAsDataNode : cmHandlesAsDataNodes) { + final String cmHandleId = String.valueOf(cmHandleAsDataNode.getLeaves().get("id")); + final YangModelCmHandle yangModelCmHandle = + YangDataConverter.convertCmHandleToYangModel(cmHandleAsDataNode, cmHandleId); + final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); + try { + moduleSyncService.deleteSchemaSetIfExists(cmHandleId); + moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle); + cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY); + } catch (final Exception e) { + log.warn("Processing of {} module sync failed due to reason {}.", cmHandleId, e.getMessage()); + syncUtils.updateLockReasonDetailsAndAttempts(compositeState, + LockReasonCategory.MODULE_SYNC_FAILED, e.getMessage()); + setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason()); + cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); + } + log.info("{} is now in {} state", cmHandleId, compositeState.getCmHandleState().name()); + } + lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandelStatePerCmHandle); + } finally { + batchCounter.getAndDecrement(); + log.info("Processing module sync batch finished. {} batch(es) active.", batchCounter.get()); + } + return CompletableFuture.completedFuture(null); + } + + /** + * Reset state to "ADVISED" for any previously failed cm handles. + * + * @param failedCmHandles previously failed (locked) cm handles + */ + public void resetFailedCmHandles(final List failedCmHandles) { + final Map cmHandleStatePerCmHandle = new HashMap<>(failedCmHandles.size()); + for (final YangModelCmHandle failedCmHandle : failedCmHandles) { + final CompositeState compositeState = failedCmHandle.getCompositeState(); + final boolean isReadyForRetry = syncUtils.needsModuleSyncRetry(compositeState); + log.info("Retry for cmHandleId : {} is {}", failedCmHandle.getId(), isReadyForRetry); + if (isReadyForRetry) { + final String resetCmHandleId = failedCmHandle.getId(); + log.debug("Reset cm handle {} state to ADVISED to be re-attempted by module-sync watchdog", + resetCmHandleId); + cmHandleStatePerCmHandle.put(failedCmHandle, CmHandleState.ADVISED); + removeResetCmHandleFromModuleSyncMap(resetCmHandleId); + } + } + lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); + } + + private void setCmHandleStateLocked(final YangModelCmHandle advisedCmHandle, + final CompositeState.LockReason lockReason) { + advisedCmHandle.getCompositeState().setLockReason(lockReason); + } + + private void removeResetCmHandleFromModuleSyncMap(final String resetCmHandleId) { + if (moduleSyncStartedOnCmHandles.remove(resetCmHandleId) != null) { + log.info("{} removed from in progress map", resetCmHandleId); + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java new file mode 100644 index 000000000..916fafd30 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java @@ -0,0 +1,139 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada + * ================================================================================ + * 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.cps.ncmp.api.impl.inventory.sync; + +import com.hazelcast.map.IMap; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; +import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.spi.model.DataNode; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +public class ModuleSyncWatchdog { + + private final SyncUtils syncUtils; + private final BlockingQueue moduleSyncWorkQueue; + private final IMap moduleSyncStartedOnCmHandles; + private final ModuleSyncTasks moduleSyncTasks; + private final AsyncTaskExecutor asyncTaskExecutor; + private static final int MODULE_SYNC_BATCH_SIZE = 100; + private static final long PREVENT_CPU_BURN_WAIT_TIME_MILLIS = 10; + private static final String VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP = "Started"; + private static final long ASYNC_TASK_TIMEOUT_IN_MILLISECONDS = TimeUnit.MINUTES.toMillis(5); + @Getter + private AtomicInteger batchCounter = new AtomicInteger(1); + + /** + * Check DB for any cm handles in 'ADVISED' state. + * Queue and create batches to process them asynchronously. + * This method will only finish when there are no more 'ADVISED' cm handles in the DB. + * This method wil be triggered on a configurable interval + */ + @Scheduled(fixedDelayString = "${ncmp.timers.advised-modules-sync.sleep-time-ms:5000}") + public void moduleSyncAdvisedCmHandles() { + log.info("Processing module sync watchdog waking up."); + populateWorkQueueIfNeeded(); + while (!moduleSyncWorkQueue.isEmpty()) { + if (batchCounter.get() <= asyncTaskExecutor.getAsyncTaskParallelismLevel()) { + final Collection nextBatch = prepareNextBatch(); + log.info("Processing module sync batch of {}. {} batch(es) active.", + nextBatch.size(), batchCounter.get()); + if (!nextBatch.isEmpty()) { + asyncTaskExecutor.executeTask(() -> + moduleSyncTasks.performModuleSync(nextBatch, batchCounter), + ASYNC_TASK_TIMEOUT_IN_MILLISECONDS); + batchCounter.getAndIncrement(); + } + } else { + preventBusyWait(); + } + } + } + + /** + * Find any failed (locked) cm handles and change state back to 'ADVISED'. + */ + @Scheduled(fixedDelayString = "${ncmp.timers.locked-modules-sync.sleep-time-ms:300000}") + public void resetPreviouslyFailedCmHandles() { + log.info("Processing module sync retry-watchdog waking up."); + final List failedCmHandles = syncUtils.getModuleSyncFailedCmHandles(); + log.info("Retrying {} cmHandles", failedCmHandles.size()); + moduleSyncTasks.resetFailedCmHandles(failedCmHandles); + } + + private void preventBusyWait() { + try { + log.info("Busy waiting now"); + TimeUnit.MILLISECONDS.sleep(PREVENT_CPU_BURN_WAIT_TIME_MILLIS); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private void populateWorkQueueIfNeeded() { + if (moduleSyncWorkQueue.isEmpty()) { + final List advisedCmHandles = syncUtils.getAdvisedCmHandles(); + log.info("Processing module sync fetched {} advised cm handles from DB", advisedCmHandles.size()); + for (final DataNode advisedCmHandle : advisedCmHandles) { + if (!moduleSyncWorkQueue.offer(advisedCmHandle)) { + log.warn("Unable to add cm handle {} to the work queue", advisedCmHandle.getLeaves().get("id")); + } + } + log.info("Work Queue Size : {}", moduleSyncWorkQueue.size()); + } + } + + private Collection prepareNextBatch() { + final Collection nextBatchCandidates = new HashSet<>(MODULE_SYNC_BATCH_SIZE); + final Collection nextBatch = new HashSet<>(MODULE_SYNC_BATCH_SIZE); + moduleSyncWorkQueue.drainTo(nextBatchCandidates, MODULE_SYNC_BATCH_SIZE); + log.info("nextBatchCandidates size : {}", nextBatchCandidates.size()); + for (final DataNode batchCandidate : nextBatchCandidates) { + final String cmHandleId = String.valueOf(batchCandidate.getLeaves().get("id")); + final boolean alreadyAddedToInProgressMap = VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP.equals( + moduleSyncStartedOnCmHandles.putIfAbsent(cmHandleId, VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP, + SynchronizationCacheConfig.MODULE_SYNC_STARTED_TTL_SECS, TimeUnit.SECONDS)); + if (alreadyAddedToInProgressMap) { + log.info("module sync for {} already in progress by other instance", cmHandleId); + } else { + log.info("Adding cmHandle : {} to current batch", cmHandleId); + nextBatch.add(batchCandidate); + } + } + log.debug("nextBatch size : {}", nextBatch.size()); + return nextBatch; + } + +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java new file mode 100644 index 000000000..c50bd4278 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java @@ -0,0 +1,201 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-2023 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada + * ================================================================================ + * 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.cps.ncmp.api.impl.inventory.sync; + +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL; + +import com.fasterxml.jackson.databind.JsonNode; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory; +import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; +import org.onap.cps.utils.JsonObjectMapper; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class SyncUtils { + + private final CmHandleQueries cmHandleQueries; + private final DmiDataOperations dmiDataOperations; + private final JsonObjectMapper jsonObjectMapper; + private static final Pattern retryAttemptPattern = Pattern.compile("^Attempt #(\\d+) failed:"); + + /** + * Query data nodes for cm handles with an "ADVISED" cm handle state. + * + * @return cm handles (data nodes) in ADVISED state (empty list if none found) + */ + public List getAdvisedCmHandles() { + final List advisedCmHandlesAsDataNodes = cmHandleQueries.queryCmHandlesByState(CmHandleState.ADVISED); + log.debug("Total number of fetched advised cm handle(s) is (are) {}", advisedCmHandlesAsDataNodes.size()); + return advisedCmHandlesAsDataNodes; + } + + /** + * First query data nodes for cm handles with CM Handle Operational Sync State in "UNSYNCHRONIZED" and + * randomly select a CM Handle and query the data nodes for CM Handle State in "READY". + * + * @return a randomized yang model cm handle list with State in READY and Operation Sync State in "UNSYNCHRONIZED", + * return empty list if not found + */ + public List getUnsynchronizedReadyCmHandles() { + final List unsynchronizedCmHandles = cmHandleQueries + .queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED); + + final List yangModelCmHandles = new ArrayList<>(); + for (final DataNode unsynchronizedCmHandle : unsynchronizedCmHandles) { + final String cmHandleId = unsynchronizedCmHandle.getLeaves().get("id").toString(); + if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) { + yangModelCmHandles.addAll( + convertCmHandlesDataNodesToYangModelCmHandles( + Collections.singletonList(unsynchronizedCmHandle))); + } + } + + Collections.shuffle(yangModelCmHandles); + + return yangModelCmHandles; + } + + /** + * Query data nodes for cm handles with an "LOCKED" cm handle state with reason MODULE_SYNC_FAILED". + * + * @return a random LOCKED yang model cm handle, return null if not found + */ + public List getModuleSyncFailedCmHandles() { + final List lockedCmHandlesAsDataNodeList = cmHandleQueries.queryCmHandleDataNodesByCpsPath( + "//lock-reason[@reason=\"MODULE_SYNC_FAILED\"]", + FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); + return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList); + } + + /** + * Update Composite State attempts counter and set new lock reason and details. + * + * @param lockReasonCategory lock reason category + * @param errorMessage error message + */ + public void updateLockReasonDetailsAndAttempts(final CompositeState compositeState, + final LockReasonCategory lockReasonCategory, + final String errorMessage) { + int attempt = 1; + if (compositeState.getLockReason() != null) { + final Matcher matcher = retryAttemptPattern.matcher(compositeState.getLockReason().getDetails()); + if (matcher.find()) { + attempt = 1 + Integer.parseInt(matcher.group(1)); + } + } + compositeState.setLockReason(CompositeState.LockReason.builder() + .details(String.format("Attempt #%d failed: %s", attempt, errorMessage)) + .lockReasonCategory(lockReasonCategory).build()); + } + + + /** + * Check if a module sync retry is needed. + * + * @param compositeState the composite state currently in the locked state + * @return if the retry mechanism should be attempted + */ + public boolean needsModuleSyncRetry(final CompositeState compositeState) { + final OffsetDateTime time = + OffsetDateTime.parse(compositeState.getLastUpdateTime(), + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); + final Matcher matcher = retryAttemptPattern.matcher(compositeState.getLockReason().getDetails()); + final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED + == compositeState.getLockReason().getLockReasonCategory(); + if (!failedDuringModuleSync) { + log.info("Locked for other reason"); + return false; + } + final int timeInMinutesUntilNextAttempt; + if (matcher.find()) { + timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1))); + } else { + timeInMinutesUntilNextAttempt = 1; + log.info("First Attempt: no current attempts found."); + } + final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes(); + if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) { + log.info("Time until next attempt is {} minutes: ", + timeInMinutesUntilNextAttempt - timeSinceLastAttempt); + return false; + } + log.info("Retry due now"); + return true; + } + + /** + * Get the Resourece Data from Node through DMI Passthrough service. + * + * @param cmHandleId cm handle id + * @return optional string containing the resource data + */ + public String getResourceData(final String cmHandleId) { + final ResponseEntity resourceDataResponseEntity = dmiDataOperations.getResourceDataFromDmi( + PASSTHROUGH_OPERATIONAL.getDatastoreName(), + cmHandleId, + UUID.randomUUID().toString()); + if (resourceDataResponseEntity.getStatusCode().is2xxSuccessful()) { + return getFirstResource(resourceDataResponseEntity.getBody()); + } + return null; + } + + private String getFirstResource(final Object responseBody) { + final String jsonObjectAsString = jsonObjectMapper.asJsonString(responseBody); + final JsonNode overallJsonNode = jsonObjectMapper.convertToJsonNode(jsonObjectAsString); + final Iterator> overallJsonTreeMap = overallJsonNode.fields(); + final Map.Entry firstElement = overallJsonTreeMap.next(); + return jsonObjectMapper.asJsonString(Map.of(firstElement.getKey(), firstElement.getValue())); + } + + private static List convertCmHandlesDataNodesToYangModelCmHandles( + final List cmHandlesAsDataNodeList) { + return cmHandlesAsDataNodeList.stream() + .map(cmHandle -> YangDataConverter.convertCmHandleToYangModel(cmHandle, + cmHandle.getLeaves().get("id").toString())).collect(Collectors.toList()); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java new file mode 100644 index 000000000..1aaee2708 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory.sync.config; + +import java.util.concurrent.ThreadPoolExecutor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +@Configuration +@EnableScheduling +public class WatchdogSchedulingConfigurer implements SchedulingConfigurer { + + @Override + public void configureTasks(final ScheduledTaskRegistrar scheduledTaskRegistrar) { + scheduledTaskRegistrar.setTaskScheduler(taskScheduler()); + } + + /** + * Implementation of Spring's {@link TaskScheduler} interface, wrapping + * a native {@link org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler} for watchdogs. + */ + @Bean + public TaskScheduler taskScheduler() { + final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setPoolSize(10); + taskScheduler.setThreadNamePrefix("watchdog-th-"); + taskScheduler.setAwaitTerminationSeconds(60); + taskScheduler.setWaitForTasksToCompleteOnShutdown(true); + taskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); + taskScheduler.initialize(); + return taskScheduler; + } +} \ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java new file mode 100644 index 000000000..2d5e7a1ab --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java @@ -0,0 +1,77 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.inventory.sync.executor; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import jakarta.annotation.PostConstruct; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class AsyncTaskExecutor { + + @Value("${ncmp.modules-sync-watchdog.async-executor.parallelism-level:10}") + @Getter + private int asyncTaskParallelismLevel; + private ExecutorService executorService; + private static final int DEFAULT_PARALLELISM_LEVEL = 10; + + /** + * Set up executor service with thread-pool size as per configuration parameter. + * If modules-sync-watchdog.async-executor.parallelism-level not set a default of 10 threads will be applied. + */ + @PostConstruct + public void setupThreadPool() { + executorService = Executors.newWorkStealingPool( + asyncTaskParallelismLevel == 0 ? DEFAULT_PARALLELISM_LEVEL : asyncTaskParallelismLevel); + } + + /** + * Execute supplied task asynchronously. + * + * @param taskSupplier functional method is get() task need to executed asynchronously + * @param timeOutInMillis the task timeout value in milliseconds + */ + public void executeTask(final Supplier taskSupplier, final long timeOutInMillis) { + CompletableFuture.supplyAsync(taskSupplier::get, executorService) + .orTimeout(timeOutInMillis, MILLISECONDS) + .whenCompleteAsync(this::handleTaskCompletion); + } + + private void handleTaskCompletion(final Object response, final Throwable throwable) { + if (throwable != null) { + if (throwable instanceof TimeoutException) { + log.warn("Async task didn't completed within the required time."); + } else { + log.debug("Watchdog async batch failed. caused by : {}", throwable.getMessage()); + } + } + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java new file mode 100644 index 000000000..d72b5d58f --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java @@ -0,0 +1,116 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022-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.cps.ncmp.api.impl.ncmppersistence; + +import java.time.OffsetDateTime; +import java.util.Collection; +import org.onap.cps.spi.FetchDescendantsOption; +import org.onap.cps.spi.model.DataNode; + +/** + * DmiRegistryConstants class to be strictly used for DMI Related constants only. + */ +public interface NcmpPersistence { + + String NCMP_DATASPACE_NAME = "NCMP-Admin"; + String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; + String NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME = "NFP-Operational"; + String NCMP_DMI_REGISTRY_PARENT = "/dmi-registry"; + OffsetDateTime NO_TIMESTAMP = null; + + /** + * Method to delete a list or a list element. + * + * @param listElementXpath list element xPath + */ + void deleteListOrListElement(String listElementXpath); + + /** + * Method to delete a schema set. + * + * @param schemaSetName schema set name + */ + void deleteSchemaSetWithCascade(String schemaSetName); + + /** + * Method to delete multiple schema sets. + * + * @param schemaSetNames schema set names + */ + void deleteSchemaSetsWithCascade(Collection schemaSetNames); + + /** + * Get data node via xpath. + * + * @param xpath xpath + * @return data node + */ + Collection getDataNode(String xpath); + + /** + * Get data node via xpath. + * + * @param xpath xpath + * @param fetchDescendantsOption fetch descendants option + * @return data node + */ + Collection getDataNode(String xpath, FetchDescendantsOption fetchDescendantsOption); + + /** + * Get collection of data nodes via xpaths. + * + * @param xpaths collection of xpaths + * @return collection of data nodes + */ + Collection getDataNodes(Collection xpaths); + + /** + * Get collection of data nodes via xpaths. + * + * @param xpaths collection of xpaths + * @param fetchDescendantsOption fetch descendants option + * @return collection of data nodes + */ + Collection getDataNodes(Collection xpaths, + FetchDescendantsOption fetchDescendantsOption); + + /** + * Replaces list content by removing all existing elements and inserting the given new elements as data nodes. + * + * @param parentNodeXpath parent node xpath + * @param dataNodes datanodes representing the updated data + */ + void replaceListContent(String parentNodeXpath, Collection dataNodes); + + /** + * Deletes data node. + * + * @param dataNodeXpath data node xpath + */ + void deleteDataNode(String dataNodeXpath); + + /** + * Deletes multiple data nodes. + * + * @param dataNodeXpaths data node xpaths + */ + void deleteDataNodes(Collection dataNodeXpaths); +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java index ba6f89192..8f76a45e0 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java @@ -35,11 +35,11 @@ import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException; import org.onap.cps.ncmp.api.impl.executor.TaskExecutor; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; import org.onap.cps.ncmp.api.impl.utils.data.operation.ResourceDataOperationRequestUtils; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.DataOperationRequest; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.utils.JsonObjectMapper; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java index 1bbd72564..32b5cb730 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java @@ -32,9 +32,9 @@ import java.util.List; import java.util.Map; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.YangResource; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.utils.JsonObjectMapper; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java index 7e9079ec9..c8d73eac6 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java @@ -24,8 +24,8 @@ package org.onap.cps.ncmp.api.impl.operations; import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; +import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java index 27d426656..8092e3951 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java @@ -21,10 +21,11 @@ package org.onap.cps.ncmp.api.impl.subscriptions; import java.util.Collection; +import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent; import org.onap.cps.spi.model.DataNode; -public interface SubscriptionPersistence { +public interface SubscriptionPersistence extends NcmpPersistence { /** * Save subscription Event. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java index 83a375b1b..dd0c20d59 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java @@ -20,42 +20,43 @@ package org.onap.cps.ncmp.api.impl.subscriptions; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP; - -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; +import org.onap.cps.api.CpsModuleService; +import org.onap.cps.ncmp.api.impl.inventory.NcmpPersistenceImpl; import org.onap.cps.ncmp.api.impl.utils.DataNodeHelper; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; +import org.onap.cps.spi.utils.CpsValidator; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.stereotype.Component; @Slf4j -@RequiredArgsConstructor @Component -public class SubscriptionPersistenceImpl implements SubscriptionPersistence { +public class SubscriptionPersistenceImpl extends NcmpPersistenceImpl implements SubscriptionPersistence { - private static final String SUBSCRIPTION_DATASPACE_NAME = "NCMP-Admin"; private static final String SUBSCRIPTION_ANCHOR_NAME = "AVC-Subscriptions"; private static final String SUBSCRIPTION_REGISTRY_PARENT = "/subscription-registry"; - private final JsonObjectMapper jsonObjectMapper; - private final CpsDataService cpsDataService; + + public SubscriptionPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService, + final CpsModuleService cpsModuleService, final CpsValidator cpsValidator) { + super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator); + } + @Override public void saveSubscriptionEvent(final YangModelSubscriptionEvent yangModelSubscriptionEvent) { final String clientId = yangModelSubscriptionEvent.getClientId(); final String subscriptionName = yangModelSubscriptionEvent.getSubscriptionName(); - final Collection dataNodes = cpsDataService.getDataNodes(SUBSCRIPTION_DATASPACE_NAME, + final Collection dataNodes = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); if (isSubscriptionRegistryEmptyOrNonExist(dataNodes, clientId, subscriptionName)) { @@ -74,8 +75,7 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final Map> cmHandleIdToStatusAndDetailsAsMapOriginal = DataNodeHelper.cmHandleIdToStatusAndDetailsAsMapFromDataNode(dataNodes); - final Map> newTargetCmHandles = - mapDifference(cmHandleIdToStatusAndDetailsAsMapNew, + final Map> newTargetCmHandles = mapDifference(cmHandleIdToStatusAndDetailsAsMapNew, cmHandleIdToStatusAndDetailsAsMapOriginal); traverseCmHandleList(newTargetCmHandles, clientId, subscriptionName, true); @@ -88,7 +88,7 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final YangModelSubscriptionEvent yangModelSubscriptionEvent) { return yangModelSubscriptionEvent.getPredicates().getTargetCmHandles() .stream().collect( - HashMap>::new, + HashMap::new, (result, cmHandle) -> { final String cmHandleId = cmHandle.getCmHandleId(); final SubscriptionStatus status = cmHandle.getStatus(); @@ -130,34 +130,31 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final boolean isAddListElementOperation) { if (isAddListElementOperation) { log.info("targetCmHandleAsJson to be added into DB {}", targetCmHandleAsJson); - cpsDataService.saveListElements(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, createCmHandleXpathPredicates(clientId, subscriptionName), - targetCmHandleAsJson, NO_TIMESTAMP); + cpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + createCmHandleXpathPredicates(clientId, subscriptionName), targetCmHandleAsJson, NO_TIMESTAMP); } else { log.info("targetCmHandleAsJson to be updated into DB {}", targetCmHandleAsJson); - cpsDataService.updateNodeLeaves(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, createCmHandleXpathPredicates(clientId, subscriptionName), - targetCmHandleAsJson, NO_TIMESTAMP); + cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + createCmHandleXpathPredicates(clientId, subscriptionName), targetCmHandleAsJson, NO_TIMESTAMP); } } private void saveSubscriptionEventYangModel(final String subscriptionEventJsonData) { log.info("SubscriptionEventJsonData to be saved into DB {}", subscriptionEventJsonData); - cpsDataService.saveListElements(SUBSCRIPTION_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + cpsDataService.saveListElements(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, subscriptionEventJsonData, NO_TIMESTAMP); } @Override public Collection getDataNodesForSubscriptionEvent() { - return cpsDataService.getDataNodes(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, SUBSCRIPTION_REGISTRY_PARENT, - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); + return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + SUBSCRIPTION_REGISTRY_PARENT, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } @Override public Collection getCmHandlesForSubscriptionEvent(final String clientId, final String subscriptionName) { - return cpsDataService.getDataNodesForMultipleXpaths(SUBSCRIPTION_DATASPACE_NAME, - SUBSCRIPTION_ANCHOR_NAME, Arrays.asList(createCmHandleXpath(clientId, subscriptionName)), + return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME, + List.of(createCmHandleXpath(clientId, subscriptionName)), FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } @@ -168,8 +165,8 @@ public class SubscriptionPersistenceImpl implements SubscriptionPersistence { final Map statusAndDetailsMap = entry.getValue(); final String status = statusAndDetailsMap.get("status"); final String details = statusAndDetailsMap.get("details"); - return new YangModelSubscriptionEvent.TargetCmHandle(cmHandleId, - SubscriptionStatus.fromString(status), details); + return new YangModelSubscriptionEvent.TargetCmHandle(cmHandleId, SubscriptionStatus.fromString(status), + details); }).collect(Collectors.toList()); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java index 746630898..1b190759e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java @@ -30,9 +30,9 @@ import java.util.regex.Pattern; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.model.DataNode; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java index c455337ac..e95d4f4c7 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java @@ -34,12 +34,12 @@ import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.NcmpEventResponseCode; import org.onap.cps.ncmp.api.impl.events.EventsPublisher; +import org.onap.cps.ncmp.api.impl.inventory.CmHandleState; import org.onap.cps.ncmp.api.impl.operations.CmHandle; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation; import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer; import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; import org.onap.cps.ncmp.api.models.DataOperationDefinition; import org.onap.cps.ncmp.api.models.DataOperationRequest; import org.springframework.scheduling.annotation.Async; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java index a6f953aa8..52fc81f50 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java @@ -34,8 +34,8 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService; -import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; /** diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueries.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueries.java deleted file mode 100644 index ff78f0022..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueries.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-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.cps.ncmp.api.inventory; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; - -public interface CmHandleQueries { - - /** - * Query CmHandles based on additional (private) properties. - * - * @param additionalPropertyQueryPairs private properties for query - * @return Ids of CmHandles which have these private properties - */ - Collection queryCmHandleAdditionalProperties(Map additionalPropertyQueryPairs); - - /** - * Query CmHandles based on public properties. - * - * @param publicPropertyQueryPairs public properties for query - * @return CmHandles which have these public properties - */ - Collection queryCmHandlePublicProperties(Map publicPropertyQueryPairs); - - /** - * Method which returns cm handles by the cm handles state. - * - * @param cmHandleState cm handle state - * @return a list of cm handles - */ - List queryCmHandlesByState(CmHandleState cmHandleState); - - /** - * Method to return data nodes representing the cm handles. - * - * @param cpsPath cps path for which the cmHandle is requested - * @return a list of data nodes representing the cm handles. - */ - List queryCmHandleDataNodesByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption); - - /** - * Method to check the state of a cm handle with given id. - * - * @param cmHandleId cm handle id - * @param requiredCmHandleState the required state of the cm handle - * @return a boolean, true if the state is equal to the required state - */ - boolean cmHandleHasState(String cmHandleId, CmHandleState requiredCmHandleState); - - /** - * Method which returns cm handles by the operational sync state of cm handle. - * - * @param dataStoreSyncState sync state - * @return a list of cm handles - */ - List queryCmHandlesByOperationalSyncState(DataStoreSyncState dataStoreSyncState); - - /** - * Get all cm handles ids by DMI plugin identifier. - * - * @param dmiPluginIdentifier DMI plugin identifier - * @return collection of cm handles - */ - Collection getCmHandleIdsByDmiPluginIdentifier(String dmiPluginIdentifier); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java deleted file mode 100644 index f61d6c348..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation - * Modifications Copyright (C) 2023 TechMahindra Ltd. - * ================================================================================ - * 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.cps.ncmp.api.inventory; - -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.inventory.enums.PropertyType; -import org.onap.cps.spi.CpsDataPersistenceService; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Component; - -@RequiredArgsConstructor -@Component -public class CmHandleQueriesImpl implements CmHandleQueries { - - private static final String NCMP_DATASPACE_NAME = "NCMP-Admin"; - private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; - private static final String DESCENDANT_PATH = "//"; - - private final CpsDataPersistenceService cpsDataPersistenceService; - private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles"; - - @Override - public Collection queryCmHandleAdditionalProperties(final Map privatePropertyQueryPairs) { - return queryCmHandleAnyProperties(privatePropertyQueryPairs, PropertyType.ADDITIONAL); - } - - @Override - public Collection queryCmHandlePublicProperties(final Map publicPropertyQueryPairs) { - return queryCmHandleAnyProperties(publicPropertyQueryPairs, PropertyType.PUBLIC); - } - - @Override - public List queryCmHandlesByState(final CmHandleState cmHandleState) { - return queryCmHandleDataNodesByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]", - INCLUDE_ALL_DESCENDANTS); - } - - @Override - public List queryCmHandleDataNodesByCpsPath(final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption); - } - - @Override - public boolean cmHandleHasState(final String cmHandleId, final CmHandleState requiredCmHandleState) { - final DataNode stateDataNode = getCmHandleState(cmHandleId); - final String cmHandleStateAsString = (String) stateDataNode.getLeaves().get("cm-handle-state"); - return CmHandleState.valueOf(cmHandleStateAsString).equals(requiredCmHandleState); - } - - @Override - public List queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) { - return queryCmHandleDataNodesByCpsPath("//state/datastores" + "/operational[@sync-state=\"" - + dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS); - } - - @Override - public Collection getCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) { - final Collection cmHandleIds = new HashSet<>(); - for (final ModelledDmiServiceLeaves modelledDmiServiceLeaf : ModelledDmiServiceLeaves.values()) { - for (final DataNode cmHandleAsDataNode: getCmHandlesByDmiPluginIdentifierAndDmiProperty( - dmiPluginIdentifier, - modelledDmiServiceLeaf.getLeafName())) { - cmHandleIds.add(cmHandleAsDataNode.getLeaves().get("id").toString()); - } - } - return cmHandleIds; - } - - private Collection collectCmHandleIdsFromDataNodes(final Collection dataNodes) { - return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet()); - } - - private Collection queryCmHandleAnyProperties( - final Map propertyQueryPairs, - final PropertyType propertyType) { - if (propertyQueryPairs.isEmpty()) { - return Collections.emptySet(); - } - Collection cmHandleIds = null; - for (final Map.Entry publicPropertyQueryPair : propertyQueryPairs.entrySet()) { - final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\"" - + publicPropertyQueryPair.getKey() - + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]"; - - final Collection dataNodes = queryCmHandleDataNodesByCpsPath(cpsPath, OMIT_DESCENDANTS); - if (cmHandleIds == null) { - cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes); - } else { - final Collection cmHandleIdsToRetain = collectCmHandleIdsFromDataNodes(dataNodes); - cmHandleIds.retainAll(cmHandleIdsToRetain); - } - if (cmHandleIds.isEmpty()) { - break; - } - } - return cmHandleIds; - } - - private List getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier, - final String dmiProperty) { - return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - "/dmi-registry/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']", - OMIT_DESCENDANTS); - } - - private DataNode getCmHandleState(final String cmHandleId) { - final String xpath = "/dmi-registry/cm-handles[@id='" + cmHandleId + "']/state"; - return cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - xpath, OMIT_DESCENDANTS).iterator().next(); - } -} - - diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleState.java deleted file mode 100644 index 7628c81dd..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CmHandleState.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory; - -public enum CmHandleState { - ADVISED, READY, LOCKED, DELETING, DELETED -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeState.java deleted file mode 100644 index bf448c568..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeState.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import lombok.Builder; -import lombok.Data; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * State Model to store state corresponding to the Yang resource dmi-registry model. - */ -@Getter -@Setter -@NoArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) -public class CompositeState { - - @JsonProperty("cm-handle-state") - private CmHandleState cmHandleState; - - @JsonProperty("lock-reason") - private LockReason lockReason; - - @JsonProperty("last-update-time") - private String lastUpdateTime; - - @JsonProperty("data-sync-enabled") - private Boolean dataSyncEnabled; - - @JsonProperty("datastores") - private DataStores dataStores; - - /** - * Date and Time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ - */ - private static final DateTimeFormatter dateTimeFormatter = - DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - - /** - * Composite State copy constructor. - * - * @param compositeState Composite State - */ - public CompositeState(final CompositeState compositeState) { - this.cmHandleState = compositeState.getCmHandleState(); - this.lockReason = compositeState.getLockReason(); - this.lastUpdateTime = compositeState.getLastUpdateTime(); - this.dataSyncEnabled = compositeState.getDataSyncEnabled(); - this.dataStores = compositeState.getDataStores(); - } - - - /** - * This will specify the latest lock reason for a specific cm handle. If a cm handle is in a state other than LOCKED - * it specifies the last lock reason. - * This can be used to track retry attempts as part of the lock details. - */ - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class LockReason { - - @JsonProperty("reason") - private LockReasonCategory lockReasonCategory; - - @JsonProperty("details") - private String details; - - } - - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class DataStores { - - @JsonProperty("operational") - private Operational operationalDataStore; - } - - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class Operational { - - @JsonProperty("sync-state") - private DataStoreSyncState dataStoreSyncState; - - @JsonProperty("last-sync-time") - private String lastSyncTime; - } - - @Data - @Builder - @JsonInclude(JsonInclude.Include.NON_NULL) - public static class Running { - - @JsonProperty("sync-state") - private String syncState; - - @JsonProperty("last-sync-time") - private String lastSyncTime; - } - - /** - * The date and time format used for the cm handle sync state. - * - * @return the date and time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ - */ - public static String nowInSyncTimeFormat() { - return dateTimeFormatter.format(OffsetDateTime.now()); - } - - /** - * Sets the last updated date and time for the cm handle sync state. - */ - public void setLastUpdateTimeNow() { - lastUpdateTime = CompositeState.nowInSyncTimeFormat(); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java deleted file mode 100644 index d6a33302d..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 Bell Canada - * Modifications Copyright (C) 2022 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.cps.ncmp.api.inventory; - -import org.onap.cps.ncmp.api.inventory.CompositeState.DataStores; -import org.onap.cps.ncmp.api.inventory.CompositeState.LockReason; -import org.onap.cps.ncmp.api.inventory.CompositeState.Operational; -import org.onap.cps.spi.model.DataNode; - -public class CompositeStateBuilder { - - private CmHandleState cmHandleState; - private LockReason lockReason; - private DataStores datastores; - private String lastUpdatedTime; - private Boolean dataSyncEnabled; - - /** - * To create the {@link CompositeState}. - * - * @return {@link DataNode} - */ - public CompositeState build() { - final CompositeState compositeState = new CompositeState(); - compositeState.setCmHandleState(cmHandleState); - compositeState.setLockReason(lockReason); - compositeState.setDataStores(datastores); - compositeState.setLastUpdateTime(lastUpdatedTime); - compositeState.setDataSyncEnabled(dataSyncEnabled); - return compositeState; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param cmHandleState for the data node - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withCmHandleState(final CmHandleState cmHandleState) { - this.cmHandleState = cmHandleState; - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param reason for the locked state - * @param details for the locked state - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withLockReason(final LockReasonCategory reason, final String details) { - this.lockReason = LockReason.builder().lockReasonCategory(reason).details(details).build(); - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param time for the state change - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withLastUpdatedTime(final String time) { - this.lastUpdatedTime = time; - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @return composite state builder - */ - public CompositeStateBuilder withLastUpdatedTimeNow() { - this.lastUpdatedTime = CompositeState.nowInSyncTimeFormat(); - return this; - } - - /** - * To use attributes for creating {@link CompositeState}. - * - * @param dataStoreSyncState for the locked state - * @param lastSyncTime for the locked state - * @return CompositeStateBuilder - */ - public CompositeStateBuilder withOperationalDataStores(final DataStoreSyncState dataStoreSyncState, - final String lastSyncTime) { - this.datastores = DataStores.builder().operationalDataStore( - Operational.builder().dataStoreSyncState(dataStoreSyncState).lastSyncTime(lastSyncTime).build()).build(); - return this; - } - - /** - * To use dataNode for creating {@link CompositeState}. - * - * @param dataNode for the dataNode - * @return CompositeState - */ - public CompositeStateBuilder fromDataNode(final DataNode dataNode) { - this.cmHandleState = CmHandleState.valueOf((String) dataNode.getLeaves() - .get("cm-handle-state")); - this.lastUpdatedTime = (String) dataNode.getLeaves().get("last-update-time"); - if (this.cmHandleState == CmHandleState.READY) { - this.dataSyncEnabled = (Boolean) dataNode.getLeaves().get("data-sync-enabled"); - } - for (final DataNode stateChildNode : dataNode.getChildDataNodes()) { - if (stateChildNode.getXpath().endsWith("/lock-reason")) { - this.lockReason = getLockReason(stateChildNode); - } - if (stateChildNode.getXpath().endsWith("/datastores")) { - for (final DataNode dataStoreNodes : stateChildNode.getChildDataNodes()) { - Operational operationalDataStore = null; - if (dataStoreNodes.getXpath().contains("/operational")) { - operationalDataStore = getOperationalDataStore(dataStoreNodes); - } - this.datastores = DataStores.builder().operationalDataStore(operationalDataStore).build(); - } - } - } - return this; - } - - private Operational getOperationalDataStore(final DataNode dataStoreNodes) { - return Operational.builder() - .dataStoreSyncState(DataStoreSyncState.valueOf((String) dataStoreNodes.getLeaves().get("sync-state"))) - .lastSyncTime((String) dataStoreNodes.getLeaves().get("last-sync-time")) - .build(); - } - - private LockReason getLockReason(final DataNode stateChildNode) { - final boolean isLockReasonExists = stateChildNode.getLeaves().containsKey("reason"); - return new LockReason(isLockReasonExists - ? LockReasonCategory.valueOf((String) stateChildNode.getLeaves().get("reason")) - : null, (String) stateChildNode.getLeaves().get("details")); - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java deleted file mode 100644 index cff1000fe..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory; - -import java.util.function.Consumer; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -/** - * It will have all the utility method responsible for handling the composite state. - */ -@Slf4j -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class CompositeStateUtils { - - /** - * Sets the cmHandleState to the provided state and updates the timestamp. - * - * @return Updated CompositeState - */ - public static Consumer setCompositeState(final CmHandleState cmHandleState) { - return compositeState -> { - compositeState.setCmHandleState(cmHandleState); - compositeState.setLastUpdateTimeNow(); - }; - } - - /** - * Set the Operational datastore sync state based on the global flag. - * - * @return Updated CompositeState - */ - public static Consumer setInitialDataStoreSyncState() { - - return compositeState -> { - compositeState.setDataSyncEnabled(false); - final CompositeState.Operational operational = - getInitialDataStoreSyncState(compositeState.getDataSyncEnabled()); - final CompositeState.DataStores dataStores = - CompositeState.DataStores.builder().operationalDataStore(operational).build(); - compositeState.setDataStores(dataStores); - }; - } - - /** - * Set the data sync enabled flag, along with the data store sync state based on this flag. - * - * @param dataSyncEnabled data sync enabled flag - * @param compositeState cm handle composite state - */ - public static void setDataSyncEnabledFlagWithDataSyncState(final boolean dataSyncEnabled, - final CompositeState compositeState) { - compositeState.setDataSyncEnabled(dataSyncEnabled); - compositeState.setLastUpdateTimeNow(); - final CompositeState.Operational operational = getInitialDataStoreSyncState(dataSyncEnabled); - final CompositeState.DataStores dataStores = - CompositeState.DataStores.builder().operationalDataStore(operational).build(); - compositeState.setDataStores(dataStores); - } - - /** - * Get initial data sync state based on data sync enabled boolean flag. - * - * @param dataSyncEnabled data sync enabled boolean flag - * @return the data store sync state - */ - private static CompositeState.Operational getInitialDataStoreSyncState(final boolean dataSyncEnabled) { - final DataStoreSyncState dataStoreSyncState = - dataSyncEnabled ? DataStoreSyncState.UNSYNCHRONIZED : DataStoreSyncState.NONE_REQUESTED; - return CompositeState.Operational.builder().dataStoreSyncState(dataStoreSyncState).build(); - } - - /** - * Sets the cmHandleState to ADVISED and retain the lock details. Used in retry scenarios. - * - * @return Updated CompositeState - */ - public static Consumer setCompositeStateForRetry() { - return compositeState -> { - compositeState.setCmHandleState(CmHandleState.ADVISED); - compositeState.setLastUpdateTimeNow(); - final String oldLockReasonDetails = compositeState.getLockReason().getDetails(); - final CompositeState.LockReason lockReason = - CompositeState.LockReason.builder().details(oldLockReasonDetails).build(); - compositeState.setLockReason(lockReason); - }; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java deleted file mode 100644 index 4dbedf5f1..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory; - -public enum DataStoreSyncState { - SYNCHRONIZED, UNSYNCHRONIZED, NONE_REQUESTED -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java deleted file mode 100644 index cbd30a8fe..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation - * Modifications Copyright (C) 2023 TechMahindra Ltd. - * ================================================================================ - * 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.cps.ncmp.api.inventory; - -import java.util.Collection; -import java.util.Map; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.model.ModuleDefinition; -import org.onap.cps.spi.model.ModuleReference; - -public interface InventoryPersistence { - - /** - * Get the Cm Handle Composite State from the data node. - * - * @param cmHandleId cm handle id - * @return the cm handle composite state - */ - CompositeState getCmHandleState(String cmHandleId); - - /** - * Save the cm handles state. - * - * @param cmHandleId cm handle id - * @param compositeState composite state - */ - void saveCmHandleState(String cmHandleId, CompositeState compositeState); - - /** - * Save all cm handles states in batch. - * - * @param cmHandleStatePerCmHandleId contains cm handle id and updated state - */ - void saveCmHandleStateBatch(Map cmHandleStatePerCmHandleId); - - /** - * This method retrieves DMI service name, DMI properties and the state for a given cm handle. - * - * @param cmHandleId the id of the cm handle - * @return yang model cm handle - */ - YangModelCmHandle getYangModelCmHandle(String cmHandleId); - - /** - * This method retrieves DMI service name, DMI properties and the state for a given cm handle. - * - * @param cmHandleIds a list of the ids of the cm handles - * @return collection of yang model cm handles - */ - Collection getYangModelCmHandles(Collection cmHandleIds); - - /** - * Method to return module definitions by cmHandleId. - * - * @param cmHandleId cm handle ID - * @return a collection of module definitions (moduleName, revision and yang resource content) - */ - Collection getModuleDefinitionsByCmHandleId(String cmHandleId); - - /** - * Method to return module references by cmHandleId. - * - * @param cmHandleId cm handle ID - * @return a collection of module references (moduleName and revision) - */ - Collection getYangResourcesModuleReferences(String cmHandleId); - - /** - * Method to save cmHandle. - * - * @param yangModelCmHandle cmHandle represented as Yang Model - */ - void saveCmHandle(YangModelCmHandle yangModelCmHandle); - - /** - * Method to save batch of cm handles. - * - * @param yangModelCmHandles cm handle represented as Yang Models - */ - void saveCmHandleBatch(Collection yangModelCmHandles); - - /** - * Method to delete a list or a list element. - * - * @param listElementXpath list element xPath - */ - void deleteListOrListElement(String listElementXpath); - - /** - * Method to delete a schema set. - * - * @param schemaSetName schema set name - */ - void deleteSchemaSetWithCascade(String schemaSetName); - - /** - * Method to delete multiple schema sets. - * - * @param schemaSetNames schema set names - */ - void deleteSchemaSetsWithCascade(Collection schemaSetNames); - - /** - * Get data node via xpath. - * - * @param xpath xpath - * @return data node - */ - Collection getDataNode(String xpath); - - /** - * Get data node via xpath. - * - * @param xpath xpath - * @param fetchDescendantsOption fetch descendants option - * @return data node - */ - Collection getDataNode(String xpath, FetchDescendantsOption fetchDescendantsOption); - - /** - * Get collection of data nodes via xpaths. - * - * @param xpaths collection of xpaths - * @return collection of data nodes - */ - Collection getDataNodes(Collection xpaths); - - /** - * Get collection of data nodes via xpaths. - * - * @param xpaths collection of xpaths - * @param fetchDescendantsOption fetch descendants option - * @return collection of data nodes - */ - Collection getDataNodes(Collection xpaths, FetchDescendantsOption fetchDescendantsOption); - - /** - * Get data node of given cm handle. - * - * @param cmHandleId cmHandle ID - * @return data node - */ - Collection getCmHandleDataNode(String cmHandleId); - - /** - * Get collection of data nodes of given cm handles. - * - * @param cmHandleIds collection of cmHandle IDs - * @return collection of data nodes - */ - Collection getCmHandleDataNodes(Collection cmHandleIds); - - /** - * get CM handles that has given module names. - * - * @param moduleNamesForQuery module names - * @return Collection of CM handle Ids - */ - Collection getCmHandleIdsWithGivenModules(Collection moduleNamesForQuery); - - /** - * Replaces list content by removing all existing elements and inserting the given new elements as data nodes. - * - * @param parentNodeXpath parent node xpath - * @param dataNodes datanodes representing the updated data - */ - void replaceListContent(String parentNodeXpath, Collection dataNodes); - - /** - * Deletes data node. - * - * @param dataNodeXpath data node xpath - */ - void deleteDataNode(String dataNodeXpath); - - /** - * Deletes multiple data nodes. - * - * @param dataNodeXpaths data node xpaths - */ - void deleteDataNodes(Collection dataNodeXpaths); -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java deleted file mode 100644 index 7908e629c..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * Modifications Copyright (C) 2023 TechMahindra Ltd. - * ================================================================================ - * 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.cps.ncmp.api.inventory; - -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP; -import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS; - -import io.micrometer.core.annotation.Timed; -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.api.CpsAdminService; -import org.onap.cps.api.CpsDataService; -import org.onap.cps.api.CpsModuleService; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.exceptions.DataValidationException; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.model.ModuleDefinition; -import org.onap.cps.spi.model.ModuleReference; -import org.onap.cps.spi.utils.CpsValidator; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.stereotype.Component; - -@Slf4j -@RequiredArgsConstructor -@Component -public class InventoryPersistenceImpl implements InventoryPersistence { - - private static final String NCMP_DATASPACE_NAME = "NCMP-Admin"; - - private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; - - private static final String NCMP_DMI_REGISTRY_PARENT = "/dmi-registry"; - - private final JsonObjectMapper jsonObjectMapper; - - private final CpsDataService cpsDataService; - - private final CpsModuleService cpsModuleService; - - private final CpsAdminService cpsAdminService; - - private final CpsValidator cpsValidator; - - @Override - public CompositeState getCmHandleState(final String cmHandleId) { - final DataNode stateAsDataNode = cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - createCmHandleXPath(cmHandleId) + "/state", - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS).iterator().next(); - cpsValidator.validateNameCharacters(cmHandleId); - return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build(); - } - - @Override - public void saveCmHandleState(final String cmHandleId, final CompositeState compositeState) { - final String cmHandleJsonData = createStateJsonData(jsonObjectMapper.asJsonString(compositeState)); - cpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - createCmHandleXPath(cmHandleId), - cmHandleJsonData, OffsetDateTime.now()); - } - - @Override - public void saveCmHandleStateBatch(final Map cmHandleStatePerCmHandleId) { - final Map cmHandlesJsonDataMap = new HashMap<>(); - cmHandleStatePerCmHandleId.forEach((cmHandleId, compositeState) -> cmHandlesJsonDataMap.put( - createCmHandleXPath(cmHandleId), - createStateJsonData(jsonObjectMapper.asJsonString(compositeState)))); - cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - cmHandlesJsonDataMap, OffsetDateTime.now()); - } - - @Override - public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { - cpsValidator.validateNameCharacters(cmHandleId); - final DataNode dataNode = getCmHandleDataNode(cmHandleId).iterator().next(); - return YangDataConverter.convertCmHandleToYangModel(dataNode, cmHandleId); - } - - @Override - public Collection getYangModelCmHandles(final Collection cmHandleIds) { - final Collection validCmHandleIds = new ArrayList<>(cmHandleIds.size()); - cmHandleIds.forEach(cmHandleId -> { - try { - cpsValidator.validateNameCharacters(cmHandleId); - validCmHandleIds.add(cmHandleId); - } catch (final DataValidationException dataValidationException) { - log.error("DataValidationException in CmHandleId {} to be ignored", - dataValidationException.getMessage()); - } - }); - return YangDataConverter.convertDataNodesToYangModelCmHandles(getCmHandleDataNodes(validCmHandleIds)); - } - - @Override - public Collection getModuleDefinitionsByCmHandleId(final String cmHandleId) { - return cpsModuleService.getModuleDefinitionsByAnchorName(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); - } - - @Override - public Collection getYangResourcesModuleReferences(final String cmHandleId) { - cpsValidator.validateNameCharacters(cmHandleId); - return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId); - } - - @Override - public void saveCmHandle(final YangModelCmHandle yangModelCmHandle) { - final String cmHandleJsonData = - createCmHandleJsonData(jsonObjectMapper.asJsonString(yangModelCmHandle)); - cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT, - cmHandleJsonData, NO_TIMESTAMP); - } - - @Override - public void saveCmHandleBatch(final Collection yangModelCmHandles) { - final List cmHandlesJsonData = new ArrayList<>(); - yangModelCmHandles.forEach(yangModelCmHandle -> cmHandlesJsonData.add( - createCmHandleJsonData(jsonObjectMapper.asJsonString(yangModelCmHandle)))); - cpsDataService.saveListElementsBatch(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - NCMP_DMI_REGISTRY_PARENT, cmHandlesJsonData, NO_TIMESTAMP); - } - - @Override - public void deleteListOrListElement(final String listElementXpath) { - cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - listElementXpath, NO_TIMESTAMP); - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete", - description = "Time taken to delete a schemaset") - public void deleteSchemaSetWithCascade(final String schemaSetName) { - try { - cpsValidator.validateNameCharacters(schemaSetName); - cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, - CASCADE_DELETE_ALLOWED); - } catch (final SchemaSetNotFoundException schemaSetNotFoundException) { - log.warn("Schema set {} does not exist or already deleted", schemaSetName); - } - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete.batch", - description = "Time taken to delete multiple schemaset") - public void deleteSchemaSetsWithCascade(final Collection schemaSetNames) { - cpsValidator.validateNameCharacters(schemaSetNames); - cpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetNames); - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", - description = "Time taken to get a data node (from ncmp dmi registry)") - public Collection getDataNode(final String xpath) { - return getDataNode(xpath, INCLUDE_ALL_DESCENDANTS); - } - - @Override - @Timed(value = "cps.ncmp.inventory.persistence.datanode.get", - description = "Time taken to get a data node (from ncmp dmi registry)") - public Collection getDataNode(final String xpath, final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - xpath, fetchDescendantsOption); - } - - @Override - public Collection getDataNodes(final Collection xpaths) { - return getDataNodes(xpaths, INCLUDE_ALL_DESCENDANTS); - } - - @Override - public Collection getDataNodes(final Collection xpaths, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - xpaths, fetchDescendantsOption); - } - - @Override - public Collection getCmHandleDataNode(final String cmHandleId) { - return this.getDataNode(createCmHandleXPath(cmHandleId)); - } - - @Override - public Collection getCmHandleDataNodes(final Collection cmHandleIds) { - final Collection xpaths = new ArrayList<>(cmHandleIds.size()); - cmHandleIds.forEach(cmHandleId -> xpaths.add(createCmHandleXPath(cmHandleId))); - return this.getDataNodes(xpaths); - } - - @Override - public Collection getCmHandleIdsWithGivenModules(final Collection moduleNamesForQuery) { - return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery); - } - - @Override - public void replaceListContent(final String parentNodeXpath, final Collection dataNodes) { - cpsDataService.replaceListContent(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - parentNodeXpath, dataNodes, NO_TIMESTAMP); - } - - @Override - public void deleteDataNode(final String dataNodeXpath) { - cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath, NO_TIMESTAMP); - } - - @Override - public void deleteDataNodes(final Collection dataNodeXpaths) { - cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP); - } - - private static String createCmHandleXPath(final String cmHandleId) { - return "/dmi-registry/cm-handles[@id='" + cmHandleId + "']"; - } - - private static String createStateJsonData(final String state) { - return "{\"state\":" + state + "}"; - } - - private static String createCmHandleJsonData(final String yangModelCmHandleAsJson) { - return "{\"cm-handles\":[" + yangModelCmHandleAsJson + "]}"; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/LockReasonCategory.java deleted file mode 100644 index 35daa62e8..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/LockReasonCategory.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory; - -public enum LockReasonCategory { - MODULE_SYNC_FAILED, MODULE_UPGRADE, MODULE_UPGRADE_FAILED -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/ModelledDmiServiceLeaves.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/ModelledDmiServiceLeaves.java deleted file mode 100644 index 0546c388b..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/ModelledDmiServiceLeaves.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory; - -public enum ModelledDmiServiceLeaves { - DMI_SERVICE_NAME("dmi-service-name"), - DMI_DATA_SERVICE_NAME("dmi-data-service-name"), - DMI_MODEL_SERVICE_NAME("dmi-model-service-name"); - - private String leafName; - - ModelledDmiServiceLeaves(final String dmiPluginIdentifierKey) { - this.leafName = dmiPluginIdentifierKey; - } - - public String getLeafName() { - return leafName; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/enums/PropertyType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/enums/PropertyType.java deleted file mode 100644 index c3c46c35e..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/enums/PropertyType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum PropertyType { - ADDITIONAL("additional-properties"), - PUBLIC("public-properties"), - DMI_PLUGIN("dmiPluginName"); - - private final String yangContainerName; -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java deleted file mode 100644 index 9fa75a0d0..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory.sync; - -import com.hazelcast.map.IMap; -import java.time.OffsetDateTime; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.api.CpsDataService; -import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -@Slf4j -@RequiredArgsConstructor -@Service -public class DataSyncWatchdog { - - private static final boolean DATA_SYNC_IN_PROGRESS = false; - private static final boolean DATA_SYNC_DONE = true; - - private final InventoryPersistence inventoryPersistence; - - private final CpsDataService cpsDataService; - - private final SyncUtils syncUtils; - - private final IMap dataSyncSemaphores; - - /** - * Execute Cm Handle poll which queries the cm handle state in 'READY' and Operational Datastore Sync State in - * 'UNSYNCHRONIZED'. - */ - @Scheduled(fixedDelayString = "${ncmp.timers.cm-handle-data-sync.sleep-time-ms:30000}") - public void executeUnSynchronizedReadyCmHandlePoll() { - syncUtils.getUnsynchronizedReadyCmHandles().forEach(unSynchronizedReadyCmHandle -> { - final String cmHandleId = unSynchronizedReadyCmHandle.getId(); - if (hasPushedIntoSemaphoreMap(cmHandleId)) { - log.debug("Executing data sync on {}", cmHandleId); - final CompositeState compositeState = inventoryPersistence - .getCmHandleState(cmHandleId); - final String resourceData = syncUtils.getResourceData(cmHandleId); - if (resourceData == null) { - log.debug("Error retrieving resource data for Cm-Handle: {}", cmHandleId); - } else { - cpsDataService.saveData("NFP-Operational", cmHandleId, - resourceData, OffsetDateTime.now()); - setSyncStateToSynchronized().accept(compositeState); - inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); - updateDataSyncSemaphoreMap(cmHandleId); - } - } else { - log.debug("{} already processed by another instance", cmHandleId); - } - }); - log.debug("No Cm-Handles currently found in READY State and Operational Sync State is UNSYNCHRONIZED"); - } - - private Consumer setSyncStateToSynchronized() { - return compositeState -> { - compositeState.setLastUpdateTimeNow(); - compositeState.getDataStores() - .setOperationalDataStore(CompositeState.Operational.builder() - .dataStoreSyncState(DataStoreSyncState.SYNCHRONIZED) - .lastSyncTime(CompositeState.nowInSyncTimeFormat()).build()); - }; - } - - private void updateDataSyncSemaphoreMap(final String cmHandleId) { - dataSyncSemaphores.replace(cmHandleId, DATA_SYNC_DONE); - } - - private boolean hasPushedIntoSemaphoreMap(final String cmHandleId) { - return dataSyncSemaphores.putIfAbsent(cmHandleId, DATA_SYNC_IN_PROGRESS, - SynchronizationCacheConfig.DATA_SYNC_SEMAPHORE_TTL_SECS, TimeUnit.SECONDS) == null; - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncService.java deleted file mode 100644 index 7efce1ad5..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncService.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory.sync; - -import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.api.CpsAdminService; -import org.onap.cps.api.CpsModuleService; -import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.spi.CascadeDeleteAllowed; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; -import org.onap.cps.spi.model.ModuleReference; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class ModuleSyncService { - - private final DmiModelOperations dmiModelOperations; - private final CpsModuleService cpsModuleService; - - private final CpsAdminService cpsAdminService; - - /** - * This method registers a cm handle and initiates modules sync. - * - * @param yangModelCmHandle the yang model of cm handle. - */ - public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { - - final Collection allModuleReferencesFromCmHandle = - dmiModelOperations.getModuleReferences(yangModelCmHandle); - - final Collection identifiedNewModuleReferencesFromCmHandle = cpsModuleService - .identifyNewModuleReferences(allModuleReferencesFromCmHandle); - - final Map newModuleNameToContentMap; - if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) { - newModuleNameToContentMap = Collections.emptyMap(); - } else { - newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, - identifiedNewModuleReferencesFromCmHandle); - } - createSchemaSetAndAnchor(yangModelCmHandle, newModuleNameToContentMap, allModuleReferencesFromCmHandle); - } - - private void createSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle, - final Map newModuleNameToContentMap, - final Collection allModuleReferencesFromCmHandle) { - final String schemaSetAndAnchorName = yangModelCmHandle.getId(); - cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName, - newModuleNameToContentMap, allModuleReferencesFromCmHandle); - cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName, - schemaSetAndAnchorName); - } - - /** - * Deletes the SchemaSet for schema set id if the SchemaSet Exists. - * - * @param schemaSetId the schema set id to be deleted - */ - public void deleteSchemaSetIfExists(final String schemaSetId) { - try { - cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetId, - CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED); - log.debug("SchemaSet for {} has been deleted. Ready to be recreated.", schemaSetId); - } catch (final SchemaSetNotFoundException e) { - log.debug("No SchemaSet for {}. Assuming CmHandle has not been previously Module Synced.", schemaSetId); - } - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasks.java deleted file mode 100644 index 9ef75b3b0..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasks.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-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.cps.ncmp.api.inventory.sync; - -import com.hazelcast.map.IMap; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicInteger; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.inventory.LockReasonCategory; -import org.onap.cps.spi.model.DataNode; -import org.springframework.stereotype.Component; - -@RequiredArgsConstructor -@Component -@Slf4j -public class ModuleSyncTasks { - private final InventoryPersistence inventoryPersistence; - private final SyncUtils syncUtils; - private final ModuleSyncService moduleSyncService; - private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; - private final IMap moduleSyncStartedOnCmHandles; - - /** - * Perform module sync on a batch of cm handles. - * - * @param cmHandlesAsDataNodes a batch of Data nodes representing cm handles to perform module sync on - * @param batchCounter the number of batches currently being processed, will be decreased when - * task is finished or fails - * @return completed future to handle post-processing - */ - public CompletableFuture performModuleSync(final Collection cmHandlesAsDataNodes, - final AtomicInteger batchCounter) { - try { - final Map cmHandelStatePerCmHandle = new HashMap<>(); - for (final DataNode cmHandleAsDataNode : cmHandlesAsDataNodes) { - final String cmHandleId = String.valueOf(cmHandleAsDataNode.getLeaves().get("id")); - final YangModelCmHandle yangModelCmHandle = - YangDataConverter.convertCmHandleToYangModel(cmHandleAsDataNode, cmHandleId); - final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); - try { - moduleSyncService.deleteSchemaSetIfExists(cmHandleId); - moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle); - cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY); - } catch (final Exception e) { - log.warn("Processing of {} module sync failed due to reason {}.", cmHandleId, e.getMessage()); - syncUtils.updateLockReasonDetailsAndAttempts(compositeState, - LockReasonCategory.MODULE_SYNC_FAILED, e.getMessage()); - setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason()); - cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED); - } - log.info("{} is now in {} state", cmHandleId, compositeState.getCmHandleState().name()); - } - lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandelStatePerCmHandle); - } finally { - batchCounter.getAndDecrement(); - log.info("Processing module sync batch finished. {} batch(es) active.", batchCounter.get()); - } - return CompletableFuture.completedFuture(null); - } - - /** - * Reset state to "ADVISED" for any previously failed cm handles. - * - * @param failedCmHandles previously failed (locked) cm handles - */ - public void resetFailedCmHandles(final List failedCmHandles) { - final Map cmHandleStatePerCmHandle = new HashMap<>(failedCmHandles.size()); - for (final YangModelCmHandle failedCmHandle : failedCmHandles) { - final CompositeState compositeState = failedCmHandle.getCompositeState(); - final boolean isReadyForRetry = syncUtils.needsModuleSyncRetry(compositeState); - log.info("Retry for cmHandleId : {} is {}", failedCmHandle.getId(), isReadyForRetry); - if (isReadyForRetry) { - final String resetCmHandleId = failedCmHandle.getId(); - log.debug("Reset cm handle {} state to ADVISED to be re-attempted by module-sync watchdog", - resetCmHandleId); - cmHandleStatePerCmHandle.put(failedCmHandle, CmHandleState.ADVISED); - removeResetCmHandleFromModuleSyncMap(resetCmHandleId); - } - } - lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); - } - - private void setCmHandleStateLocked(final YangModelCmHandle advisedCmHandle, - final CompositeState.LockReason lockReason) { - advisedCmHandle.getCompositeState().setLockReason(lockReason); - } - - private void removeResetCmHandleFromModuleSyncMap(final String resetCmHandleId) { - if (moduleSyncStartedOnCmHandles.remove(resetCmHandleId) != null) { - log.info("{} removed from in progress map", resetCmHandleId); - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java deleted file mode 100644 index 6ff426d66..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * ================================================================================ - * 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.cps.ncmp.api.inventory.sync; - -import com.hazelcast.map.IMap; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.sync.executor.AsyncTaskExecutor; -import org.onap.cps.spi.model.DataNode; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -@Slf4j -@RequiredArgsConstructor -@Service -public class ModuleSyncWatchdog { - - private final SyncUtils syncUtils; - private final BlockingQueue moduleSyncWorkQueue; - private final IMap moduleSyncStartedOnCmHandles; - private final ModuleSyncTasks moduleSyncTasks; - private final AsyncTaskExecutor asyncTaskExecutor; - private static final int MODULE_SYNC_BATCH_SIZE = 100; - private static final long PREVENT_CPU_BURN_WAIT_TIME_MILLIS = 10; - private static final String VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP = "Started"; - private static final long ASYNC_TASK_TIMEOUT_IN_MILLISECONDS = TimeUnit.MINUTES.toMillis(5); - @Getter - private AtomicInteger batchCounter = new AtomicInteger(1); - - /** - * Check DB for any cm handles in 'ADVISED' state. - * Queue and create batches to process them asynchronously. - * This method will only finish when there are no more 'ADVISED' cm handles in the DB. - * This method wil be triggered on a configurable interval - */ - @Scheduled(fixedDelayString = "${ncmp.timers.advised-modules-sync.sleep-time-ms:5000}") - public void moduleSyncAdvisedCmHandles() { - log.info("Processing module sync watchdog waking up."); - populateWorkQueueIfNeeded(); - while (!moduleSyncWorkQueue.isEmpty()) { - if (batchCounter.get() <= asyncTaskExecutor.getAsyncTaskParallelismLevel()) { - final Collection nextBatch = prepareNextBatch(); - log.info("Processing module sync batch of {}. {} batch(es) active.", - nextBatch.size(), batchCounter.get()); - if (!nextBatch.isEmpty()) { - asyncTaskExecutor.executeTask(() -> - moduleSyncTasks.performModuleSync(nextBatch, batchCounter), - ASYNC_TASK_TIMEOUT_IN_MILLISECONDS); - batchCounter.getAndIncrement(); - } - } else { - preventBusyWait(); - } - } - } - - /** - * Find any failed (locked) cm handles and change state back to 'ADVISED'. - */ - @Scheduled(fixedDelayString = "${ncmp.timers.locked-modules-sync.sleep-time-ms:300000}") - public void resetPreviouslyFailedCmHandles() { - log.info("Processing module sync retry-watchdog waking up."); - final List failedCmHandles = syncUtils.getModuleSyncFailedCmHandles(); - log.info("Retrying {} cmHandles", failedCmHandles.size()); - moduleSyncTasks.resetFailedCmHandles(failedCmHandles); - } - - private void preventBusyWait() { - try { - log.info("Busy waiting now"); - TimeUnit.MILLISECONDS.sleep(PREVENT_CPU_BURN_WAIT_TIME_MILLIS); - } catch (final InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - private void populateWorkQueueIfNeeded() { - if (moduleSyncWorkQueue.isEmpty()) { - final List advisedCmHandles = syncUtils.getAdvisedCmHandles(); - log.info("Processing module sync fetched {} advised cm handles from DB", advisedCmHandles.size()); - for (final DataNode advisedCmHandle : advisedCmHandles) { - if (!moduleSyncWorkQueue.offer(advisedCmHandle)) { - log.warn("Unable to add cm handle {} to the work queue", advisedCmHandle.getLeaves().get("id")); - } - } - log.info("Work Queue Size : {}", moduleSyncWorkQueue.size()); - } - } - - private Collection prepareNextBatch() { - final Collection nextBatchCandidates = new HashSet<>(MODULE_SYNC_BATCH_SIZE); - final Collection nextBatch = new HashSet<>(MODULE_SYNC_BATCH_SIZE); - moduleSyncWorkQueue.drainTo(nextBatchCandidates, MODULE_SYNC_BATCH_SIZE); - log.info("nextBatchCandidates size : {}", nextBatchCandidates.size()); - for (final DataNode batchCandidate : nextBatchCandidates) { - final String cmHandleId = String.valueOf(batchCandidate.getLeaves().get("id")); - final boolean alreadyAddedToInProgressMap = VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP.equals( - moduleSyncStartedOnCmHandles.putIfAbsent(cmHandleId, VALUE_FOR_HAZELCAST_IN_PROGRESS_MAP, - SynchronizationCacheConfig.MODULE_SYNC_STARTED_TTL_SECS, TimeUnit.SECONDS)); - if (alreadyAddedToInProgressMap) { - log.info("module sync for {} already in progress by other instance", cmHandleId); - } else { - log.info("Adding cmHandle : {} to current batch", cmHandleId); - nextBatch.add(batchCandidate); - } - } - log.debug("nextBatch size : {}", nextBatch.size()); - return nextBatch; - } - -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java deleted file mode 100644 index ce41e3339..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/SyncUtils.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * ================================================================================ - * 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.cps.ncmp.api.inventory.sync; - -import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL; - -import com.fasterxml.jackson.databind.JsonNode; -import java.time.Duration; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; -import org.onap.cps.ncmp.api.inventory.CmHandleQueries; -import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.inventory.CompositeState; -import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.api.inventory.LockReasonCategory; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -@RequiredArgsConstructor -public class SyncUtils { - private final CmHandleQueries cmHandleQueries; - - private final DmiDataOperations dmiDataOperations; - - private final JsonObjectMapper jsonObjectMapper; - - private static final Pattern retryAttemptPattern = Pattern.compile("^Attempt #(\\d+) failed:"); - - /** - * Query data nodes for cm handles with an "ADVISED" cm handle state. - * - * @return cm handles (data nodes) in ADVISED state (empty list if none found) - */ - public List getAdvisedCmHandles() { - final List advisedCmHandlesAsDataNodes = cmHandleQueries.queryCmHandlesByState(CmHandleState.ADVISED); - log.debug("Total number of fetched advised cm handle(s) is (are) {}", advisedCmHandlesAsDataNodes.size()); - return advisedCmHandlesAsDataNodes; - } - - /** - * First query data nodes for cm handles with CM Handle Operational Sync State in "UNSYNCHRONIZED" and - * randomly select a CM Handle and query the data nodes for CM Handle State in "READY". - * - * @return a randomized yang model cm handle list with State in READY and Operation Sync State in "UNSYNCHRONIZED", - * return empty list if not found - */ - public List getUnsynchronizedReadyCmHandles() { - final List unsynchronizedCmHandles = cmHandleQueries - .queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED); - - final List yangModelCmHandles = new ArrayList<>(); - for (final DataNode unsynchronizedCmHandle : unsynchronizedCmHandles) { - final String cmHandleId = unsynchronizedCmHandle.getLeaves().get("id").toString(); - if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) { - yangModelCmHandles.addAll( - convertCmHandlesDataNodesToYangModelCmHandles( - Collections.singletonList(unsynchronizedCmHandle))); - } - } - - Collections.shuffle(yangModelCmHandles); - - return yangModelCmHandles; - } - - /** - * Query data nodes for cm handles with an "LOCKED" cm handle state with reason MODULE_SYNC_FAILED". - * - * @return a random LOCKED yang model cm handle, return null if not found - */ - public List getModuleSyncFailedCmHandles() { - final List lockedCmHandlesAsDataNodeList = cmHandleQueries.queryCmHandleDataNodesByCpsPath( - "//lock-reason[@reason=\"MODULE_SYNC_FAILED\"]", - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); - return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList); - } - - /** - * Update Composite State attempts counter and set new lock reason and details. - * - * @param lockReasonCategory lock reason category - * @param errorMessage error message - */ - public void updateLockReasonDetailsAndAttempts(final CompositeState compositeState, - final LockReasonCategory lockReasonCategory, - final String errorMessage) { - int attempt = 1; - if (compositeState.getLockReason() != null) { - final Matcher matcher = retryAttemptPattern.matcher(compositeState.getLockReason().getDetails()); - if (matcher.find()) { - attempt = 1 + Integer.parseInt(matcher.group(1)); - } - } - compositeState.setLockReason(CompositeState.LockReason.builder() - .details(String.format("Attempt #%d failed: %s", attempt, errorMessage)) - .lockReasonCategory(lockReasonCategory).build()); - } - - - /** - * Check if a module sync retry is needed. - * - * @param compositeState the composite state currently in the locked state - * @return if the retry mechanism should be attempted - */ - public boolean needsModuleSyncRetry(final CompositeState compositeState) { - final OffsetDateTime time = - OffsetDateTime.parse(compositeState.getLastUpdateTime(), - DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); - final Matcher matcher = retryAttemptPattern.matcher(compositeState.getLockReason().getDetails()); - final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED - == compositeState.getLockReason().getLockReasonCategory(); - if (!failedDuringModuleSync) { - log.info("Locked for other reason"); - return false; - } - final int timeInMinutesUntilNextAttempt; - if (matcher.find()) { - timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1))); - } else { - timeInMinutesUntilNextAttempt = 1; - log.info("First Attempt: no current attempts found."); - } - final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes(); - if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) { - log.info("Time until next attempt is {} minutes: ", - timeInMinutesUntilNextAttempt - timeSinceLastAttempt); - return false; - } - log.info("Retry due now"); - return true; - } - - /** - * Get the Resourece Data from Node through DMI Passthrough service. - * - * @param cmHandleId cm handle id - * @return optional string containing the resource data - */ - public String getResourceData(final String cmHandleId) { - final ResponseEntity resourceDataResponseEntity = dmiDataOperations.getResourceDataFromDmi( - PASSTHROUGH_OPERATIONAL.getDatastoreName(), - cmHandleId, - UUID.randomUUID().toString()); - if (resourceDataResponseEntity.getStatusCode().is2xxSuccessful()) { - return getFirstResource(resourceDataResponseEntity.getBody()); - } - return null; - } - - private String getFirstResource(final Object responseBody) { - final String jsonObjectAsString = jsonObjectMapper.asJsonString(responseBody); - final JsonNode overallJsonNode = jsonObjectMapper.convertToJsonNode(jsonObjectAsString); - final Iterator> overallJsonTreeMap = overallJsonNode.fields(); - final Map.Entry firstElement = overallJsonTreeMap.next(); - return jsonObjectMapper.asJsonString(Map.of(firstElement.getKey(), firstElement.getValue())); - } - - private static List convertCmHandlesDataNodesToYangModelCmHandles( - final List cmHandlesAsDataNodeList) { - return cmHandlesAsDataNodeList.stream() - .map(cmHandle -> YangDataConverter.convertCmHandleToYangModel(cmHandle, - cmHandle.getLeaves().get("id").toString())).collect(Collectors.toList()); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurer.java deleted file mode 100644 index 196a655ca..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/config/WatchdogSchedulingConfigurer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory.sync.config; - -import java.util.concurrent.ThreadPoolExecutor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.TaskScheduler; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; - -@Configuration -@EnableScheduling -public class WatchdogSchedulingConfigurer implements SchedulingConfigurer { - - @Override - public void configureTasks(final ScheduledTaskRegistrar scheduledTaskRegistrar) { - scheduledTaskRegistrar.setTaskScheduler(taskScheduler()); - } - - /** - * Implementation of Spring's {@link TaskScheduler} interface, wrapping - * a native {@link org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler} for watchdogs. - */ - @Bean - public TaskScheduler taskScheduler() { - final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); - taskScheduler.setPoolSize(10); - taskScheduler.setThreadNamePrefix("watchdog-th-"); - taskScheduler.setAwaitTerminationSeconds(60); - taskScheduler.setWaitForTasksToCompleteOnShutdown(true); - taskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); - taskScheduler.initialize(); - return taskScheduler; - } -} \ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutor.java deleted file mode 100644 index 3d08185e1..000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/executor/AsyncTaskExecutor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.cps.ncmp.api.inventory.sync.executor; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import jakarta.annotation.PostConstruct; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeoutException; -import java.util.function.Supplier; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Slf4j -@Service -public class AsyncTaskExecutor { - - @Value("${ncmp.modules-sync-watchdog.async-executor.parallelism-level:10}") - @Getter - private int asyncTaskParallelismLevel; - private ExecutorService executorService; - private static final int DEFAULT_PARALLELISM_LEVEL = 10; - - /** - * Set up executor service with thread-pool size as per configuration parameter. - * If modules-sync-watchdog.async-executor.parallelism-level not set a default of 10 threads will be applied. - */ - @PostConstruct - public void setupThreadPool() { - executorService = Executors.newWorkStealingPool( - asyncTaskParallelismLevel == 0 ? DEFAULT_PARALLELISM_LEVEL : asyncTaskParallelismLevel); - } - - /** - * Execute supplied task asynchronously. - * - * @param taskSupplier functional method is get() task need to executed asynchronously - * @param timeOutInMillis the task timeout value in milliseconds - */ - public void executeTask(final Supplier taskSupplier, final long timeOutInMillis) { - CompletableFuture.supplyAsync(taskSupplier::get, executorService) - .orTimeout(timeOutInMillis, MILLISECONDS) - .whenCompleteAsync(this::handleTaskCompletion); - } - - private void handleTaskCompletion(final Object response, final Throwable throwable) { - if (throwable != null) { - if (throwable instanceof TimeoutException) { - log.warn("Async task didn't completed within the required time."); - } else { - log.debug("Watchdog async batch failed. caused by : {}", throwable.getMessage()); - } - } - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java index ae40d330b..c46a8c26d 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-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. @@ -28,7 +28,7 @@ import java.util.Map; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.onap.cps.ncmp.api.inventory.CompositeState; +import org.onap.cps.ncmp.api.impl.inventory.CompositeState; import org.springframework.validation.annotation.Validated; /** diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java index 5316d666d..b805cdcd8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java @@ -20,6 +20,9 @@ package org.onap.cps.ncmp.init; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR; + import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; @@ -32,8 +35,6 @@ public class InventoryModelLoader extends AbstractModelLoader { private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2023-08-23.yang"; private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2023-08-23"; - private static final String DATASPACE_NAME = "NCMP-Admin"; - private static final String ANCHOR_NAME = "ncmp-dmi-registry"; public InventoryModelLoader(final CpsAdminService cpsAdminService, final CpsModuleService cpsModuleService, @@ -43,20 +44,20 @@ public class InventoryModelLoader extends AbstractModelLoader { @Override public void onboardOrUpgradeModel() { - waitUntilDataspaceIsAvailable(DATASPACE_NAME); + waitUntilDataspaceIsAvailable(NCMP_DATASPACE_NAME); updateInventoryModel(); log.info("Inventory Model updated successfully"); } private void updateInventoryModel() { - createSchemaSet(DATASPACE_NAME, NEW_SCHEMA_SET_NAME, NEW_MODEL_FILE_NAME); - updateAnchorSchemaSet(DATASPACE_NAME, ANCHOR_NAME, NEW_SCHEMA_SET_NAME); + createSchemaSet(NCMP_DATASPACE_NAME, NEW_SCHEMA_SET_NAME, NEW_MODEL_FILE_NAME); + updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NEW_SCHEMA_SET_NAME); deleteOldButNotThePreviousSchemaSets(); } private void deleteOldButNotThePreviousSchemaSets() { //No schema sets passed in yet, but wil be required for future updates - deleteUnusedSchemaSets(DATASPACE_NAME); + deleteUnusedSchemaSets(NCMP_DATASPACE_NAME); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java index 891244c7c..4d1a91ca9 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/SubscriptionModelLoader.java @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.init; +import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME; + import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; @@ -32,7 +34,6 @@ import org.springframework.stereotype.Service; public class SubscriptionModelLoader extends AbstractModelLoader { private static final String MODEL_FILENAME = "subscription.yang"; - private static final String DATASPACE_NAME = "NCMP-Admin"; private static final String ANCHOR_NAME = "AVC-Subscriptions"; private static final String SCHEMASET_NAME = "subscriptions"; private static final String REGISTRY_DATANODE_NAME = "subscription-registry"; @@ -49,7 +50,7 @@ public class SubscriptionModelLoader extends AbstractModelLoader { @Override public void onboardOrUpgradeModel() { if (subscriptionModelLoaderEnabled) { - waitUntilDataspaceIsAvailable(DATASPACE_NAME); + waitUntilDataspaceIsAvailable(NCMP_DATASPACE_NAME); onboardSubscriptionModel(); log.info("Subscription Model onboarded successfully"); } else { @@ -58,9 +59,9 @@ public class SubscriptionModelLoader extends AbstractModelLoader { } private void onboardSubscriptionModel() { - createSchemaSet(DATASPACE_NAME, SCHEMASET_NAME, MODEL_FILENAME); - createAnchor(DATASPACE_NAME, SCHEMASET_NAME, ANCHOR_NAME); - createTopLevelDataNode(DATASPACE_NAME, ANCHOR_NAME, REGISTRY_DATANODE_NAME); + createSchemaSet(NCMP_DATASPACE_NAME, SCHEMASET_NAME, MODEL_FILENAME); + createAnchor(NCMP_DATASPACE_NAME, SCHEMASET_NAME, ANCHOR_NAME); + createTopLevelDataNode(NCMP_DATASPACE_NAME, ANCHOR_NAME, REGISTRY_DATANODE_NAME); } } -- cgit 1.2.3-korg