diff options
Diffstat (limited to 'cps-ncmp-service/src')
56 files changed, 480 insertions, 544 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java index a260ce9cbe..c980d7fa24 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/DataStoreSyncState.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.inventory; +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/impl/inventory/models/CmHandleState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleState.java index 9a4b3e2a83..ecd6116051 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleState.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.inventory.models; +package org.onap.cps.ncmp.api.inventory.models; public enum CmHandleState { ADVISED, READY, LOCKED, DELETING, DELETED diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java index ca4fde2b62..d873f66ff5 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java @@ -29,9 +29,7 @@ import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; -import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; /** * State Model to store state corresponding to the Yang resource dmi-registry model. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java index a8d9018489..8a71713223 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java @@ -22,12 +22,10 @@ package org.onap.cps.ncmp.api.inventory.models; import org.onap.cps.api.model.DataNode; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.models.CompositeState.DataStores; import org.onap.cps.ncmp.api.inventory.models.CompositeState.LockReason; import org.onap.cps.ncmp.api.inventory.models.CompositeState.Operational; -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; -import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory; public class CompositeStateBuilder { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/LockReasonCategory.java index 1003aeca2d..884e066f24 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/LockReasonCategory.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.inventory.models; +package org.onap.cps.ncmp.api.inventory.models; public enum LockReasonCategory { MODULE_SYNC_FAILED, diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/ServiceConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/ServiceConfig.java index f1fce0c7c6..775e9d7b14 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/ServiceConfig.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/ServiceConfig.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,4 +33,5 @@ public abstract class ServiceConfig { private Integer connectionTimeoutInSeconds = 1; private long readTimeoutInSeconds = 1; private long writeTimeoutInSeconds = 1; + private long responseTimeoutInSeconds = 60; } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java index a29799b13f..fe933d766f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java @@ -28,7 +28,7 @@ import org.springframework.context.annotation.Configuration; @Configuration public class AdminCacheConfig extends HazelcastCacheConfig { - private static final MapConfig adminCacheMapConfig = createMapConfig("adminCacheMapConfig"); + private static final MapConfig cmHandleStateCacheMapConfig = createMapConfig("cmHandleStateCacheMapConfig"); /** * Distributed instance admin cache map for cm handles by state for use of gauge metrics. @@ -37,13 +37,7 @@ public class AdminCacheConfig extends HazelcastCacheConfig { */ @Bean public IMap<String, Integer> cmHandlesByState() { - final IMap<String, Integer> cmHandlesByState = getOrCreateHazelcastInstance(adminCacheMapConfig).getMap( + return getOrCreateHazelcastInstance(cmHandleStateCacheMapConfig).getMap( "cmHandlesByState"); - cmHandlesByState.putIfAbsent("advisedCmHandlesCount", 0); - cmHandlesByState.putIfAbsent("readyCmHandlesCount", 0); - cmHandlesByState.putIfAbsent("lockedCmHandlesCount", 0); - cmHandlesByState.putIfAbsent("deletingCmHandlesCount", 0); - cmHandlesByState.putIfAbsent("deletedCmHandlesCount", 0); - return cmHandlesByState; } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java index 20c7c7b13d..98c66afe30 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java @@ -38,12 +38,14 @@ import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventProduc import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.dmi_to_ncmp.Data; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.dmi_to_ncmp.DmiOutEvent; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @Component @Slf4j @RequiredArgsConstructor +@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) public class DmiOutEventConsumer { private final DmiCacheHandler dmiCacheHandler; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java index 8dcf5a5e85..1b368dde6c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java @@ -46,10 +46,12 @@ import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.Pr import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor +@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) public class CmSubscriptionHandlerImpl implements CmSubscriptionHandler { private static final Pattern SUBSCRIPTION_KEY_FROM_XPATH_PATTERN = Pattern.compile( diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java index cba64e0e94..17b1de6d08 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java @@ -29,12 +29,14 @@ import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.NcmpInEvent; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.Predicate; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @Component @Slf4j @RequiredArgsConstructor +@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true) public class NcmpInEventConsumer { private final CmSubscriptionHandler cmSubscriptionHandler; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java index 60f5c2c04b..189239ceb2 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java @@ -40,6 +40,7 @@ import org.onap.cps.ncmp.api.data.models.CmResourceAddress; import org.onap.cps.ncmp.api.data.models.DataOperationRequest; import org.onap.cps.ncmp.api.data.models.OperationType; import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; import org.onap.cps.ncmp.impl.data.models.DmiDataOperationRequest; import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle; @@ -48,7 +49,6 @@ import org.onap.cps.ncmp.impl.data.utils.DmiDataOperationsHelper; import org.onap.cps.ncmp.impl.dmi.DmiProperties; import org.onap.cps.ncmp.impl.dmi.DmiRestClient; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.models.DmiRequestBody; import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java index a0d89644e4..cb435f4a84 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java @@ -38,11 +38,11 @@ import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.data.models.DataOperationDefinition; import org.onap.cps.ncmp.api.data.models.DataOperationRequest; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.config.CpsApplicationContext; import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle; import org.onap.cps.ncmp.impl.dmi.DmiServiceNameOrganizer; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java index 2ba1b2ab5d..9447f13b68 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java @@ -24,7 +24,8 @@ import java.util.Collection; import java.util.Map; import org.onap.cps.api.model.DataNode; import org.onap.cps.api.parameters.FetchDescendantsOption; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; public interface CmHandleQueryService { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java index 5610013863..59d0f9704e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java @@ -39,8 +39,9 @@ import org.onap.cps.api.model.DataNode; import org.onap.cps.api.parameters.FetchDescendantsOption; import org.onap.cps.cpspath.parser.CpsPathUtil; import org.onap.cps.impl.utils.CpsValidator; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.ModelledDmiServiceLeaves; import org.onap.cps.ncmp.impl.inventory.models.PropertyType; import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelCacheConfig; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java index ed5e703eef..75c52f3c60 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2021-2022 Bell Canada * Modifications Copyright (C) 2023 TechMahindra Ltd. @@ -23,14 +23,13 @@ package org.onap.cps.ncmp.impl.inventory; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED; import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY; import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST; import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE; import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE; import com.google.common.collect.Lists; import com.hazelcast.map.IMap; @@ -52,14 +51,15 @@ import org.onap.cps.api.exceptions.AlreadyDefinedException; import org.onap.cps.api.exceptions.CpsException; import org.onap.cps.api.exceptions.DataNodeNotFoundException; import org.onap.cps.api.exceptions.DataValidationException; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder; import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistrationResponse; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.inventory.sync.ModuleOperationsUtils; import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler; @@ -137,17 +137,20 @@ public class CmHandleRegistrationService { protected void processRemovedCmHandles(final DmiPluginRegistration dmiPluginRegistration, final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { - final List<String> tobeRemovedCmHandleIds = dmiPluginRegistration.getRemovedCmHandles(); + final List<String> toBeRemovedCmHandleIds = dmiPluginRegistration.getRemovedCmHandles(); + if (toBeRemovedCmHandleIds.isEmpty()) { + return; + } final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = - new ArrayList<>(tobeRemovedCmHandleIds.size()); + new ArrayList<>(toBeRemovedCmHandleIds.size()); final Collection<YangModelCmHandle> yangModelCmHandles = - inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandleIds); + inventoryPersistence.getYangModelCmHandles(toBeRemovedCmHandleIds); updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING); final Set<String> notDeletedCmHandles = new HashSet<>(); - for (final List<String> tobeRemovedCmHandleBatch : Lists.partition(tobeRemovedCmHandleIds, DELETE_BATCH_SIZE)) { + for (final List<String> tobeRemovedCmHandleBatch : Lists.partition(toBeRemovedCmHandleIds, DELETE_BATCH_SIZE)) { try { - batchDeleteCmHandlesFromDbAndCaches(tobeRemovedCmHandleBatch); + deleteCmHandlesFromDbAndCaches(tobeRemovedCmHandleBatch); tobeRemovedCmHandleBatch.forEach(cmHandleId -> cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId))); @@ -200,8 +203,9 @@ public class CmHandleRegistrationService { protected void processUpdatedCmHandles(final DmiPluginRegistration dmiPluginRegistration, final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { - dmiPluginRegistrationResponse.setUpdatedCmHandles(cmHandleRegistrationServicePropertyHandler - .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles())); + final List<CmHandleRegistrationResponse> updatedCmHandles = cmHandleRegistrationServicePropertyHandler + .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()); + dmiPluginRegistrationResponse.setUpdatedCmHandles(updatedCmHandles); } protected void processUpgradedCmHandles( @@ -274,7 +278,7 @@ public class CmHandleRegistrationService { private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) { try { - deleteCmHandleFromDbAndCaches(cmHandleId); + deleteCmHandlesFromDbAndCaches(Collections.singletonList(cmHandleId)); return CmHandleRegistrationResponse.createSuccessResponse(cmHandleId); } catch (final DataNodeNotFoundException dataNodeNotFoundException) { log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", @@ -297,16 +301,9 @@ public class CmHandleRegistrationService { lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); } - private void deleteCmHandleFromDbAndCaches(final String cmHandleId) { - inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId); - inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"); - trustLevelManager.removeCmHandles(Collections.singleton(cmHandleId)); - removeDeletedCmHandleFromModuleSyncMap(cmHandleId); - } - - private void batchDeleteCmHandlesFromDbAndCaches(final Collection<String> cmHandleIds) { - inventoryPersistence.deleteSchemaSetsWithCascade(cmHandleIds); + private void deleteCmHandlesFromDbAndCaches(final Collection<String> cmHandleIds) { inventoryPersistence.deleteDataNodes(mapCmHandleIdsToXpaths(cmHandleIds)); + inventoryPersistence.deleteAnchors(cmHandleIds); trustLevelManager.removeCmHandles(cmHandleIds); cmHandleIds.forEach(this::removeDeletedCmHandleFromModuleSyncMap); } @@ -325,8 +322,11 @@ public class CmHandleRegistrationService { private List<CmHandleRegistrationResponse> upgradeCmHandles(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) { + if (cmHandleStatePerCmHandle.isEmpty()) { + return Collections.emptyList(); + } final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle); - log.info("Moving cm handles : {} into locked (for upgrade) state.", cmHandleIds); + log.info("Moving {} cm handles into locked (for upgrade) state: {} ", cmHandleIds.size(), cmHandleIds); try { lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds); @@ -346,7 +346,7 @@ public class CmHandleRegistrationService { final Collection<String> rejectedCmHandleIds = alternateIdChecker .getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated, AlternateIdChecker.Operation.CREATE); cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses( - rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED)); + rejectedCmHandleIds, CM_HANDLE_ALREADY_EXIST)); return rejectedCmHandleIds; } @@ -383,5 +383,4 @@ public class CmHandleRegistrationService { ncmpServiceCmHandle.getDataProducerIdentifier()); } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java index b7a13d9989..3415793478 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * Modifications Copyright (C) 2024 TechMahindra Ltd. * ================================================================================ @@ -22,8 +22,8 @@ package org.onap.cps.ncmp.impl.inventory; -import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED; import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND; +import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST; import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID; import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.DMI_PROPERTY; import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.PUBLIC_PROPERTY; @@ -49,7 +49,7 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.api.exceptions.DataNodeNotFoundException; import org.onap.cps.api.exceptions.DataValidationException; import org.onap.cps.api.model.DataNode; -import org.onap.cps.api.model.DataNodeBuilder; +import org.onap.cps.impl.DataNodeBuilder; import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; @@ -81,7 +81,7 @@ public class CmHandleRegistrationServicePropertyHandler { final Collection<String> rejectedCmHandleIds = alternateIdChecker .getIdsOfCmHandlesWithRejectedAlternateId(updatedNcmpServiceCmHandles, AlternateIdChecker.Operation.UPDATE); final List<CmHandleRegistrationResponse> failureResponses = - CmHandleRegistrationResponse.createFailureResponses(rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED); + CmHandleRegistrationResponse.createFailureResponses(rejectedCmHandleIds, CM_HANDLE_ALREADY_EXIST); final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>(failureResponses); for (final NcmpServiceCmHandle updatedNcmpServiceCmHandle : updatedNcmpServiceCmHandles) { final String cmHandleId = updatedNcmpServiceCmHandle.getCmHandleId(); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java index 685d204633..e9a617d1f6 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java @@ -23,8 +23,9 @@ package org.onap.cps.ncmp.impl.inventory; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.CompositeState; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; /** * It will have all the utility method responsible for handling the composite state. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java index d566ae43cb..e7ec9cd13c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * Modifications Copyright (C) 2024 TechMahindra Ltd. * ================================================================================ @@ -62,26 +62,27 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv private static final int CMHANDLE_BATCH_SIZE = 100; private final CpsModuleService cpsModuleService; - private final CpsAnchorService cpsAnchorService; private final CpsValidator cpsValidator; private final CmHandleQueryService cmHandleQueryService; /** * 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 cpsAnchorService cps anchor service instance + * @param cpsValidator cps validation service instance + * @param jsonObjectMapper json mapper object + * @param cpsAnchorService cps anchor service instance + * @param cpsModuleService cps module service instance + * @param cpsDataService cps data service instance + * @param cmHandleQueryService cm handle query service instance */ - public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService, - final CpsModuleService cpsModuleService, final CpsValidator cpsValidator, + public InventoryPersistenceImpl(final CpsValidator cpsValidator, + final JsonObjectMapper jsonObjectMapper, final CpsAnchorService cpsAnchorService, + final CpsModuleService cpsModuleService, + final CpsDataService cpsDataService, final CmHandleQueryService cmHandleQueryService) { - super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator); + super(jsonObjectMapper, cpsAnchorService, cpsDataService); this.cpsModuleService = cpsModuleService; - this.cpsAnchorService = cpsAnchorService; this.cpsValidator = cpsValidator; this.cmHandleQueryService = cmHandleQueryService; } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java index 714a7ca12f..f327edab17 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,9 +25,6 @@ import java.util.Collection; import org.onap.cps.api.model.DataNode; import org.onap.cps.api.parameters.FetchDescendantsOption; -/** - * DmiRegistryConstants class to be strictly used for DMI Related constants only. - */ public interface NcmpPersistence { String NCMP_DATASPACE_NAME = "NCMP-Admin"; @@ -44,20 +41,6 @@ public interface NcmpPersistence { 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<String> schemaSetNames); - - /** * Get data node via xpath. * * @param xpath xpath @@ -113,4 +96,12 @@ public interface NcmpPersistence { * @param dataNodeXpaths data node xpaths */ void deleteDataNodes(Collection<String> dataNodeXpaths); + + /** + * Deletes multiple anchors identified by their IDs. + * + * @param anchorIds ids of the anchors to be deleted + */ + void deleteAnchors(Collection<String> anchorIds); + } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java index 6092d8b3b9..2232d7ce12 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation + * Copyright (C) 2023-2025 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,31 +20,25 @@ package org.onap.cps.ncmp.impl.inventory; -import static org.onap.cps.api.parameters.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; import static org.onap.cps.api.parameters.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.CpsAnchorService; import org.onap.cps.api.CpsDataService; -import org.onap.cps.api.CpsModuleService; -import org.onap.cps.api.exceptions.SchemaSetNotFoundException; import org.onap.cps.api.model.DataNode; import org.onap.cps.api.parameters.FetchDescendantsOption; -import org.onap.cps.impl.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 CpsAnchorService cpsAnchorService; protected final CpsDataService cpsDataService; - private final CpsModuleService cpsModuleService; - private final CpsValidator cpsValidator; @Override public void deleteListOrListElement(final String listElementXpath) { @@ -53,27 +47,6 @@ public class NcmpPersistenceImpl implements NcmpPersistence { } @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<String> 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<DataNode> getDataNode(final String xpath) { @@ -116,4 +89,9 @@ public class NcmpPersistenceImpl implements NcmpPersistence { cpsDataService.deleteDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpaths, NO_TIMESTAMP); } + @Override + public void deleteAnchors(final Collection<String> anchorIds) { + cpsAnchorService.deleteAnchors(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, anchorIds); + } + } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java index c3973236f0..af78d95742 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java @@ -29,8 +29,8 @@ 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.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.models.CompositeState; -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java index 2895d9b77c..e9f3d9b475 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java @@ -36,12 +36,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.model.DataNode; import org.onap.cps.api.parameters.FetchDescendantsOption; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.api.inventory.models.LockReasonCategory; import org.onap.cps.ncmp.impl.data.DmiDataOperations; import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; -import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.utils.YangDataConverter; import org.onap.cps.utils.JsonObjectMapper; @@ -189,7 +189,7 @@ public class ModuleOperationsUtils { .getLockReasonCategory())); } - public static String getUpgradedModuleSetTagFromLockReason(final CompositeState.LockReason lockReason) { + public static String getTargetModuleSetTagFromLockReason(final CompositeState.LockReason lockReason) { return getLockedCompositeStateDetails(lockReason).getOrDefault(MODULE_SET_TAG_KEY, ""); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java index a46fb62085..6c1dc731c6 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2024 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,24 +26,18 @@ import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT; import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME; -import com.hazelcast.collection.ISet; import java.time.OffsetDateTime; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; import java.util.Map; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.logging.log4j.util.Strings; import org.onap.cps.api.CpsAnchorService; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsModuleService; -import org.onap.cps.api.exceptions.SchemaSetNotFoundException; +import org.onap.cps.api.exceptions.AlreadyDefinedException; +import org.onap.cps.api.exceptions.DuplicatedYangResourceException; import org.onap.cps.api.model.ModuleReference; -import org.onap.cps.api.parameters.CascadeDeleteAllowed; -import org.onap.cps.ncmp.api.exceptions.NcmpException; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.utils.ContentType; import org.onap.cps.utils.JsonObjectMapper; @@ -54,15 +48,11 @@ import org.springframework.stereotype.Service; @RequiredArgsConstructor public class ModuleSyncService { - private static final Map<String, String> NO_NEW_MODULES = Collections.emptyMap(); - private final DmiModelOperations dmiModelOperations; private final CpsModuleService cpsModuleService; private final CpsDataService cpsDataService; private final CpsAnchorService cpsAnchorService; private final JsonObjectMapper jsonObjectMapper; - private final ISet<String> moduleSetTagsBeingProcessed; - private final Map<String, ModuleDelta> privateModuleSetCache = new HashMap<>(); @AllArgsConstructor private static final class ModuleDelta { @@ -71,41 +61,20 @@ public class ModuleSyncService { } /** - * This method creates a cm handle and initiates modules sync. + * Creates a CM handle and initiates the synchronization of modules to create a schema set and anchor. * * @param yangModelCmHandle the yang model of cm handle. */ public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) { + final String cmHandleId = yangModelCmHandle.getId(); final String moduleSetTag = yangModelCmHandle.getModuleSetTag(); - final ModuleDelta moduleDelta; - boolean isNewModuleSetTag = Strings.isNotBlank(moduleSetTag); + final String schemaSetName = getSchemaSetName(cmHandleId, moduleSetTag); + syncAndCreateSchemaSet(yangModelCmHandle, schemaSetName); try { - if (privateModuleSetCache.containsKey(moduleSetTag)) { - moduleDelta = privateModuleSetCache.get(moduleSetTag); - } else { - if (isNewModuleSetTag) { - if (moduleSetTagsBeingProcessed.add(moduleSetTag)) { - log.info("Processing new module set tag {}", moduleSetTag); - } else { - isNewModuleSetTag = false; - throw new NcmpException("Concurrent processing of module set tag " + moduleSetTag, - moduleSetTag + " already being processed for cm handle " + yangModelCmHandle.getId()); - } - } - moduleDelta = getModuleDelta(yangModelCmHandle, moduleSetTag); - } - final String cmHandleId = yangModelCmHandle.getId(); - cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, - moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); - cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId); - if (isNewModuleSetTag) { - final ModuleDelta noModuleDelta = new ModuleDelta(moduleDelta.allModuleReferences, NO_NEW_MODULES); - privateModuleSetCache.put(moduleSetTag, noModuleDelta); - } - } finally { - if (isNewModuleSetTag) { - moduleSetTagsBeingProcessed.remove(moduleSetTag); - } + cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName, cmHandleId); + } catch (final AlreadyDefinedException alreadyDefinedException) { + log.warn("Ignoring (anchor) already exist exception for {}. Exception details: ", + yangModelCmHandle.getId(), alreadyDefinedException); } } @@ -115,55 +84,68 @@ public class ModuleSyncService { * @param yangModelCmHandle the yang model of cm handle. */ public void syncAndUpgradeSchemaSet(final YangModelCmHandle yangModelCmHandle) { - final String upgradedModuleSetTag = ModuleOperationsUtils.getUpgradedModuleSetTagFromLockReason( + final String cmHandleId = yangModelCmHandle.getId(); + final String sourceModuleSetTag = yangModelCmHandle.getModuleSetTag(); + final String targetModuleSetTag = ModuleOperationsUtils.getTargetModuleSetTagFromLockReason( yangModelCmHandle.getCompositeState().getLockReason()); - final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle, upgradedModuleSetTag); - cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, - yangModelCmHandle.getId(), moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); - setCmHandleModuleSetTag(yangModelCmHandle, upgradedModuleSetTag); + if (sourceModuleSetTag.isEmpty() && targetModuleSetTag.isEmpty()) { + final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle); + cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, + cmHandleId, moduleDelta.newModuleNameToContentMap, moduleDelta.allModuleReferences); + } else { + final String targetSchemaSetName = getSchemaSetName(cmHandleId, targetModuleSetTag); + syncAndCreateSchemaSet(yangModelCmHandle, targetSchemaSetName); + cpsAnchorService.updateAnchorSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, + targetSchemaSetName); + setCmHandleModuleSetTag(yangModelCmHandle, targetModuleSetTag); + log.info("Upgrading schema set for CM handle ID: {}, Source Tag: {}, Target Tag: {}", + cmHandleId, sourceModuleSetTag, targetModuleSetTag); + } } - /** - * 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); + private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle, final String schemaSetName) { + if (isNewSchemaSet(schemaSetName)) { + final ModuleDelta moduleDelta = getModuleDelta(yangModelCmHandle); + try { + log.info("Creating Schema Set {} for CM Handle {}", schemaSetName, yangModelCmHandle.getId()); + cpsModuleService.createSchemaSetFromModules( + NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, + schemaSetName, + moduleDelta.newModuleNameToContentMap, + moduleDelta.allModuleReferences + ); + log.info("Successfully created Schema Set {} for CM Handle {}", schemaSetName, + yangModelCmHandle.getId()); + } catch (final AlreadyDefinedException alreadyDefinedException) { + log.warn("Ignoring already exist (schema set) exception for {}. Exception details: ", + yangModelCmHandle.getId(), alreadyDefinedException); + } catch (final DuplicatedYangResourceException duplicatedYangResourceException) { + log.warn("Duplicate Yang Resource {} creation for {}. " + + "CM Handle will be LOCKED (for retry). Exception details: ", + duplicatedYangResourceException.getName(), + yangModelCmHandle.getId(), + duplicatedYangResourceException); + throw duplicatedYangResourceException; + } } } - public void clearPrivateModuleSetCache() { - privateModuleSetCache.clear(); + private boolean isNewSchemaSet(final String schemaSetName) { + return !cpsModuleService.schemaSetExists(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName); } - private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle, final String targetModuleSetTag) { - final Map<String, String> newYangResources; - Collection<ModuleReference> allModuleReferences = getModuleReferencesByModuleSetTag(targetModuleSetTag); - if (allModuleReferences.isEmpty()) { - allModuleReferences = dmiModelOperations.getModuleReferences(yangModelCmHandle); - newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, - cpsModuleService.identifyNewModuleReferences(allModuleReferences)); - } else { - log.info("Found other cm handle having same module set tag: {}", targetModuleSetTag); - newYangResources = NO_NEW_MODULES; - } + private ModuleDelta getModuleDelta(final YangModelCmHandle yangModelCmHandle) { + final Collection<ModuleReference> allModuleReferences = + dmiModelOperations.getModuleReferences(yangModelCmHandle); + final Collection<ModuleReference> newModuleReferences = + cpsModuleService.identifyNewModuleReferences(allModuleReferences); + final Map<String, String> newYangResources = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, + newModuleReferences); + log.debug("Module delta calculated for CM handle ID: {}. All references: {}. New modules: {}", + yangModelCmHandle.getId(), allModuleReferences, newYangResources.keySet()); return new ModuleDelta(allModuleReferences, newYangResources); } - private Collection<ModuleReference> getModuleReferencesByModuleSetTag(final String moduleSetTag) { - if (Strings.isBlank(moduleSetTag)) { - return Collections.emptyList(); - } - return cpsModuleService.getModuleReferencesByAttribute(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - Map.of("module-set-tag", moduleSetTag), Map.of("cm-handle-state", CmHandleState.READY.name())); - } - private void setCmHandleModuleSetTag(final YangModelCmHandle yangModelCmHandle, final String newModuleSetTag) { final String jsonForUpdate = jsonObjectMapper.asJsonString(Map.of( "cm-handles", Map.of("id", yangModelCmHandle.getId(), "module-set-tag", newModuleSetTag))); @@ -171,4 +153,8 @@ public class ModuleSyncService { jsonForUpdate, OffsetDateTime.now(), ContentType.JSON); } + private static String getSchemaSetName(final String cmHandleId, final String moduleSetTag) { + return moduleSetTag.isEmpty() ? cmHandleId : moduleSetTag; + } + } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java index 9450805eaf..b63496753e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,10 +29,10 @@ import java.util.concurrent.atomic.AtomicInteger; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.exceptions.DataNodeNotFoundException; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.CompositeState; +import org.onap.cps.ncmp.api.inventory.models.LockReasonCategory; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; -import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler; import org.springframework.stereotype.Component; @@ -109,13 +109,12 @@ public class ModuleSyncTasks { if (inUpgrade) { moduleSyncService.syncAndUpgradeSchemaSet(yangModelCmHandle); } else { - moduleSyncService.deleteSchemaSetIfExists(yangModelCmHandle.getId()); moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle); } compositeState.setLockReason(null); return CmHandleState.READY; } catch (final Exception e) { - log.warn("Processing of {} module failed due to reason {}.", yangModelCmHandle.getId(), e.getMessage()); + log.warn("Processing of {} failed,reason : ", yangModelCmHandle.getId(), e); final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED : LockReasonCategory.MODULE_SYNC_FAILED; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java index d6ac242b30..c05944f66e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================== - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 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,13 +20,10 @@ package org.onap.cps.ncmp.impl.inventory.sync; -import com.hazelcast.collection.ISet; import com.hazelcast.config.MapConfig; import com.hazelcast.config.QueueConfig; -import com.hazelcast.config.SetConfig; import com.hazelcast.map.IMap; import java.util.concurrent.BlockingQueue; -import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.impl.cache.HazelcastCacheConfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,7 +31,6 @@ import org.springframework.context.annotation.Configuration; /** * Core infrastructure of the hazelcast distributed caches for Module Sync and Data Sync use cases. */ -@Slf4j @Configuration public class SynchronizationCacheConfig extends HazelcastCacheConfig { @@ -45,8 +41,6 @@ public class SynchronizationCacheConfig extends HazelcastCacheConfig { private static final MapConfig moduleSyncStartedConfig = createMapConfigWithTimeToLiveInSeconds("moduleSyncStartedConfig", MODULE_SYNC_STARTED_TTL_SECS); private static final MapConfig dataSyncSemaphoresConfig = createMapConfig("dataSyncSemaphoresConfig"); - private static final SetConfig moduleSetTagsBeingProcessedConfig - = createSetConfig("moduleSetTagsBeingProcessedConfig"); /** * Module Sync Distributed Queue Instance. @@ -78,14 +72,4 @@ public class SynchronizationCacheConfig extends HazelcastCacheConfig { return getOrCreateHazelcastInstance(dataSyncSemaphoresConfig).getMap("dataSyncSemaphores"); } - /** - * Collection of (new) module set tags being processed. - * To prevent processing on multiple threads of same tag - * - * @return set of module set tags being processed - */ - @Bean - public ISet<String> moduleSetTagsBeingProcessed() { - return getOrCreateHazelcastInstance(moduleSetTagsBeingProcessedConfig).getSet("moduleSetTagsBeingProcessed"); - } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java index 4fd752c0d1..708508e9d8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java @@ -25,18 +25,42 @@ import com.hazelcast.map.IMap; import java.util.Collection; import java.util.Map; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.CompositeState; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair; +import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent; +import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor +@Slf4j public class CmHandleStateMonitor { - private static final String METRIC_POSTFIX = "CmHandlesCount"; - final IMap<String, Integer> cmHandlesByState; + + private final CmHandleQueryService cmHandleQueryService; + private final IMap<String, Integer> cmHandlesByState; + + /** + * Method to initialise cm handle state monitor by querying the current state counts + * and storing them in the provided map. This method is triggered by NcmpInventoryModelOnboardingFinishedEvent. + * + * @param ncmpInventoryModelOnboardingFinishedEvent the event that triggers the initialization + */ + @EventListener + public void initialiseCmHandleStateMonitor( + final NcmpInventoryModelOnboardingFinishedEvent ncmpInventoryModelOnboardingFinishedEvent) { + for (final CmHandleState cmHandleState : CmHandleState.values()) { + final String cmHandleStateAsString = cmHandleState.name().toLowerCase(); + final String stateMetricKey = cmHandleStateAsString + METRIC_POSTFIX; + final int cmHandleCountForState = cmHandleQueryService.queryCmHandleIdsByState(cmHandleState).size(); + cmHandlesByState.putIfAbsent(stateMetricKey, cmHandleCountForState); + log.info("Cm handle state monitor has set " + stateMetricKey + " to " + cmHandleCountForState); + } + } /** * Asynchronously update the cm handle state metrics. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandler.java index de3df6b9da..69409bbbca 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandler.java @@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.inventory.sync.lcm; import java.util.Collection; import java.util.Map; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; /** diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java index 3e6597ea39..5ca19886fa 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java @@ -20,10 +20,10 @@ package org.onap.cps.ncmp.impl.inventory.sync.lcm; -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED; -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED; -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.LOCKED; -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY; +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.ADVISED; +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.DELETED; +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.LOCKED; +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY; import io.micrometer.core.annotation.Timed; import java.util.ArrayList; @@ -37,10 +37,10 @@ import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.models.CmHandleState; import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.impl.inventory.CompositeStateUtils; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.springframework.stereotype.Service; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorHelper.java index 348894d1b4..e4fb5c3ce8 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorHelper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorHelper.java @@ -20,7 +20,7 @@ package org.onap.cps.ncmp.impl.inventory.sync.lcm; -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED; +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.DELETED; import static org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventType.CREATE; import static org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventType.DELETE; import static org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventType.UPDATE; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java index eefabd1079..0214c0c2a9 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,8 +41,6 @@ import reactor.netty.resources.ConnectionProvider; */ public class WebClientConfiguration { - private static final Duration DEFAULT_RESPONSE_TIMEOUT = Duration.ofSeconds(30); - protected WebClient configureWebClient(final WebClient.Builder webClientBuilder, final ServiceConfig serviceConfig) { final ConnectionProvider connectionProvider = getConnectionProvider(serviceConfig); @@ -53,7 +51,7 @@ public class WebClientConfiguration { private static HttpClient createHttpClient(final ServiceConfig serviceConfig, final ConnectionProvider connectionProvider) { return HttpClient.create(connectionProvider) - .responseTimeout(DEFAULT_RESPONSE_TIMEOUT) + .responseTimeout(Duration.ofSeconds(serviceConfig.getResponseTimeoutInSeconds())) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, serviceConfig.getConnectionTimeoutInSeconds() * 1000) .doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler( serviceConfig.getReadTimeoutInSeconds(), TimeUnit.SECONDS)).addHandlerLast( 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 58a5f553af..514d9b8fe4 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 @@ -30,11 +30,15 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsDataspaceService; import org.onap.cps.api.CpsModuleService; import org.onap.cps.init.AbstractModelLoader; +import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @Slf4j @Service public class InventoryModelLoader extends AbstractModelLoader { + + private final ApplicationEventPublisher applicationEventPublisher; private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2024-02-23.yang"; private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2024-02-23"; private static final String REGISTRY_DATANODE_NAME = "dmi-registry"; @@ -42,14 +46,17 @@ public class InventoryModelLoader extends AbstractModelLoader { public InventoryModelLoader(final CpsDataspaceService cpsDataspaceService, final CpsModuleService cpsModuleService, final CpsAnchorService cpsAnchorService, - final CpsDataService cpsDataService) { + final CpsDataService cpsDataService, + final ApplicationEventPublisher applicationEventPublisher) { super(cpsDataspaceService, cpsModuleService, cpsAnchorService, cpsDataService); + this.applicationEventPublisher = applicationEventPublisher; } @Override public void onboardOrUpgradeModel() { updateInventoryModel(); log.info("Inventory Model updated successfully"); + applicationEventPublisher.publishEvent(new NcmpInventoryModelOnboardingFinishedEvent(this)); } private void updateInventoryModel() { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java new file mode 100644 index 0000000000..92d5e8241d --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2025 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.utils.events; + +import org.springframework.context.ApplicationEvent; + +/** + * Custom event triggered when the NCMP inventory model onboarding process is completed. + * Extends Spring's {@link ApplicationEvent} to be used within Spring's event-driven architecture. + */ +public class NcmpInventoryModelOnboardingFinishedEvent extends ApplicationEvent { + + /** + * Creates a new instance of NcmpModelOnboardingFinishedEvent. + * + * @param source the object that is the source of the event (i.e. the source that completed the onboarding process) + */ + public NcmpInventoryModelOnboardingFinishedEvent(final Object source) { + super(source); + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy index 055a6e7448..c49af0f01b 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada - * Modifications Copyright (C) 2023-2024 Nordix Foundation + * Modifications Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import spock.lang.Specification import java.util.stream.Collectors -import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR @@ -89,14 +88,14 @@ class CmHandleRegistrationResponseSpec extends Specification { } def 'Failed cm-handle registration based on cm handle id and registration error'() { - when: 'the failure response is created with "alternate id already associated" error code for 1 cm handle' + when: 'the failure response is created with "cm-handle already exists" error code for 1 cm handle' def cmHandleRegistrationResponses = - CmHandleRegistrationResponse.createFailureResponses(['ch 1'], ALTERNATE_ID_ALREADY_ASSOCIATED) + CmHandleRegistrationResponse.createFailureResponses(['ch 1'], CM_HANDLE_ALREADY_EXIST) then: 'the response with expected values' assert cmHandleRegistrationResponses[0].cmHandle == 'ch 1' assert cmHandleRegistrationResponses[0].status == Status.FAILURE - assert cmHandleRegistrationResponses[0].ncmpResponseStatus == ALTERNATE_ID_ALREADY_ASSOCIATED - assert cmHandleRegistrationResponses[0].errorText == 'alternate id already associated' + assert cmHandleRegistrationResponses[0].ncmpResponseStatus == CM_HANDLE_ALREADY_EXIST + assert cmHandleRegistrationResponses[0].errorText == 'cm-handle already exists' } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilderSpec.groovy index b01f4dfa0e..8b04568239 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilderSpec.groovy @@ -22,11 +22,9 @@ package org.onap.cps.ncmp.api.inventory.models -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState -import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import org.onap.cps.api.model.DataNode -import org.onap.cps.api.model.DataNodeBuilder +import org.onap.cps.impl.DataNodeBuilder import spock.lang.Specification import java.time.OffsetDateTime diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateSpec.groovy index f6e4c8870e..4ee05104ee 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateSpec.groovy @@ -21,9 +21,7 @@ package org.onap.cps.ncmp.api.inventory.models import com.fasterxml.jackson.databind.ObjectMapper -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState -import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import spock.lang.Specification import java.time.OffsetDateTime diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy index 23f5edd890..387252e163 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,7 @@ class DmiHttpClientConfigSpec extends Specification { assert connectionTimeoutInSeconds == 4 assert readTimeoutInSeconds == 5 assert writeTimeoutInSeconds == 6 + assert responseTimeoutInSeconds == 60 } } @@ -56,6 +57,7 @@ class DmiHttpClientConfigSpec extends Specification { assert connectionTimeoutInSeconds == 14 assert readTimeoutInSeconds == 15 assert writeTimeoutInSeconds == 16 + assert responseTimeoutInSeconds == 60 } } @@ -68,6 +70,7 @@ class DmiHttpClientConfigSpec extends Specification { assert connectionTimeoutInSeconds == 24 assert readTimeoutInSeconds == 25 assert writeTimeoutInSeconds == 26 + assert responseTimeoutInSeconds == 60 } } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy index b988f9e171..3df910322c 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ class PolicyExecutorHttpClientConfigSpec extends Specification { assert pendingAcquireMaxCount == 33 assert connectionTimeoutInSeconds == 34 assert writeTimeoutInSeconds == 36 + assert responseTimeoutInSeconds == 60 } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy index 9b9603369d..a576865262 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy @@ -45,13 +45,5 @@ class AdminCacheConfigSpec extends Specification { assert Hazelcast.allHazelcastInstances.size() > 0 and: 'Hazelcast cache instance for cm handle by state is present' assert Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').getMap('cmHandlesByState') != null - and: 'the cache already contains 5 entries, an entry for each state' - def cmHandleByState = Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').getMap('cmHandlesByState') - assert cmHandleByState.size() == 5 - assert cmHandleByState.containsKey('advisedCmHandlesCount') - assert cmHandleByState.containsKey('lockedCmHandlesCount') - assert cmHandleByState.containsKey('readyCmHandlesCount') - assert cmHandleByState.containsKey('deletingCmHandlesCount') - assert cmHandleByState.containsKey('deletedCmHandlesCount') } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy index f1447f4eb5..01a08e7bb5 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy @@ -22,21 +22,21 @@ package org.onap.cps.ncmp.impl.data import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.api.exceptions.DataNodeNotFoundException +import org.onap.cps.api.exceptions.DataValidationException import org.onap.cps.events.EventsPublisher import org.onap.cps.ncmp.api.data.models.CmResourceAddress import org.onap.cps.ncmp.api.data.models.DataOperationRequest import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.config.CpsApplicationContext import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec import org.onap.cps.ncmp.impl.dmi.DmiProperties -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import org.onap.cps.ncmp.utils.TestUtils -import org.onap.cps.api.exceptions.DataNodeNotFoundException -import org.onap.cps.api.exceptions.DataValidationException import org.onap.cps.utils.JsonObjectMapper import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy index 77e2c4fa25..33b8490e5e 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy @@ -42,8 +42,8 @@ import org.springframework.util.LinkedMultiValueMap import java.time.Duration -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY import static org.onap.cps.ncmp.utils.events.CloudEventMapper.toTargetEvent @ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext]) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy index d00d3ab8f6..1edee4e355 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy @@ -23,7 +23,7 @@ package org.onap.cps.ncmp.impl.dmi import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.impl.inventory.InventoryPersistence -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.spockframework.spring.SpringBean import spock.lang.Shared diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy index 1c8a19a3bd..811e4ea526 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy @@ -27,8 +27,9 @@ import com.hazelcast.instance.impl.HazelcastInstanceFactory import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsQueryService import org.onap.cps.impl.utils.CpsValidator +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import org.onap.cps.ncmp.api.inventory.models.TrustLevel -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.api.model.DataNode import spock.lang.Specification diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandlerSpec.groovy index b600d02be5..70bd418026 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandlerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandlerSpec.groovy @@ -32,7 +32,7 @@ import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.api.exceptions.DataNodeNotFoundException import org.onap.cps.api.exceptions.DataValidationException import org.onap.cps.api.model.DataNode -import org.onap.cps.api.model.DataNodeBuilder +import org.onap.cps.impl.DataNodeBuilder import org.onap.cps.utils.ContentType import org.onap.cps.utils.JsonObjectMapper import org.slf4j.LoggerFactory diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy index 0706a1e19f..953e1c7d0e 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation + * Copyright (C) 2021-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,23 +23,22 @@ package org.onap.cps.ncmp.impl.inventory import com.hazelcast.map.IMap import org.onap.cps.api.CpsDataService -import org.onap.cps.api.CpsModuleService +import org.onap.cps.api.exceptions.AlreadyDefinedException +import org.onap.cps.api.exceptions.CpsException +import org.onap.cps.api.exceptions.DataNodeNotFoundException +import org.onap.cps.api.exceptions.DataValidationException import org.onap.cps.ncmp.api.exceptions.DmiRequestException +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.api.inventory.models.UpgradedCmHandles -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager -import org.onap.cps.api.exceptions.AlreadyDefinedException -import org.onap.cps.api.exceptions.CpsException -import org.onap.cps.api.exceptions.DataNodeNotFoundException -import org.onap.cps.api.exceptions.DataValidationException -import org.onap.cps.api.exceptions.SchemaSetNotFoundException import spock.lang.Specification import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND @@ -52,7 +51,6 @@ import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_D class CmHandleRegistrationServiceSpec extends Specification { def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id') - def mockCpsModuleService = Mock(CpsModuleService) def mockNetworkCmProxyDataServicePropertyHandler = Mock(CmHandleRegistrationServicePropertyHandler) def mockInventoryPersistence = Mock(InventoryPersistence) def mockCmHandleQueries = Mock(CmHandleQueryService) @@ -79,33 +77,43 @@ class CmHandleRegistrationServiceSpec extends Specification { def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server') dmiRegistration.setCreatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-1', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])]) dmiRegistration.setUpdatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-2', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])]) - dmiRegistration.setRemovedCmHandles(['cmhandle-2']) - dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag')) - and: 'cm handles are persisted' + dmiRegistration.setRemovedCmHandles(['cmhandle-3']) + dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-4', 'cmhandle-5'], moduleSetTag: moduleSetTagForUpgrade)) + and: 'cm handles 2,3 and 4 already exist in the inventory' mockInventoryPersistence.getYangModelCmHandles(['cmhandle-2']) >> [new YangModelCmHandle()] - mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: CmHandleState.READY)) - and: 'cm handle is in READY state' - mockCmHandleQueries.cmHandleHasState('cmhandle-3', CmHandleState.READY) >> true - and: 'cm handles is present in in-progress map' - mockModuleSyncStartedOnCmHandles.containsKey('cmhandle-2') >> true + mockInventoryPersistence.getYangModelCmHandles(['cmhandle-3']) >> [new YangModelCmHandle()] + mockInventoryPersistence.getYangModelCmHandle('cmhandle-4') >> new YangModelCmHandle(id: 'cmhandle-4', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: CmHandleState.READY)) + and: 'cm handle 5 also exist but already has the new module set tag (upgrade to)' + mockInventoryPersistence.getYangModelCmHandle('cmhandle-5') >> new YangModelCmHandle(id: 'cmhandle-5', moduleSetTag: moduleSetTagForUpgrade , compositeState: new CompositeState(cmHandleState: CmHandleState.READY)) + and: 'all cm handles are in READY state' + mockCmHandleQueries.cmHandleHasState(_, CmHandleState.READY) >> true + and: 'cm handle to be removed is in progress map' + mockModuleSyncStartedOnCmHandles.containsKey('cmhandle-3') >> true when: 'registration is processed' - objectUnderTest.updateDmiRegistration(dmiRegistration) + def result = objectUnderTest.updateDmiRegistration(dmiRegistration) then: 'cm-handles are removed first' 1 * objectUnderTest.processRemovedCmHandles(*_) and: 'de-registered cm handle entry is removed from in progress map' - 1 * mockModuleSyncStartedOnCmHandles.removeAsync('cmhandle-2') - then: 'cm-handles are updated' + 1 * mockModuleSyncStartedOnCmHandles.removeAsync('cmhandle-3') + then: 'updated cm handles are processed by the property handler service' 1 * objectUnderTest.processUpdatedCmHandles(*_) - 1 * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> [] + 1 * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> [CmHandleRegistrationResponse.createSuccessResponse('cmhandle-2')] then: 'cm-handles are upgraded' 1 * objectUnderTest.processUpgradedCmHandles(*_) + and: 'result contains the correct cm handles for each operation' + assert result.createdCmHandles.cmHandle == ['cmhandle-1'] + assert result.updatedCmHandles.cmHandle == ['cmhandle-2'] + assert result.removedCmHandles.cmHandle == ['cmhandle-3'] + assert result.upgradedCmHandles.cmHandle as Set == ['cmhandle-4', 'cmhandle-5'] as Set + where: 'upgrade with and without module set tag' + moduleSetTagForUpgrade << ['some tag', ''] } def 'DMI Registration upgrade operation with upgrade node state #scenario'() { given: 'a registration with upgrade operation' def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server') dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag')) - and: 'exception while checking cm handle state' + and: 'cm handle has the state #cmHandleState' mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: cmHandleState)) when: 'registration is processed' def result = objectUnderTest.updateDmiRegistration(dmiRegistration) @@ -133,6 +141,21 @@ class CmHandleRegistrationServiceSpec extends Specification { 'cm handle is invalid' | new DataValidationException('some error message', 'some error details') || '110' } + def 'DMI Registration upgrade with exception while updating CM-handle state'() { + given: 'a registration with upgrade operation' + def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server') + dmiRegistration.setUpgradedCmHandles(new UpgradedCmHandles(cmHandles: ['cmhandle-3'], moduleSetTag: 'some-module-set-tag')) + and: 'cm handle has the state READY' + mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: CmHandleState.READY)) + and: 'exception will occur while updating cm handle state to LOCKED for upgrade' + mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { throw new RuntimeException() } + when: 'registration is processed' + def result = objectUnderTest.updateDmiRegistration(dmiRegistration) + then: 'upgrade operation contains expected error code' + assert result.upgradedCmHandles[0].status == Status.FAILURE + assert result.upgradedCmHandles[0].ncmpResponseStatus == UNKNOWN_ERROR + } + def 'Create CM-handle Validation: Registration with valid Service names: #scenario'() { given: 'a registration ' def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: dmiPlugin, dmiModelPlugin: dmiModelPlugin, @@ -275,18 +298,15 @@ class CmHandleRegistrationServiceSpec extends Specification { assert response.updatedCmHandles.containsAll(updateOperationResponse) } - def 'Remove CmHandle Successfully: #scenario'() { - given: 'a registration' + def 'Remove CmHandle Successfully'() { + given: 'a registration update to delete a cm handle' def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', removedCmHandles: ['cmhandle']) - and: '#scenario' - mockCpsModuleService.deleteSchemaSetsWithCascade(_, ['cmhandle']) >> { if (!schemaSetExist) { throw new SchemaSetNotFoundException('', '') } } - when: 'registration is updated to delete cmhandle' + when: 'the registration is updated' def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration) - then: 'the cmHandle state is updated to "DELETING"' - 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> - { args -> args[0].values()[0] == CmHandleState.DELETING } - then: 'method to delete relevant schema set is called once' - 1 * mockInventoryPersistence.deleteSchemaSetsWithCascade(_) + then: 'the cmHandle state is set to "DELETING"' + 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> args[0].values()[0] == CmHandleState.DELETING } + then: 'method to delete anchors is called once' + 1 * mockInventoryPersistence.deleteAnchors(_) and: 'method to delete relevant list/list element is called once' 1 * mockInventoryPersistence.deleteDataNodes(_) and: 'successful response is received' @@ -296,14 +316,7 @@ class CmHandleRegistrationServiceSpec extends Specification { assert it.cmHandle == 'cmhandle' } and: 'the cmHandle state is updated to "DELETED"' - 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> - { args -> args[0].values()[0] == CmHandleState.DELETED } - and: 'No cm handles state updates for "upgraded cm handles"' - 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch([:]) - where: - scenario | schemaSetExist - 'schema-set exists and can be deleted successfully' | true - 'schema-set does not exist' | false + 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args -> args[0].values()[0] == CmHandleState.DELETED } } def 'Remove CmHandle: Partial Success'() { @@ -313,10 +326,11 @@ class CmHandleRegistrationServiceSpec extends Specification { and: 'cm handles to be deleted in the progress map' mockModuleSyncStartedOnCmHandles.containsKey("cmhandle1") >> true mockModuleSyncStartedOnCmHandles.containsKey("cmhandle3") >> true - and: 'cm-handle deletion fails on batch' - mockInventoryPersistence.deleteDataNodes(_) >> { throw new RuntimeException("Failed") } - and: 'cm-handle deletion is successful for 1st and 3rd; failed for 2nd' - mockInventoryPersistence.deleteDataNode("/dmi-registry/cm-handles[@id='cmhandle2']") >> { throw new RuntimeException("Failed") } + and: 'delete fails for batch. Retry only fails for and cm handle 2' + mockInventoryPersistence.deleteDataNodes(_) >> { throw new RuntimeException("Batch Failed") } + >> { /* cm handle 1 is OK */ } + >> { throw new RuntimeException("Cm handle 2 Failed")} + >> { /* cm handle 3 is OK */ } when: 'registration is updated to delete cmhandles' def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration) then: 'the cmHandle states are all updated to "DELETING"' @@ -342,7 +356,7 @@ class CmHandleRegistrationServiceSpec extends Specification { with(response.removedCmHandles[1]) { assert it.status == Status.FAILURE assert it.ncmpResponseStatus == UNKNOWN_ERROR - assert it.errorText == 'Failed' + assert it.errorText == 'Cm handle 2 Failed' assert it.cmHandle == 'cmhandle2' } and: 'the cmHandle state is updated to DELETED for 1st and 3rd' @@ -350,40 +364,11 @@ class CmHandleRegistrationServiceSpec extends Specification { assert it.size() == 2 assert it.every { entry -> entry.value == CmHandleState.DELETED } }) - and: 'No cm handles state updates for "upgraded cm handles"' - 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch([:]) - } - - def 'Remove CmHandle Error Handling: Schema Set Deletion failed'() { - given: 'a registration' - def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', - removedCmHandles: ['cmhandle']) - and: 'schema set batch deletion failed with unknown error' - mockInventoryPersistence.deleteSchemaSetsWithCascade(_) >> { throw new RuntimeException('Failed') } - and: 'schema set single deletion failed with unknown error' - mockInventoryPersistence.deleteSchemaSetWithCascade(_) >> { throw new RuntimeException('Failed') } - when: 'registration is updated to delete cmhandle' - def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration) - then: 'no exception is thrown' - noExceptionThrown() - and: 'cm-handle is not deleted' - 0 * mockInventoryPersistence.deleteDataNodes(_) - and: 'the cmHandle state is not updated to "DELETED"' - 0 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch([yangModelCmHandle: CmHandleState.DELETED]) - and: 'a failure response is received' - assert response.removedCmHandles.size() == 1 - with(response.removedCmHandles[0]) { - assert it.status == Status.FAILURE - assert it.cmHandle == 'cmhandle' - assert it.errorText == 'Failed' - assert it.ncmpResponseStatus == UNKNOWN_ERROR - } } def 'Remove CmHandle Error Handling: #scenario'() { given: 'a registration' - def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', - removedCmHandles: ['cmhandle']) + def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', removedCmHandles: ['cmhandle']) and: 'cm-handle deletion fails on batch' mockInventoryPersistence.deleteDataNodes(_) >> { throw deleteListElementException } and: 'cm-handle deletion fails on individual delete' @@ -407,7 +392,7 @@ class CmHandleRegistrationServiceSpec extends Specification { 'an unexpected exception' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed' } - def 'Set Cm Handle Data Sync Enabled Flag where data sync flag is #scenario'() { + def 'Set Cm Handle Data Sync Enabled Flag where data sync flag is #scenario'() { given: 'an existing cm handle composite state' def compositeState = new CompositeState(cmHandleState: CmHandleState.READY, dataSyncEnabled: initialDataSyncEnabledFlag, dataStores: CompositeState.DataStores.builder() @@ -428,7 +413,7 @@ class CmHandleRegistrationServiceSpec extends Specification { saveCmHandleStateExpectedNumberOfInvocations * mockInventoryPersistence.saveCmHandleState('some-cm-handle-id', compositeState) where: 'the following data sync enabled flag is used' scenario | dataSyncEnabledFlag | initialDataSyncEnabledFlag | initialDataSyncState || expectedDataStoreSyncState | deleteDataNodeExpectedNumberOfInvocation | saveCmHandleStateExpectedNumberOfInvocations - 'enabled' | true | false | DataStoreSyncState.NONE_REQUESTED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 1 + 'enabled' | true | false | DataStoreSyncState.NONE_REQUESTED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 1 'disabled' | false | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 0 | 1 'disabled where sync-state is currently SYNCHRONIZED' | false | true | DataStoreSyncState.SYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 1 | 1 'is set to existing flag state' | true | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 0 @@ -447,6 +432,4 @@ class CmHandleRegistrationServiceSpec extends Specification { 0 * mockInventoryPersistence.saveCmHandleState(_, _) } - - } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy index c1a8589c48..d8d92e99f5 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * Modifications Copyright (C) 2024 TechMahindra Ltd. * ================================================================================ @@ -23,38 +23,36 @@ package org.onap.cps.ncmp.impl.inventory import com.fasterxml.jackson.databind.ObjectMapper +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter import org.onap.cps.api.CpsAnchorService import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService import org.onap.cps.api.exceptions.DataNodeNotFoundException import org.onap.cps.api.exceptions.DataValidationException +import org.onap.cps.api.model.DataNode +import org.onap.cps.api.model.ModuleDefinition +import org.onap.cps.api.model.ModuleReference +import org.onap.cps.api.parameters.FetchDescendantsOption import org.onap.cps.impl.utils.CpsValidator import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException import org.onap.cps.ncmp.api.inventory.models.CompositeState -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.impl.utils.YangDataConverter -import org.onap.cps.api.parameters.CascadeDeleteAllowed -import org.onap.cps.api.parameters.FetchDescendantsOption -import org.onap.cps.api.model.DataNode -import org.onap.cps.api.model.ModuleDefinition -import org.onap.cps.api.model.ModuleReference import org.onap.cps.utils.ContentType import org.onap.cps.utils.JsonObjectMapper import spock.lang.Shared import spock.lang.Specification -import java.time.OffsetDateTime -import java.time.ZoneOffset -import java.time.format.DateTimeFormatter - +import static org.onap.cps.api.parameters.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANTS import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NO_TIMESTAMP -import static org.onap.cps.api.parameters.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS -import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANTS class InventoryPersistenceImplSpec extends Specification { @@ -72,8 +70,7 @@ class InventoryPersistenceImplSpec extends Specification { def mockYangDataConverter = Mock(YangDataConverter) - def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService, - mockCpsValidator, mockCpsAnchorService, mockCmHandleQueries) + def objectUnderTest = new InventoryPersistenceImpl(mockCpsValidator, spiedJsonObjectMapper, mockCpsAnchorService, mockCpsModuleService, mockCpsDataService, mockCmHandleQueries) def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ") .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC)) @@ -294,24 +291,6 @@ class InventoryPersistenceImplSpec extends Specification { 1 * mockCpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,'sample xPath',null) } - def 'Delete schema set with a valid schema set name'() { - when: 'the method to delete schema set is called with valid schema set name' - objectUnderTest.deleteSchemaSetWithCascade('validSchemaSetName') - then: 'the module service to delete schemaSet is invoked once' - 1 * mockCpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'validSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) - and: 'the schema set name is validated' - 1 * mockCpsValidator.validateNameCharacters('validSchemaSetName') - } - - def 'Delete multiple schema sets with valid schema set names'() { - when: 'the method to delete schema sets is called with valid schema set names' - objectUnderTest.deleteSchemaSetsWithCascade(['validSchemaSetName1', 'validSchemaSetName2']) - then: 'the module service to delete schema sets is invoked once' - 1 * mockCpsModuleService.deleteSchemaSetsWithCascade(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['validSchemaSetName1', 'validSchemaSetName2']) - and: 'the schema set names are validated' - 1 * mockCpsValidator.validateNameCharacters(['validSchemaSetName1', 'validSchemaSetName2']) - } - def 'Get data node via xPath'() { when: 'the method to get data nodes is called' objectUnderTest.getDataNode('sample xPath') diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy index c62a87f5c3..eff8082a0d 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy @@ -25,6 +25,7 @@ package org.onap.cps.ncmp.impl.inventory import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.api.model.ConditionProperties +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryApiParameters import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters import org.onap.cps.ncmp.api.inventory.models.CompositeState @@ -33,8 +34,8 @@ import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.impl.NetworkCmProxyInventoryFacadeImpl -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState -import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory +import org.onap.cps.ncmp.api.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.LockReasonCategory import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandleSpec.groovy index 4908379a4e..63ab0a9740 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandleSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandleSpec.groovy @@ -20,10 +20,12 @@ package org.onap.cps.ncmp.impl.inventory.models +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder +import org.onap.cps.ncmp.api.inventory.models.LockReasonCategory import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import spock.lang.Specification import static org.onap.cps.ncmp.impl.models.RequiredDmiService.DATA diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdogSpec.groovy index 2ee5226dc2..ae6cb120a5 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdogSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdogSpec.groovy @@ -23,9 +23,9 @@ package org.onap.cps.ncmp.impl.inventory.sync import com.hazelcast.map.IMap import org.onap.cps.api.CpsDataService import org.onap.cps.ncmp.api.inventory.models.CompositeState -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import org.onap.cps.ncmp.impl.inventory.InventoryPersistence -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import spock.lang.Specification diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy index f116e0e1dd..fdd7e47875 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy @@ -30,8 +30,8 @@ import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder import org.onap.cps.ncmp.impl.data.DmiDataOperations import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.api.parameters.FetchDescendantsOption import org.onap.cps.api.model.DataNode import org.onap.cps.utils.JsonObjectMapper @@ -42,9 +42,9 @@ import org.springframework.http.ResponseEntity import spock.lang.Specification import java.util.stream.Collectors -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE_FAILED +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE_FAILED class ModuleOperationsUtilsSpec extends Specification{ diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy index 44cbe25b43..868609e282 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 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,25 +20,22 @@ package org.onap.cps.ncmp.impl.inventory.sync -import com.hazelcast.collection.ISet import org.onap.cps.api.CpsAnchorService import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService -import org.onap.cps.ncmp.api.exceptions.NcmpException +import org.onap.cps.api.exceptions.AlreadyDefinedException +import org.onap.cps.api.exceptions.DuplicatedYangResourceException +import org.onap.cps.api.model.ModuleReference import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle -import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncService.ModuleDelta -import org.onap.cps.api.parameters.CascadeDeleteAllowed -import org.onap.cps.api.exceptions.SchemaSetNotFoundException -import org.onap.cps.api.model.ModuleReference import org.onap.cps.utils.JsonObjectMapper import spock.lang.Specification import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE class ModuleSyncServiceSpec extends Specification { @@ -48,18 +45,8 @@ class ModuleSyncServiceSpec extends Specification { def mockCmHandleQueries = Mock(CmHandleQueryService) def mockCpsDataService = Mock(CpsDataService) def mockJsonObjectMapper = Mock(JsonObjectMapper) - def mockModuleSetTagsBeingProcessed = Mock(ISet<String>); - def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsDataService, mockCpsAnchorService, mockJsonObjectMapper, mockModuleSetTagsBeingProcessed) - - def expectedDataspaceName = NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME - - def setup() { - // Allow tags for al test except 'duplicate-processing-tag' to be added to processing semaphore - mockModuleSetTagsBeingProcessed.add('new-tag') >> true - mockModuleSetTagsBeingProcessed.add('same-tag') >> true - mockModuleSetTagsBeingProcessed.add('cached-tag') >> true - } + def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsDataService, mockCpsAnchorService, mockJsonObjectMapper) def 'Sync models for a NEW cm handle using module set tags: #scenario.'() { given: 'a cm handle to be synced' @@ -71,26 +58,24 @@ class ModuleSyncServiceSpec extends Specification { mockDmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, identifiedNewModuleReferences) >> newModuleNameContentToMap and: 'the module service identifies #identifiedNewModuleReferences.size() new modules' mockCpsModuleService.identifyNewModuleReferences(moduleReferences) >> identifiedNewModuleReferences - and: 'the service returns a list of module references when queried with the specified attributes' - mockCpsModuleService.getModuleReferencesByAttribute(*_) >> existingModuleReferences when: 'module sync is triggered' objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle) then: 'create schema set from module is invoked with correct parameters' - 1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', newModuleNameContentToMap, moduleReferences) + 1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, expectedSchemaSetName, newModuleNameContentToMap, moduleReferences) and: 'anchor is created with the correct parameters' - 1 * mockCpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', 'ch-1') + 1 * mockCpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, expectedSchemaSetName, 'ch-1') where: 'the following parameters are used' - scenario | identifiedNewModuleReferences | newModuleNameContentToMap | moduleSetTag | existingModuleReferences - 'one new module, new tag' | [new ModuleReference('module1', '1')] | [module1: 'some yang source'] | '' | [] - 'no new module, new tag' | [] | [:] | 'new-tag' | [] - 'same tag' | [] | [:] | 'same-tag' | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] + scenario | identifiedNewModuleReferences | newModuleNameContentToMap | moduleSetTag | existingModuleReferences || expectedSchemaSetName + 'one new module, new tag' | [new ModuleReference('module1', '1')] | [module1: 'some yang source'] | '' | [] || 'ch-1' + 'no new module, new tag' | [] | [:] | 'new-tag' | [] || 'new-tag' + 'same tag' | [] | [:] | 'same-tag' | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] || 'same-tag' } - def 'Attempt Sync models for a cm handle with exception and #scenario module set tag'() { + def 'Attempt Sync models for a cm handle with exception and #scenario module set tag.'() { given: 'a cm handle to be synced' def yangModelCmHandle = createAdvisedCmHandle(moduleSetTag) - and: 'the service returns a list of module references when queried with the specified attributes' - mockCpsModuleService.getModuleReferencesByAttribute(*_) >> [new ModuleReference('module1', '1')] + and: 'dmi returns no new yang resources' + mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:] and: 'exception occurs when trying to store result' def testException = new RuntimeException('test') mockCpsModuleService.createSchemaSetFromModules(*_) >> { throw testException } @@ -99,130 +84,100 @@ class ModuleSyncServiceSpec extends Specification { then: 'the same exception is thrown up' def exceptionThrown = thrown(Exception) assert testException == exceptionThrown - and: 'module set tag is removed from processing semaphores only when needed' - expectedCallsToRemoveTag * mockModuleSetTagsBeingProcessed.remove('new-tag') where: 'following module set tags are used' - scenario | moduleSetTag || expectedCallsToRemoveTag - 'with' | 'new-tag' || 1 - 'without' | ' ' || 0 + scenario | moduleSetTag + 'with' | 'new-tag' + 'without' | '' } - def 'Sync models for a cm handle with previously cached module set tag.'() { + def 'Sync models for a cm handle with already defined exception upon schema set creation.'() { given: 'a cm handle to be synced' - def yangModelCmHandle = createAdvisedCmHandle('cached-tag') - and: 'The module set tag exists in the private cache' - def moduleReferences = [ new ModuleReference('module1','1') ] - def cachedModuleDelta = new ModuleDelta(moduleReferences, [:]) - objectUnderTest.privateModuleSetCache.put('cached-tag', cachedModuleDelta) + def yangModelCmHandle = createAdvisedCmHandle('existing tag') + and: 'dmi returns no new yang resources' + mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:] + and: 'already defined exception occurs when creating schema (existing)' + mockCpsModuleService.createSchemaSetFromModules(*_) >> { throw AlreadyDefinedException.forSchemaSet('', '', null) } when: 'module sync is triggered' objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle) - then: 'create schema set from module is invoked with correct parameters' - 1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', [:], moduleReferences) - and: 'anchor is created with the correct parameters' - 1 * mockCpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', 'ch-1') + then: 'the exception is ignored' + noExceptionThrown() + } + + def 'Sync models for a cm handle with already defined exception upon anchor set creation.'() { + given: 'a cm handle to be synced' + def yangModelCmHandle = createAdvisedCmHandle('existing tag') + and: 'dmi returns no new yang resources' + mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:] + and: 'already defined exception occurs when creating schema (existing)' + mockCpsAnchorService.createAnchor(*_) >> { throw AlreadyDefinedException.forAnchor('', '', null) } + when: 'module sync is triggered' + objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle) + then: 'the exception is ignored' + noExceptionThrown() } - def 'Attempt to sync using a module set tag already being processed by a different instance or thread.'() { + def 'Attempt Sync models for a cm handle with duplicate yang resources exception).'() { given: 'a cm handle to be synced' - def yangModelCmHandle = createAdvisedCmHandle('duplicateTag') - and: 'The module set tag already exists in the processing semaphore set' - mockModuleSetTagsBeingProcessed.add('duplicate-processing-tag') > false + def yangModelCmHandle = createAdvisedCmHandle('existing tag') + and: 'dmi returns no new yang resources' + mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:] + and: 'duplicate yang resource exception occurs when creating schema' + def originalException = new DuplicatedYangResourceException('', '', null) + mockCpsModuleService.createSchemaSetFromModules(*_) >> { throw originalException } when: 'module sync is triggered' objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle) - then: 'a ncmp exception is thrown with the relevant details' - def exceptionThrown = thrown(NcmpException) - assert exceptionThrown.message.contains('duplicateTag') - assert exceptionThrown.details.contains('duplicateTag') - assert exceptionThrown.details.contains('ch-1') + then: 'same exception is thrown up' + def thrownException = thrown(Exception) + assert thrownException == originalException } - def 'Upgrade model for an existing cm handle with Module Set Tag where the modules are #scenario'() { - given: 'a cm handle being upgraded to module set tag: tag-1' + def 'Model upgrade without using Module Set Tags (legacy) where the modules are in database.'() { + given: 'a cm handle being upgraded without using module set tags' def ncmpServiceCmHandle = new NcmpServiceCmHandle() - ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: tag-1').build()) + ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withLockReason(MODULE_UPGRADE, '').build()) def dmiServiceName = 'some service name' ncmpServiceCmHandle.cmHandleId = 'upgraded-ch' - def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'tag-1', '', '') - and: 'some module references' - def moduleReferences = [ new ModuleReference('module1','1') ] + def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'', '', '') and: 'DMI operations returns some module references for upgraded cm handle' + def moduleReferences = [ new ModuleReference('module1','1') ] mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences mockDmiModelOperations.getNewYangResourcesFromDmi(_, []) >> [:] - and: 'none of these module references are new (unknown to the system)' + and: 'none of these module references are new (all already known to the system)' mockCpsModuleService.identifyNewModuleReferences(_) >> [] - and: 'CPS-Core returns list of existing module resources for TBD' - mockCpsModuleService.getYangResourcesModuleReferences(*_) >> [ new ModuleReference('module1','1') ] - and: 'the service returns a list of module references when queried with the specified attributes' - mockCpsModuleService.getModuleReferencesByAttribute(*_) >> existingModuleReferences - and: 'the other cm handle is a state ready' - mockCmHandleQueries.cmHandleHasState('otherId', CmHandleState.READY) >> true when: 'module sync is triggered' objectUnderTest.syncAndUpgradeSchemaSet(yangModelCmHandle) then: 'update schema set from module is invoked for the upgraded cm handle' 1 * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences) - and: 'create schema set from module is not invoked for the upgraded cm handle' - 0 * mockCpsModuleService.createSchemaSetFromModules(*_) and: 'No anchor is created for the upgraded cm handle' 0 * mockCpsAnchorService.createAnchor(*_) - where: 'the following parameters are used' - scenario | existingModuleReferences - 'new' | [] - 'in database' | [new ModuleReference('module1', '1')] } - def 'upgrade model for an existing cm handle'() { + def 'Model upgrade using to existing Module Set Tag'() { given: 'a cm handle that is ready but locked for upgrade' def ncmpServiceCmHandle = new NcmpServiceCmHandle() - ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder() - .withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: targetModuleSetTag').build()) + ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: ' + tagTo).build()) ncmpServiceCmHandle.setCmHandleId('cmHandleId-1') - def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, 'targetModuleSetTag', '', '') + def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, tagFrom, '', '') mockCmHandleQueries.cmHandleHasState('cmHandleId-1', CmHandleState.READY) >> true - and: 'the module service returns some module references' - def moduleReferences = [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] - mockCpsModuleService.getYangResourcesModuleReferences(*_)>> moduleReferences - and: 'the service returns a list of module references when queried with the specified attributes' - mockCpsModuleService.getModuleReferencesByAttribute(*_) >> moduleReferences + and: 'the module tag (schemaset) exists is #schemaExists' + mockCpsModuleService.schemaSetExists(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, tagTo) >> schemaExists + and: 'DMI operations returns some module references for upgraded cm handle' + def moduleReferences = [ new ModuleReference('module1','1') ] + expectedCallsToDmi * mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences + and: 'dmi returns no new yang resources' + mockDmiModelOperations.getNewYangResourcesFromDmi(*_) >> [:] + and: 'none of these module references are new (all already known to the system)' + expectedCallsToModuleService * mockCpsModuleService.identifyNewModuleReferences(_) >> [] when: 'module upgrade is triggered' objectUnderTest.syncAndUpgradeSchemaSet(yangModelCmHandle) - then: 'the upgrade is delegated to the module service (with the correct parameters)' - 1 * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', Collections.emptyMap(), moduleReferences) - } - - def 'Delete Schema Set for CmHandle'() { - when: 'delete schema set if exists is called' - objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id') - then: 'the module service is invoked to delete the correct schema set' - 1 * mockCpsModuleService.deleteSchemaSet(expectedDataspaceName, 'some-cmhandle-id', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) - } - - def 'Delete a non-existing Schema Set for CmHandle' () { - given: 'the DB throws an exception because its Schema Set does not exist' - mockCpsModuleService.deleteSchemaSet(*_) >> { throw new SchemaSetNotFoundException('some-dataspace-name', 'some-cmhandle-id') } - when: 'delete schema set if exists is called' - objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id') - then: 'the exception from the DB is ignored; there are no exceptions' - noExceptionThrown() - } - - def 'Delete Schema Set for CmHandle with other exception' () { - given: 'an exception other than SchemaSetNotFoundException is thrown' - UnsupportedOperationException unsupportedOperationException = new UnsupportedOperationException(); - 1 * mockCpsModuleService.deleteSchemaSet(*_) >> { throw unsupportedOperationException } - when: 'delete schema set if exists is called' - objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id') - then: 'an exception is thrown' - def result = thrown(UnsupportedOperationException) - result == unsupportedOperationException - } - - def 'Clear module set cache.'() { - given: 'something in the module set cache' - objectUnderTest.privateModuleSetCache.put('test',new ModuleDelta([],[:])) - when: 'the cache is cleared' - objectUnderTest.clearPrivateModuleSetCache() - then: 'the cache is empty' - objectUnderTest.privateModuleSetCache.isEmpty() + then: 'the upgrade is delegated to the anchor service (with the correct parameters) except when new tag is blank' + expectedCallsToAnchorService * mockCpsAnchorService.updateAnchorSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', tagTo) + where: 'with or without from tag' + scenario | schemaExists | tagFrom | tagTo || expectedCallsToDmi | expectedCallsToModuleService | expectedCallsToAnchorService + 'from no tag to existing tag' | true | '' | 'tagTo'|| 0 | 0 | 1 + 'from tag to other existing tag' | true | 'oldTag' | 'tagTo'|| 0 | 0 | 1 + 'to new tag' | false | 'oldTag' | 'tagTo'|| 1 | 1 | 1 + 'to NO tag' | true | 'oldTag' | '' || 1 | 1 | 0 } def createAdvisedCmHandle(moduleSetTag) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy index c7fe45db90..92f4b38f31 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,20 +29,21 @@ import com.hazelcast.config.Config import com.hazelcast.core.Hazelcast import com.hazelcast.instance.impl.HazelcastInstanceFactory import com.hazelcast.map.IMap +import org.onap.cps.api.exceptions.DataNodeNotFoundException +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder import org.onap.cps.ncmp.impl.inventory.InventoryPersistence -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler -import org.onap.cps.api.exceptions.DataNodeNotFoundException import org.slf4j.LoggerFactory import spock.lang.Specification + import java.util.concurrent.atomic.AtomicInteger -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE_FAILED +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_UPGRADE_FAILED class ModuleSyncTasksSpec extends Specification { @@ -87,10 +88,7 @@ class ModuleSyncTasksSpec extends Specification { mockInventoryPersistence.getYangModelCmHandle('cm-handle-2') >> cmHandle2 when: 'module sync poll is executed' objectUnderTest.performModuleSync(['cm-handle-1', 'cm-handle-2'], batchCount) - then: 'module sync service deletes schemas set of each cm handle if it already exists' - 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-1') - 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-2') - and: 'module sync service is invoked for each cm handle' + then: 'module sync service is invoked for each cm handle' 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assert args[0].id == 'cm-handle-1' } 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assert args[0].id == 'cm-handle-2' } and: 'the state handler is called for the both cm handles' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy index 3213e5d442..7db9e5a870 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================== - * Copyright (C) 2022-2024 Nordix Foundation + * Copyright (C) 2022-2025 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,6 @@ package org.onap.cps.ncmp.impl.inventory.sync -import com.hazelcast.collection.ISet import com.hazelcast.config.Config import com.hazelcast.core.Hazelcast import com.hazelcast.map.IMap @@ -45,9 +44,6 @@ class SynchronizationCacheConfigSpec extends Specification { @Autowired IMap<String, Boolean> dataSyncSemaphores - @Autowired - ISet<String> moduleSetTagsBeingProcessed - def cleanupSpec() { Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').shutdown() } @@ -59,8 +55,6 @@ class SynchronizationCacheConfigSpec extends Specification { assert null != moduleSyncStartedOnCmHandles and: 'system is able to create an instance of a map to hold data sync semaphores' assert null != dataSyncSemaphores - and: 'system is able to create an instance of a set to hold module set tags being processed' - assert null != moduleSetTagsBeingProcessed and: 'there is only one instance with the correct name' assert Hazelcast.allHazelcastInstances.size() == 1 assert Hazelcast.allHazelcastInstances.name[0] == 'cps-and-ncmp-hazelcast-instance-test-config' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy index 2833ca838f..4d7c22a200 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy @@ -20,22 +20,25 @@ package org.onap.cps.ncmp.impl.inventory.sync.lcm -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY import com.hazelcast.core.Hazelcast import com.hazelcast.map.IMap import org.onap.cps.ncmp.api.inventory.models.CompositeState +import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.impl.inventory.sync.lcm.CmHandleStateMonitor.DecreasingEntryProcessor import org.onap.cps.ncmp.impl.inventory.sync.lcm.CmHandleStateMonitor.IncreasingEntryProcessor +import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent import spock.lang.Shared import spock.lang.Specification; class CmHandleStateMonitorSpec extends Specification { - def cmHandlesByState = Mock(IMap) - def objectUnderTest = new CmHandleStateMonitor(cmHandlesByState) + def mockCmHandlesByState = Mock(IMap) + def mockCmHandleQueryService = Mock(CmHandleQueryService) + def objectUnderTest = new CmHandleStateMonitor(mockCmHandleQueryService, mockCmHandlesByState) @Shared def entryProcessingMap = Hazelcast.newHazelcastInstance().getMap('entryProcessingMap') @@ -49,6 +52,25 @@ class CmHandleStateMonitorSpec extends Specification { Hazelcast.shutdownAll() } + def 'Initialise cm handle state monitor: #scenario'() { + given: 'the query service returns a list of cm-handle ids for the given state' + mockCmHandleQueryService.queryCmHandleIdsByState(_) >> queryResult + and: 'a mocked NcmpModelOnboardingFinishedEvent is triggered' + def mockNcmpModelOnboardingFinishedEvent = Mock(NcmpInventoryModelOnboardingFinishedEvent) + when: 'the method to initialise cm handle state monitor is triggered by onboarding event' + objectUnderTest.initialiseCmHandleStateMonitor(mockNcmpModelOnboardingFinishedEvent) + then: 'metrics map is called correct number of times for each state except DELETED, with expected value' + 1 * mockCmHandlesByState.putIfAbsent("advisedCmHandlesCount", expectedValue) + 1 * mockCmHandlesByState.putIfAbsent("readyCmHandlesCount", expectedValue) + 1 * mockCmHandlesByState.putIfAbsent("lockedCmHandlesCount", expectedValue) + 1 * mockCmHandlesByState.putIfAbsent("deletingCmHandlesCount", expectedValue) + where: + scenario | queryResult || expectedValue + 'query service returns zero cm handle id'| [] || 0 + 'query service returns 1 cm handle id' | ['someId'] || 1 + } + + def 'Update cm handle state metric'() { given: 'a collection of cm handle state pair' def cmHandleTransitionPair = new LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair() @@ -57,19 +79,19 @@ class CmHandleStateMonitorSpec extends Specification { when: 'method to update cm handle state metrics is called' objectUnderTest.updateCmHandleStateMetrics([cmHandleTransitionPair]) then: 'cm handle by state cache map is called once for current and target state for entry processing' - 1 * cmHandlesByState.executeOnKey('advisedCmHandlesCount', _) - 1 * cmHandlesByState.executeOnKey('readyCmHandlesCount', _) + 1 * mockCmHandlesByState.executeOnKey('advisedCmHandlesCount', _) + 1 * mockCmHandlesByState.executeOnKey('readyCmHandlesCount', _) } - def 'Updating cm handle state metric with no previous state'() { + def 'Update cm handle state metric with no previous state'() { given: 'a collection of cm handle state pair wherein current state is null' def cmHandleTransitionPair = new LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair() cmHandleTransitionPair.currentYangModelCmHandle = new YangModelCmHandle(compositeState: null) cmHandleTransitionPair.targetYangModelCmHandle = new YangModelCmHandle(compositeState: new CompositeState(cmHandleState: ADVISED)) - when: 'method to update cm handle state metrics is called' + when: 'updating cm handle state metrics' objectUnderTest.updateCmHandleStateMetrics([cmHandleTransitionPair]) then: 'cm handle by state cache map is called only once' - 1 * cmHandlesByState.executeOnKey(_, _) + 1 * mockCmHandlesByState.executeOnKey(_, _) } def 'Applying decreasing entry processor to a key on map where #scenario'() { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy index 5e614a6f88..62db2e34ad 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy @@ -25,7 +25,7 @@ import ch.qos.logback.classic.Logger import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.read.ListAppender import org.onap.cps.ncmp.api.inventory.models.CompositeState -import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState import org.onap.cps.ncmp.impl.inventory.InventoryPersistence import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.slf4j.LoggerFactory @@ -33,12 +33,12 @@ import spock.lang.Specification import static java.util.Collections.EMPTY_LIST import static java.util.Collections.EMPTY_MAP -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETING -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.LOCKED -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY -import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.DELETED +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.DELETING +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.LOCKED +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY +import static org.onap.cps.ncmp.api.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED class LcmEventsCmHandleStateHandlerImplSpec extends Specification { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorSpec.groovy index e0a552ea99..c63e3d9c8e 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreatorSpec.groovy @@ -24,12 +24,12 @@ import org.mapstruct.factory.Mappers import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle import org.onap.cps.ncmp.events.lcm.v1.Values -import org.onap.cps.ncmp.impl.inventory.models.CmHandleState +import org.onap.cps.ncmp.api.inventory.models.CmHandleState import spock.lang.Specification -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETING -import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.DELETING +import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY class LcmEventsCreatorSpec extends Specification { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy index ffd1d89fe1..dc6ec4120b 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy @@ -30,6 +30,7 @@ import org.onap.cps.api.CpsModuleService import org.onap.cps.api.model.Dataspace import org.slf4j.LoggerFactory import org.springframework.boot.context.event.ApplicationStartedEvent +import org.springframework.context.ApplicationEventPublisher import org.springframework.context.annotation.AnnotationConfigApplicationContext import spock.lang.Specification @@ -42,7 +43,8 @@ class InventoryModelLoaderSpec extends Specification { def mockCpsModuleService = Mock(CpsModuleService) def mockCpsDataService = Mock(CpsDataService) def mockCpsAnchorService = Mock(CpsAnchorService) - def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsAnchorService, mockCpsDataService) + def mockApplicationEventPublisher = Mock(ApplicationEventPublisher) + def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsAnchorService, mockCpsDataService, mockApplicationEventPublisher) def applicationContext = new AnnotationConfigApplicationContext() @@ -75,6 +77,8 @@ class InventoryModelLoaderSpec extends Specification { 1 * mockCpsAnchorService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2024-02-23') and: 'No schema sets are being removed by the module service (yet)' 0 * mockCpsModuleService.deleteSchemaSet(NCMP_DATASPACE_NAME, _, _) + and: 'application event publisher is called once' + 1 * mockApplicationEventPublisher.publishEvent(_) } } |