From: Joseph Keenan Date: Tue, 2 Aug 2022 12:59:07 +0000 (+0000) Subject: Merge "Enable/Disable Data Sync for Cm Handle" X-Git-Tag: 3.1.0~54 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=7dfc3a01f327654d64451865ac05b819c5583b27;hp=e79e48d75c0a84e7f1b3cef53d29ac89321184ea;p=cps.git Merge "Enable/Disable Data Sync for Cm Handle" --- diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml index dd83795f7..6bbe80bfb 100644 --- a/cps-application/src/main/resources/application.yml +++ b/cps-application/src/main/resources/application.yml @@ -164,8 +164,4 @@ timers: locked-modules-sync: sleep-time-ms: 300000 cm-handle-data-sync: - sleep-time-ms: 30000 - -data-sync: - cache: - enabled: false \ No newline at end of file + sleep-time-ms: 30000 \ No newline at end of file diff --git a/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java b/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java index d8e48be07..67af6f10a 100644 --- a/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java +++ b/cps-ncmp-rest-stub/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada + * Modifications Copyright (c) 2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,6 +86,12 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi { return ResponseEntity.ok(restOutputCmHandles); } + @Override + public ResponseEntity setDataSyncEnabledFlagForCmHandle(final String cmHandleId, + final Boolean dataSyncEnabled) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + @Override public ResponseEntity> searchCmHandleIds( final CmHandleQueryParameters cmHandleQueryParameters) { diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index 14fd4d24d..c1e05876c 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -423,6 +423,14 @@ components: schema: type: string example: my-cm-handle + dataSyncEnabled: + name: dataSyncEnabled + in: query + description: Is used to enable or disable the data synchronization flag + required: true + schema: + type: boolean + example: true xpathInQuery: name: xpath in: query diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml index d7b383705..f394e8575 100755 --- a/cps-ncmp-rest/docs/openapi/ncmp.yml +++ b/cps-ncmp-rest/docs/openapi/ncmp.yml @@ -430,4 +430,28 @@ searchCmHandleIds: 404: $ref: 'components.yaml#/components/responses/NotFound' 500: - $ref: 'components.yaml#/components/responses/InternalServerError' \ No newline at end of file + $ref: 'components.yaml#/components/responses/InternalServerError' + +setDataSyncEnabledFlag: + put: + tags: + - network-cm-proxy + summary: Set the Data Sync Enabled Flag + description: Set the data sync enabled flag to true or false for a specified Cm-Handle. This will in turn set the data sync state to UNSYNCHRONIZED and NONE_REQUESTED respectfully. + operationId: setDataSyncEnabledFlagForCmHandle + parameters: + - $ref: 'components.yaml#/components/parameters/cmHandleInPath' + - $ref: 'components.yaml#/components/parameters/dataSyncEnabled' + responses: + 200: + $ref: 'components.yaml#/components/responses/Ok' + 400: + $ref: 'components.yaml#/components/responses/BadRequest' + 401: + $ref: 'components.yaml#/components/responses/Unauthorized' + 403: + $ref: 'components.yaml#/components/responses/Forbidden' + 500: + $ref: 'components.yaml#/components/responses/InternalServerError' + 502: + $ref: 'components.yaml#/components/responses/BadGateway' \ No newline at end of file diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml index 35be59a38..8e020668a 100755 --- a/cps-ncmp-rest/docs/openapi/openapi.yml +++ b/cps-ncmp-rest/docs/openapi/openapi.yml @@ -52,3 +52,6 @@ paths: /v1/ch/{cm-handle}/state: $ref: 'ncmp.yml#/getCmHandleStateById' + + /v1/ch/{cm-handle}/data-sync: + $ref: 'ncmp.yml#/setDataSyncEnabledFlag' diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java index b20487119..d2ed39379 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java @@ -320,6 +320,20 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { return new ResponseEntity<>(restModuleReferences, HttpStatus.OK); } + /** + * Set the data sync enabled flag, along with the data sync state for the specified cm handle. + * + * @param cmHandleId cm handle id + * @param dataSyncEnabledFlag data sync enabled flag + * @return response entity ok if request is successful + */ + @Override + public ResponseEntity setDataSyncEnabledFlagForCmHandle(final String cmHandleId, + final Boolean dataSyncEnabledFlag) { + networkCmProxyDataService.setDataSyncEnabled(cmHandleId, dataSyncEnabledFlag); + return new ResponseEntity<>(HttpStatus.OK); + } + private RestOutputCmHandle toRestOutputCmHandle(final NcmpServiceCmHandle ncmpServiceCmHandle) { final RestOutputCmHandle restOutputCmHandle = new RestOutputCmHandle(); final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties(); diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy index 06a7759be..d568a5a92 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy @@ -423,6 +423,20 @@ class NetworkCmProxyControllerSpec extends Specification { response.status == HttpStatus.OK.value() } + def 'Set the data sync enabled based on the cm handle id and the data sync flag is #scenario' () { + when: 'the set data sync enabled request is invoked' + def response = mvc.perform(put("$ncmpBasePathV1/ch/some-cm-handle-id/data-sync?dataSyncEnabled=" + dataSyncEnabledFlag)) + .andReturn().response + then: 'method to set data sync enabled is called' + 1 * mockNetworkCmProxyDataService.setDataSyncEnabled('some-cm-handle-id', dataSyncEnabledFlag) + and: 'the response returns an OK http code' + response.status == HttpStatus.OK.value() + where: 'the following parameters are used' + scenario | dataSyncEnabledFlag + 'enabled' | true + 'disabled' | false + } + def dataStores() { DataStores.builder() .operationalDataStore(Operational.builder() diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java index ea27d4a1e..3295a6e2b 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java @@ -154,4 +154,12 @@ public interface NetworkCmProxyDataService { * @return collection of cm handle ids */ Set executeCmHandleIdSearch(CmHandleQueryApiParameters cmHandleQueryApiParameters); + + /** + * Set the data sync enabled flag, along with the data sync state to true or false based on the cm handle id. + * + * @param cmHandleId cm handle id + * @param dataSyncEnabled data sync enabled flag + */ + void setDataSyncEnabled(String cmHandleId, boolean dataSyncEnabled); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index 28cbf2cc2..8462d687b 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -26,6 +26,7 @@ package org.onap.cps.ncmp.api.impl; import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum; import static org.onap.cps.utils.CmHandleQueryRestParametersValidator.validateCmHandleQueryParameters; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -35,6 +36,7 @@ import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.api.CpsDataService; import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsCmHandleStateHandler; @@ -44,6 +46,8 @@ import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.inventory.CmHandleState; import org.onap.cps.ncmp.api.inventory.CompositeState; +import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters; import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse; @@ -52,6 +56,7 @@ import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.cps.spi.exceptions.AlreadyDefinedException; +import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; import org.onap.cps.spi.model.CmHandleQueryServiceParameters; @@ -79,6 +84,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; + private final CpsDataService cpsDataService; + @Override public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( final DmiPluginRegistration dmiPluginRegistration) { @@ -181,6 +188,36 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService return networkCmProxyCmHandlerQueryService.queryCmHandleIds(cmHandleQueryServiceParameters); } + /** + * Set the data sync enabled flag, along with the data sync state + * based on the data sync enabled boolean for the cm handle id provided. + * + * @param cmHandleId cm handle id + * @param dataSyncEnabled data sync enabled flag + */ + @Override + public void setDataSyncEnabled(final String cmHandleId, final boolean dataSyncEnabled) { + CpsValidator.validateNameCharacters(cmHandleId); + final CompositeState compositeState = inventoryPersistence + .getCmHandleState(cmHandleId); + if (compositeState.getDataSyncEnabled().equals(dataSyncEnabled)) { + log.info("Data-Sync Enabled flag is already: {} ", dataSyncEnabled); + } else if (compositeState.getCmHandleState() != CmHandleState.READY) { + throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. Cm handle state is: " + + compositeState.getCmHandleState()); + } else { + final DataStoreSyncState dataStoreSyncState = compositeState.getDataStores() + .getOperationalDataStore().getDataStoreSyncState(); + if (!dataSyncEnabled && dataStoreSyncState == DataStoreSyncState.SYNCHRONIZED) { + cpsDataService.deleteDataNode("NFP-Operational", cmHandleId, + "/netconf-state", OffsetDateTime.now()); + } + CompositeStateUtils.setDataSyncEnabledFlagWithDataSyncState(dataSyncEnabled, compositeState); + inventoryPersistence.saveCmHandleState(cmHandleId, + compositeState); + } + } + /** * Retrieve cm handle details for a given cm handle. * diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java index bd47bea73..9027a6eb0 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java @@ -34,7 +34,6 @@ import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; import org.onap.ncmp.cmhandle.event.lcm.LcmEvent; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Slf4j @@ -46,14 +45,10 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState private final LcmEventsCreator lcmEventsCreator; private final LcmEventsService lcmEventsService; - @Value("${data-sync.cache.enabled:false}") - private boolean isGlobalDataSyncCacheEnabled; - @Override public void updateCmHandleState(final YangModelCmHandle yangModelCmHandle, final CmHandleState targetCmHandleState) { - if (yangModelCmHandle.getCompositeState().getCmHandleState() == targetCmHandleState) { log.debug("CmHandle with id : {} already in state : {}", yangModelCmHandle.getId(), targetCmHandleState); } else { @@ -67,7 +62,7 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState final CmHandleState targetCmHandleState) { if (READY == targetCmHandleState) { - CompositeStateUtils.setCompositeStateToReadyWithInitialDataStoreSyncState(isGlobalDataSyncCacheEnabled) + CompositeStateUtils.setCompositeStateToReadyWithInitialDataStoreSyncState() .accept(yangModelCmHandle.getCompositeState()); inventoryPersistence.saveCmHandleState(yangModelCmHandle.getId(), yangModelCmHandle.getCompositeState()); } else if (ADVISED == targetCmHandleState) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java index a0fc0c3a9..d6a33302d 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateBuilder.java @@ -32,6 +32,7 @@ public class CompositeStateBuilder { private LockReason lockReason; private DataStores datastores; private String lastUpdatedTime; + private Boolean dataSyncEnabled; /** * To create the {@link CompositeState}. @@ -44,6 +45,7 @@ public class CompositeStateBuilder { compositeState.setLockReason(lockReason); compositeState.setDataStores(datastores); compositeState.setLastUpdateTime(lastUpdatedTime); + compositeState.setDataSyncEnabled(dataSyncEnabled); return compositeState; } @@ -115,6 +117,9 @@ public class CompositeStateBuilder { this.cmHandleState = CmHandleState.valueOf((String) dataNode.getLeaves() .get("cm-handle-state")); this.lastUpdatedTime = (String) dataNode.getLeaves().get("last-update-time"); + if (this.cmHandleState == CmHandleState.READY) { + this.dataSyncEnabled = (Boolean) dataNode.getLeaves().get("data-sync-enabled"); + } for (final DataNode stateChildNode : dataNode.getChildDataNodes()) { if (stateChildNode.getXpath().endsWith("/lock-reason")) { this.lockReason = getLockReason(stateChildNode); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java index 506bd1162..54ca68a0e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/CompositeStateUtils.java @@ -49,10 +49,9 @@ public class CompositeStateUtils { * * @return Updated CompositeState */ - public static Consumer setCompositeStateToReadyWithInitialDataStoreSyncState( - final boolean isGlobalDataSyncCacheEnabled) { + public static Consumer setCompositeStateToReadyWithInitialDataStoreSyncState() { return compositeState -> { - compositeState.setDataSyncEnabled(isGlobalDataSyncCacheEnabled); + compositeState.setDataSyncEnabled(false); compositeState.setCmHandleState(CmHandleState.READY); final CompositeState.Operational operational = getInitialDataStoreSyncState(compositeState.getDataSyncEnabled()); @@ -62,6 +61,27 @@ public class CompositeStateUtils { }; } + /** + * Set the data sync enabled flag, along with the data store sync state based on this flag. + * + * @param dataSyncEnabled data sync enabled flag + * @param compositeState cm handle composite state + */ + public static void setDataSyncEnabledFlagWithDataSyncState(final boolean dataSyncEnabled, + final CompositeState compositeState) { + compositeState.setDataSyncEnabled(dataSyncEnabled); + final CompositeState.Operational operational = getInitialDataStoreSyncState(dataSyncEnabled); + final CompositeState.DataStores dataStores = + CompositeState.DataStores.builder().operationalDataStore(operational).build(); + compositeState.setDataStores(dataStores); + } + + /** + * Get initial data sync state based on data sync enabled boolean flag. + * + * @param dataSyncEnabled data sync enabled boolean flag + * @return the data store sync state + */ private static CompositeState.Operational getInitialDataStoreSyncState(final boolean dataSyncEnabled) { final DataStoreSyncState dataStoreSyncState = dataSyncEnabled ? DataStoreSyncState.UNSYNCHRONIZED : DataStoreSyncState.NONE_REQUESTED; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java index adfa33ad8..395fb01f4 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java @@ -58,6 +58,9 @@ public class DataSyncWatchdog { final String resourceData = syncUtils.getResourceData(cmHandleId); if (resourceData == null) { log.debug("Error accessing the node for Cm-Handle: {}", cmHandleId); + } else if (unSynchronizedReadyCmHandle.getCompositeState().getDataSyncEnabled().equals(false)) { + log.debug("Error: data sync enabled for {} must be true." + + "Data sync enabled is currently set to false", cmHandleId); } else { cpsDataService.saveData("NFP-Operational", cmHandleId, resourceData, OffsetDateTime.now()); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java index c71f68f77..37bd1ed0f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java @@ -32,7 +32,6 @@ import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.inventory.LockReasonCategory; -import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -47,9 +46,6 @@ public class ModuleSyncWatchdog { private final ModuleSyncService moduleSyncService; - @Value("${data-sync.cache.enabled:false}") - private boolean isGlobalDataSyncCacheEnabled; - private final ConcurrentMap moduleSyncSemaphoreMap; /** @@ -107,9 +103,9 @@ public class ModuleSyncWatchdog { private Consumer setCompositeStateToReadyWithInitialDataStoreSyncState() { return compositeState -> { - compositeState.setDataSyncEnabled(isGlobalDataSyncCacheEnabled); + compositeState.setDataSyncEnabled(false); compositeState.setCmHandleState(CmHandleState.READY); - final CompositeState.Operational operational = getDataStoreSyncState(compositeState.getDataSyncEnabled()); + final CompositeState.Operational operational = getDataStoreSyncState(); final CompositeState.DataStores dataStores = CompositeState.DataStores.builder() .operationalDataStore(operational) .build(); @@ -126,9 +122,8 @@ public class ModuleSyncWatchdog { compositeState.setLockReason(lockReason); } - private CompositeState.Operational getDataStoreSyncState(final boolean dataSyncEnabled) { - final DataStoreSyncState dataStoreSyncState = dataSyncEnabled - ? DataStoreSyncState.UNSYNCHRONIZED : DataStoreSyncState.NONE_REQUESTED; + private CompositeState.Operational getDataStoreSyncState() { + final DataStoreSyncState dataStoreSyncState = DataStoreSyncState.NONE_REQUESTED; return CompositeState.Operational.builder().dataStoreSyncState(dataStoreSyncState).build(); } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index 1ee1ad2f6..2aa08b8e7 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -22,6 +22,7 @@ package org.onap.cps.ncmp.api.impl import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsCmHandleStateHandler @@ -60,6 +61,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def mockInventoryPersistence = Mock(InventoryPersistence) def stubbedNetworkCmProxyCmHandlerQueryService = Stub(NetworkCmProxyCmHandlerQueryService) def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler) + def mockCpsDataService = Mock(CpsDataService) def objectUnderTest = getObjectUnderTest() def 'DMI Registration: Create, Update & Delete operations are processed in the right order'() { @@ -351,6 +353,6 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def getObjectUnderTest() { return Spy(new NetworkCmProxyDataServiceImpl(spiedJsonObjectMapper, mockDmiDataOperations, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, stubbedNetworkCmProxyCmHandlerQueryService, - mockLcmEventsCmHandleStateHandler)) + mockLcmEventsCmHandleStateHandler, mockCpsDataService)) } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index d11255767..a372defc6 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -34,6 +34,7 @@ import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters import org.onap.cps.ncmp.api.models.ConditionApiProperties import org.onap.cps.ncmp.api.models.DmiPluginRegistration import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle +import org.onap.cps.spi.exceptions.CpsException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.model.CmHandleQueryServiceParameters import spock.lang.Shared @@ -79,7 +80,8 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCpsCmHandlerQueryService, - mockLcmEventsCmHandleStateHandler) + mockLcmEventsCmHandleStateHandler, + mockCpsDataService) def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']" @@ -311,14 +313,6 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleId('some-cm-handle') } - - def dataStores() { - CompositeState.DataStores.builder() - .operationalDataStore(CompositeState.Operational.builder() - .dataStoreSyncState(DataStoreSyncState.NONE_REQUESTED) - .lastSyncTime('some-timestamp').build()).build() - } - def 'Execute cm handle search'() { given: 'valid CmHandleQueryApiParameters input' def cmHandleQueryApiParameters = new CmHandleQueryApiParameters() @@ -335,4 +329,51 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { then: 'result is the same collection as returned by the CPS Data Service' assert result.stream().map(d -> d.cmHandleId).collect(Collectors.toSet()) == ['cm-handle-id-1'] as Set } + + 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() + .operationalDataStore(CompositeState.Operational.builder() + .dataStoreSyncState(initialDataSyncState) + .build()).build()) + and: 'get cm handle state returns the composite state for the given cm handle id' + mockInventoryPersistence.getCmHandleState('some-cm-handle-id') >> compositeState + when: 'set data sync enabled is called with the data sync enabled flag set to #dataSyncEnabledFlag' + objectUnderTest.setDataSyncEnabled('some-cm-handle-id', dataSyncEnabledFlag) + then: 'the data sync enabled flag is set to #dataSyncEnabled' + compositeState.dataSyncEnabled == dataSyncEnabledFlag + and: 'the data store sync state is set to #expectedDataStoreSyncState' + compositeState.dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState + and: 'the cps data service to delete data nodes is invoked the expected number of times' + deleteDataNodeExpectedNumberOfInvocation * mockCpsDataService.deleteDataNode('NFP-Operational', 'some-cm-handle-id', '/netconf-state', _) + and: 'the inventory persistence service to update node leaves is called with the correct values' + 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 + '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 + } + + def 'Set cm Handle Data Sync Enabled flag with following cm handle not in ready state exception' () { + given: 'a cm handle composite state' + def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, dataSyncEnabled: false) + and: 'get cm handle state returns the composite state for the given cm handle id' + mockInventoryPersistence.getCmHandleState('some-cm-handle-id') >> compositeState + when: 'set data sync enabled is called with the data sync enabled flag set to true' + objectUnderTest.setDataSyncEnabled('some-cm-handle-id', true) + then: 'the expected exception is thrown' + thrown(CpsException) + and: 'the inventory persistence service to update node leaves is not invoked' + 0 * mockInventoryPersistence.saveCmHandleState(_, _) + } + + def dataStores() { + CompositeState.DataStores.builder() + .operationalDataStore(CompositeState.Operational.builder() + .dataStoreSyncState(DataStoreSyncState.NONE_REQUESTED) + .lastSyncTime('some-timestamp').build()).build() + } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy index b4e57c78b..b3436792d 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy @@ -94,29 +94,25 @@ class LcmEventsCmHandleStateHandlerImplSpec extends Specification { 1 * mockLcmEventsService.publishLcmEvent(cmHandleId, _) } - def 'Update and Publish Events on State Change to READY with #scenario'() { + def 'Update and Publish Events on State Change to READY'() { given: 'Cm Handle represented as YangModelCmHandle' compositeState = new CompositeState(cmHandleState: ADVISED) yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) and: 'global sync flag is set' - objectUnderTest.isGlobalDataSyncCacheEnabled = dataSyncCacheEnabled + compositeState.setDataSyncEnabled(false) when: 'update cmhandle state is invoked' objectUnderTest.updateCmHandleState(yangModelCmHandle, READY) then: 'state is saved using inventory persistence with expected dataSyncState' 1 * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) >> { args-> { def result = (args[1] as CompositeState) - assert result.dataSyncEnabled == dataSyncCacheEnabled - assert result.dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState + assert result.dataSyncEnabled == false + assert result.dataStores.operationalDataStore.dataStoreSyncState == DataStoreSyncState.NONE_REQUESTED } } and: 'event service is called to publish event' 1 * mockLcmEventsService.publishLcmEvent(cmHandleId, _) - where: - scenario | dataSyncCacheEnabled || expectedDataStoreSyncState - 'data sync cache enabled' | true || DataStoreSyncState.UNSYNCHRONIZED - 'data sync cache is not enabled' | false || DataStoreSyncState.NONE_REQUESTED } def 'Update cmHandle state to "DELETING"' (){ diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy index f2cd2b51f..c7e6b6d35 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsPublisherSpec.groovy @@ -22,7 +22,6 @@ package org.onap.cps.ncmp.api.impl.event.lcm import com.fasterxml.jackson.databind.ObjectMapper import org.apache.kafka.clients.consumer.KafkaConsumer -import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsPublisher import org.onap.cps.ncmp.api.utils.MessagingSpec import org.onap.cps.ncmp.utils.TestUtils import org.onap.cps.utils.JsonObjectMapper diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncSpec.groovy index 20880ca3b..650a779a4 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncSpec.groovy @@ -26,6 +26,7 @@ import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState import org.onap.cps.ncmp.api.inventory.InventoryPersistence import org.onap.cps.ncmp.api.inventory.DataStoreSyncState +import spock.lang.Shared import spock.lang.Specification class DataSyncSpec extends Specification { @@ -36,6 +37,7 @@ class DataSyncSpec extends Specification { def mockSyncUtils = Mock(SyncUtils) + @Shared def jsonString = '{"stores:bookstore":{"categories":[{"code":"01"}]}}' def objectUnderTest = new DataSyncWatchdog(mockInventoryPersistence, mockCpsDataService, mockSyncUtils) @@ -48,7 +50,7 @@ class DataSyncSpec extends Specification { def 'Schedule Data Sync for Cm Handle State in READY and Operational Sync State in UNSYNCHRONIZED'() { given: 'sample resource data' - def resourceData = jsonString; + def resourceData = jsonString and: 'sync utilities return a cm handle twice' mockSyncUtils.getAnUnSynchronizedReadyCmHandle() >>> [yangModelCmHandle1, yangModelCmHandle2, null] when: 'data sync poll is executed' @@ -71,18 +73,24 @@ class DataSyncSpec extends Specification { 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle-2', compositeState) } - def 'Schedule Data Sync for Cm Handle State in READY and Operational Sync State in UNSYNCHRONIZED which return empty data from Node'() { - given: 'cm handles in an ready state and operational sync state in unsynchronized' - and: 'sync utilities return a cm handle twice' - mockSyncUtils.getAnUnSynchronizedReadyCmHandle() >>> [yangModelCmHandle1, null] + def 'Schedule Data Sync for Cm Handle State in READY and Operational Sync State in UNSYNCHRONIZED which return empty data from Node because #scenario'() { + given: 'a yang model cm handle' + def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', compositeState: new CompositeState(dataSyncEnabled: dataSyncEnabled)) + and: 'sync utilities returns a single cm handle' + mockSyncUtils.getAnUnSynchronizedReadyCmHandle() >>> [yangModelCmHandle, null] when: 'data sync poll is executed' objectUnderTest.executeUnSynchronizedReadyCmHandlePoll() then: 'the inventory persistence cm handle returns a composite state for the first cm handle' - 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle-1') >> compositeState + 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle') >> compositeState and: 'the sync util returns first resource data' - 1 * mockSyncUtils.getResourceData('some-cm-handle-1') >> null + 1 * mockSyncUtils.getResourceData('some-cm-handle') >> resourceData and: 'the cm-handle data is not saved' 0 * mockCpsDataService.saveData('NFP-Operational', 'some-cm-handle-1', jsonString, _) + where: + scenario | dataSyncEnabled | resourceData + 'data sync is not enabled' | false | jsonString + 'resource data is null' | true | null + 'data sync is not enabled and resource data is null' | false | null } def createSampleYangModelCmHandle(cmHandleId) { @@ -92,7 +100,7 @@ class DataSyncSpec extends Specification { def getCompositeState() { def cmHandleState = CmHandleState.READY - def compositeState = new CompositeState(cmHandleState: cmHandleState) + def compositeState = new CompositeState(cmHandleState: cmHandleState, dataSyncEnabled: true) compositeState.setDataStores(CompositeState.DataStores.builder() .operationalDataStore(CompositeState.Operational.builder().dataStoreSyncState(DataStoreSyncState.SYNCHRONIZED) .build()).build()) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy index 7455438cc..41f2160bc 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy @@ -47,13 +47,12 @@ class ModuleSyncWatchdogSpec extends Specification { def objectUnderTest = new ModuleSyncWatchdog(mockInventoryPersistence, mockSyncUtils, mockModuleSyncService, stubbedMap as ConcurrentHashMap) - def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handles where #scenario'() { + def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handles'() { given: 'cm handles in an advised state and a data sync state' def compositeState1 = new CompositeState(cmHandleState: cmHandleState) def compositeState2 = new CompositeState(cmHandleState: cmHandleState) def yangModelCmHandle1 = new YangModelCmHandle(id: 'some-cm-handle', compositeState: compositeState1) def yangModelCmHandle2 = new YangModelCmHandle(id: 'some-cm-handle-2', compositeState: compositeState2) - objectUnderTest.isGlobalDataSyncCacheEnabled = dataSyncCacheEnabled and: 'sync utilities return a cm handle twice' mockSyncUtils.getAdvisedCmHandles() >> [yangModelCmHandle1, yangModelCmHandle2] when: 'module sync poll is executed' @@ -66,8 +65,10 @@ class ModuleSyncWatchdogSpec extends Specification { 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle1) then: 'the composite state cm handle state is now READY' assert compositeState1.getCmHandleState() == CmHandleState.READY + and: 'the data sync enabled flag is set correctly' + compositeState1.getDataSyncEnabled() == false and: 'the data store sync state returns the expected state' - compositeState1.getDataStores().operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState + compositeState1.getDataStores().operationalDataStore.dataStoreSyncState == DataStoreSyncState.NONE_REQUESTED and: 'the first cm handle state is updated' 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle', compositeState1) then: 'the inventory persistence cm handle returns a composite state for the second cm handle' @@ -78,10 +79,6 @@ class ModuleSyncWatchdogSpec extends Specification { assert compositeState2.getCmHandleState() == CmHandleState.READY and: 'the second cm handle state is updated' 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle-2', compositeState2) - where: - scenario | dataSyncCacheEnabled || expectedDataStoreSyncState - 'data sync cache enabled' | true || DataStoreSyncState.UNSYNCHRONIZED - 'data sync cache is not enabled' | false || DataStoreSyncState.NONE_REQUESTED } def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handle with failure'() {