Merge "Add withTrustLevel condition to CmHandle Query API"
authorToine Siebelink <toine.siebelink@est.tech>
Mon, 16 Oct 2023 13:51:05 +0000 (13:51 +0000)
committerGerrit Code Review <gerrit@onap.org>
Mon, 16 Oct 2023 13:51:05 +0000 (13:51 +0000)
1  2 
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy

@@@ -24,6 -24,7 +24,7 @@@ import static org.onap.cps.ncmp.api.imp
  import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES;
  import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES;
  import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH;
+ import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_TRUST_LEVEL;
  import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCpsPathConditionProperties;
  import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties;
  import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
@@@ -70,7 -71,8 +71,8 @@@ public class NetworkCmProxyCmHandleQuer
          return executeQueries(cmHandleQueryServiceParameters,
              this::executeCpsPathQuery,
              this::queryCmHandlesByPublicProperties,
-             this::executeModuleNameQuery);
+             this::executeModuleNameQuery,
+                 this::queryCmHandlesByTrustLevel);
      }
  
      @Override
                  getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
                          InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName());
  
-         return privatePropertyQueryPairs.isEmpty()
-                 ? NO_QUERY_TO_EXECUTE
-                 : cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
+         if (privatePropertyQueryPairs.isEmpty()) {
+             return NO_QUERY_TO_EXECUTE;
+         }
+         return cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
      }
  
      private Collection<String> queryCmHandlesByPublicProperties(
                  getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
                          HAS_ALL_PROPERTIES.getConditionName());
  
-         return publicPropertyQueryPairs.isEmpty()
-                 ? NO_QUERY_TO_EXECUTE
-                 : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+         if (publicPropertyQueryPairs.isEmpty()) {
+             return NO_QUERY_TO_EXECUTE;
+         }
+         return cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+     }
+     private Collection<String> queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters
+                                                                   cmHandleQueryServiceParameters) {
+         final Map<String, String> trustLevelPropertyQueryPairs =
+                 getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
+                         WITH_TRUST_LEVEL.getConditionName());
+         if (trustLevelPropertyQueryPairs.isEmpty()) {
+             return NO_QUERY_TO_EXECUTE;
+         }
+         return cmHandleQueries.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs);
      }
  
      private Collection<String> executeModuleNameQuery(
          }
          try {
              cpsPathQueryResult = collectCmHandleIdsFromDataNodes(
 -                cmHandleQueries.queryCmHandleDataNodesByCpsPath(cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS));
 +                cmHandleQueries.queryCmHandleAncestorsByCpsPath(
 +                        cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS));
          } catch (final PathParsingException pathParsingException) {
              throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
                      pathParsingException);
  package org.onap.cps.ncmp.api.impl;
  
  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.impl.inventory.LockReasonCategory.MODULE_UPGRADE;
  import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
  import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
  import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCmHandleQueryParameters;
  
  import com.google.common.collect.Lists;
  import com.hazelcast.map.IMap;
 +import java.text.MessageFormat;
  import java.time.OffsetDateTime;
  import java.util.ArrayList;
  import java.util.Collection;
@@@ -54,7 -51,6 +54,7 @@@ import org.onap.cps.ncmp.api.impl.event
  import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
  import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
  import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
 +import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder;
  import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils;
  import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState;
  import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
@@@ -72,7 -68,6 +72,7 @@@ import org.onap.cps.ncmp.api.models.Dat
  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.ncmp.api.models.UpgradedCmHandles;
  import org.onap.cps.spi.FetchDescendantsOption;
  import org.onap.cps.spi.exceptions.AlreadyDefinedException;
  import org.onap.cps.spi.exceptions.CpsException;
@@@ -99,7 -94,7 +99,7 @@@ public class NetworkCmProxyDataServiceI
      private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler;
      private final CpsDataService cpsDataService;
      private final IMap<String, Object> moduleSyncStartedOnCmHandles;
-     private final IMap<String, TrustLevel> trustLevelPerDmiPlugin;
+     private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
  
      @Override
      public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
  
          if (!dmiPluginRegistration.getRemovedCmHandles().isEmpty()) {
              dmiPluginRegistrationResponse.setRemovedCmHandles(
 -                    parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration.getRemovedCmHandles()));
 +                    parseAndProcessDeletedCmHandlesInRegistration(dmiPluginRegistration.getRemovedCmHandles()));
          }
  
          if (!dmiPluginRegistration.getCreatedCmHandles().isEmpty()) {
              dmiPluginRegistrationResponse.setCreatedCmHandles(
 -                    parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration));
 +                    parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration));
          }
          if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) {
              dmiPluginRegistrationResponse.setUpdatedCmHandles(
                      networkCmProxyDataServicePropertyHandler
                              .updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()));
          }
 +        if (dmiPluginRegistration.getUpgradedCmHandles() != null
 +                && !dmiPluginRegistration.getUpgradedCmHandles().getCmHandles().isEmpty()) {
 +            dmiPluginRegistrationResponse.setUpgradedCmHandles(
 +                    parseAndProcessUpgradedCmHandlesInRegistration(dmiPluginRegistration));
 +        }
  
          setTrustLevelPerDmiPlugin(dmiPluginRegistration);
  
       */
      @Override
      public void setDataSyncEnabled(final String cmHandleId, final boolean dataSyncEnabled) {
 -        final CompositeState compositeState = inventoryPersistence
 -                .getCmHandleState(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) {
       */
      @Override
      public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) {
 -        final YangModelCmHandle yangModelCmHandle =
 -                inventoryPersistence.getYangModelCmHandle(cmHandleId);
 +        final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
          final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties();
          final Map<String, String> cmHandlePublicProperties = new HashMap<>();
          YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties);
       * @param dmiPluginRegistration dmi plugin registration information.
       * @return cm-handle registration response for create cm-handle requests.
       */
 -    public List<CmHandleRegistrationResponse> parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(
 +    public List<CmHandleRegistrationResponse> parseAndProcessCreatedCmHandlesInRegistration(
              final DmiPluginRegistration dmiPluginRegistration) {
          final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>();
          dmiPluginRegistration.getCreatedCmHandles()
                              dmiPluginRegistration.getDmiPlugin(),
                              dmiPluginRegistration.getDmiDataPlugin(),
                              dmiPluginRegistration.getDmiModelPlugin(),
 -                            cmHandle);
 +                            cmHandle,
 +                            cmHandle.getModuleSetTag());
                      cmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.ADVISED);
                  });
          return registerNewCmHandles(cmHandleStatePerCmHandle);
      }
  
 -    protected List<CmHandleRegistrationResponse> parseAndRemoveCmHandlesInDmiRegistration(
 +    protected List<CmHandleRegistrationResponse> parseAndProcessDeletedCmHandlesInRegistration(
              final List<String> tobeRemovedCmHandles) {
          final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses =
                  new ArrayList<>(tobeRemovedCmHandles.size());
          final Collection<YangModelCmHandle> yangModelCmHandles =
 -            inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandles);
 +                inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandles);
  
          updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING);
  
          return cmHandleRegistrationResponses;
      }
  
 +    protected List<CmHandleRegistrationResponse> parseAndProcessUpgradedCmHandlesInRegistration(
 +            final DmiPluginRegistration dmiPluginRegistration) {
 +
 +        final UpgradedCmHandles upgradedCmHandles = dmiPluginRegistration.getUpgradedCmHandles();
 +        final String moduleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag();
 +        final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle =
 +                new HashMap<>(upgradedCmHandles.getCmHandles().size());
 +        final Collection<String> notReadyCmHandles = new ArrayList<>(upgradedCmHandles.getCmHandles().size());
 +        final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle();
 +        final String formattedModuleSetTag = MessageFormat.format("new moduleSetTag: {0}", moduleSetTag);
 +
 +        upgradedCmHandles.getCmHandles().forEach(cmHandleId -> {
 +            if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) {
 +                ncmpServiceCmHandle.setCmHandleId(cmHandleId);
 +                ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder()
 +                        .withCmHandleState(CmHandleState.READY)
 +                        .withLockReason(MODULE_UPGRADE, formattedModuleSetTag).build());
 +                final YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(
 +                        dmiPluginRegistration.getDmiPlugin(),
 +                        dmiPluginRegistration.getDmiDataPlugin(),
 +                        dmiPluginRegistration.getDmiModelPlugin(),
 +                        ncmpServiceCmHandle,
 +                        moduleSetTag);
 +                cmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED);
 +            } else {
 +                notReadyCmHandles.add(cmHandleId);
 +            }
 +        });
 +
 +        final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses
 +                = upgradeCmHandles(cmHandleStatePerCmHandle);
 +        cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses(notReadyCmHandles,
 +                CM_HANDLES_NOT_READY));
 +        return cmHandleRegistrationResponses;
 +    }
 +
      private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) {
          try {
              deleteCmHandleFromDbAndModuleSyncMap(cmHandleId);
  
      private List<CmHandleRegistrationResponse> registerNewCmHandles(final Map<YangModelCmHandle, CmHandleState>
                                                                              cmHandleStatePerCmHandle) {
 -        final List<String> cmHandleIds = cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId)
 -                .toList();
 +        final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle);
          try {
              lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
              return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds);
          }
      }
  
 +    private List<CmHandleRegistrationResponse> upgradeCmHandles(final Map<YangModelCmHandle, CmHandleState>
 +                                                                        cmHandleStatePerCmHandle) {
 +        final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle);
 +        log.info("Moving cm handles : {} into locked (for upgrade) state.", cmHandleIds);
 +        try {
 +            lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
 +            return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds);
 +        } catch (final Exception exception) {
 +            return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, exception);
 +        }
 +    }
 +
 +    private static List<String> getCmHandleIds(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) {
 +        return cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId).toList();
 +    }
 +
      private void setTrustLevelPerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) {
          if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) {
              trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiPlugin(), TrustLevel.COMPLETE);
@@@ -44,6 -44,14 +44,14 @@@ public interface CmHandleQueries 
       */
      Collection<String> queryCmHandlePublicProperties(Map<String, String> publicPropertyQueryPairs);
  
+     /**
+      * Query CmHandles based on Trust Level.
+      *
+      * @param trustLevelPropertyQueryPairs trust level properties for query
+      * @return CmHandles which have desired trust level
+      */
+     Collection<String> queryCmHandlesByTrustLevel(Map<String, String> trustLevelPropertyQueryPairs);
      /**
       * Method which returns cm handles by the cm handles state.
       *
       */
      List<DataNode> queryCmHandlesByState(CmHandleState cmHandleState);
  
 +    /**
 +     * Method to return data nodes with ancestor representing the cm handles.
 +     *
 +     * @param cpsPath cps path for which the cmHandle is requested
 +     * @return a list of data nodes representing the cm handles.
 +     */
 +    List<DataNode> queryCmHandleAncestorsByCpsPath(String cpsPath,
 +                                                   FetchDescendantsOption fetchDescendantsOption);
 +
      /**
       * Method to return data nodes representing the cm handles.
       *
       * @param cpsPath cps path for which the cmHandle is requested
       * @return a list of data nodes representing the cm handles.
       */
 -    List<DataNode> queryCmHandleDataNodesByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption);
 +    List<DataNode> queryNcmpRegistryByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption);
  
      /**
       * Method to check the state of a cm handle with given id.
@@@ -35,6 -35,8 +35,8 @@@ import java.util.Map
  import java.util.stream.Collectors;
  import lombok.RequiredArgsConstructor;
  import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType;
+ import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
+ import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelFilter;
  import org.onap.cps.spi.CpsDataPersistenceService;
  import org.onap.cps.spi.FetchDescendantsOption;
  import org.onap.cps.spi.model.DataNode;
@@@ -45,9 -47,9 +47,9 @@@ import org.springframework.stereotype.C
  public class CmHandleQueriesImpl implements CmHandleQueries {
  
      private static final String DESCENDANT_PATH = "//";
-     private final CpsDataPersistenceService cpsDataPersistenceService;
      private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles";
+     private final CpsDataPersistenceService cpsDataPersistenceService;
+     private final Map<String, TrustLevel> trustLevelPerCmHandle;
  
      @Override
      public Collection<String> queryCmHandleAdditionalProperties(final Map<String, String> privatePropertyQueryPairs) {
          return queryCmHandleAnyProperties(publicPropertyQueryPairs, PropertyType.PUBLIC);
      }
  
+     @Override
+     public Collection<String> queryCmHandlesByTrustLevel(final Map<String, String> trustLevelPropertyQueryPairs) {
+         final String trustLevelProperty = trustLevelPropertyQueryPairs.values().iterator().next();
+         final TrustLevel targetTrustLevel = TrustLevel.valueOf(trustLevelProperty);
+         final TrustLevelFilter trustLevelFilter = new TrustLevelFilter(targetTrustLevel, trustLevelPerCmHandle);
+         return trustLevelFilter.getAllCmHandleIdsByTargetTrustLevel();
+     }
      @Override
      public List<DataNode> queryCmHandlesByState(final CmHandleState cmHandleState) {
 -        return queryCmHandleDataNodesByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]",
 +        return queryCmHandleAncestorsByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]",
              INCLUDE_ALL_DESCENDANTS);
      }
  
      @Override
 -    public List<DataNode> queryCmHandleDataNodesByCpsPath(final String cpsPath,
 -            final FetchDescendantsOption fetchDescendantsOption) {
 +    public List<DataNode> queryNcmpRegistryByCpsPath(final String cpsPath,
 +                                                     final FetchDescendantsOption fetchDescendantsOption) {
          return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
 -            cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption);
 +                cpsPath, fetchDescendantsOption);
 +    }
 +
 +    @Override
 +    public List<DataNode> queryCmHandleAncestorsByCpsPath(final String cpsPath,
 +                                                          final FetchDescendantsOption fetchDescendantsOption) {
 +        return queryNcmpRegistryByCpsPath(cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption);
      }
  
      @Override
@@@ -87,7 -92,7 +98,7 @@@
  
      @Override
      public List<DataNode> queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) {
 -        return queryCmHandleDataNodesByCpsPath("//state/datastores" + "/operational[@sync-state=\""
 +        return queryCmHandleAncestorsByCpsPath("//state/datastores" + "/operational[@sync-state=\""
                  + dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS);
      }
  
                  + publicPropertyQueryPair.getKey()
                  + "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]";
  
 -            final Collection<DataNode> dataNodes = queryCmHandleDataNodesByCpsPath(cpsPath, OMIT_DESCENDANTS);
 +            final Collection<DataNode> dataNodes = queryCmHandleAncestorsByCpsPath(cpsPath,
 +                    OMIT_DESCENDANTS);
              if (cmHandleIds == null) {
                  cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes);
              } else {
@@@ -39,7 -39,7 +39,7 @@@ import spock.lang.Specificatio
  class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
  
      def cmHandleQueries = Mock(CmHandleQueries)
-     def partiallyMockedCmHandleQueries = Spy(CmHandleQueriesImpl)
+     def partiallyMockedCmHandleQueries = Spy(CmHandleQueries)
      def mockInventoryPersistence = Mock(InventoryPersistence)
  
      def dmiRegistry = new DataNode(xpath: NCMP_DMI_REGISTRY_PARENT, childDataNodes: createDataNodeList(['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4']))
@@@ -53,7 -53,7 +53,7 @@@
              def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']])
              cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
          and: 'the query get the cm handle datanodes excluding all descendants returns a datanode'
 -            cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])]
 +            cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])]
          when: 'the query is executed for cm handle ids'
              def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
          then: 'the correct expected cm handles ids are returned'
@@@ -66,7 -66,7 +66,7 @@@
              def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']])
              cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
          and: 'cmHandleQueries throws a path parsing exception'
 -            cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> { throw thrownException }
 +            cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> { throw thrownException }
          when: 'the query is executed for cm handle ids'
              objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
          then: 'a data validation exception is thrown'
              'No anchors are returned' | []
      }
  
+     def 'Query cm handles with some trust level query parameters'() {
+         given: 'a trust level condition property'
+             def trustLevelQueryParameters = new CmHandleQueryServiceParameters()
+             def trustLevelConditionProperties = createConditionProperties('cmHandleWithTrustLevel', [['trustLevel': 'COMPLETE'] as Map])
+             trustLevelQueryParameters.setCmHandleQueryParameters([trustLevelConditionProperties])
+         when: 'the query is being executed'
+             objectUnderTest.queryCmHandleIds(trustLevelQueryParameters)
+         then: 'the query is being delegated to the cm handle query service with correct parameter'
+             1 * cmHandleQueries.queryCmHandlesByTrustLevel(['trustLevel': 'COMPLETE'] as Map)
+     }
      def 'Query cm handle details with module names when #scenario from query.'() {
          given: 'a modules condition property'
              def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
@@@ -76,7 -76,7 +76,7 @@@ class NetworkCmProxyDataServiceImplSpe
      def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandleQueryService)
      def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
      def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>)
-     def stubTrustLevelPerDmiPlugin = Stub(IMap<String, TrustLevel>)
+     def stubTrustLevelPerDmiPlugin = Stub(Map<String, TrustLevel>)
  
      def NO_TOPIC = null
      def NO_REQUEST_ID = null
              dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
              mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle]
          when: 'parse and create cm handle in dmi registration then sync module'
 -            objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(mockDmiPluginRegistration)
 +            objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(mockDmiPluginRegistration)
          then: 'system persists the cm handle state'
              1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> {
                  args -> {
  
  package org.onap.cps.ncmp.api.inventory
  
+ import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
  import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
  import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
  import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
  import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
  import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
  
+ import com.hazelcast.map.IMap
  import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueriesImpl
  import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
  import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
@@@ -37,8 -40,9 +40,9 @@@ import spock.lang.Specificatio
  
  class CmHandleQueriesImplSpec extends Specification {
      def cpsDataPersistenceService = Mock(CpsDataPersistenceService)
+     def trustLevelPerCmHandle = [ 'my completed cm handle': TrustLevel.COMPLETE, 'my untrusted cm handle': TrustLevel.NONE ]
  
-     def objectUnderTest = new CmHandleQueriesImpl(cpsDataPersistenceService)
+     def objectUnderTest = new CmHandleQueriesImpl(cpsDataPersistenceService, trustLevelPerCmHandle)
  
      @Shared
      def static sampleDataNodes = [new DataNode()]
              result.containsAll(expectedCmHandleIds)
              result.size() == expectedCmHandleIds.size()
          where: 'the following data is used'
-             scenario                         | publicPropertyPairs                                                                           || expectedCmHandleIds
-             'single property matches'        | ['Contact' : 'newemailforstore@bookstore.com']                                                || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
-             'public property does not match' | ['wont_match' : 'wont_match']                                                                 || []
-             '2 properties, only one match'   | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': 'newemailforstore2@bookstore.com'] || ['PNFDemo4']
-             '2 properties, no matches'       | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': '']                                || []
+             scenario                         | publicPropertyPairs                                                                      || expectedCmHandleIds
+             'single property matches'        | [Contact: 'newemailforstore@bookstore.com']                                              || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
+             'public property does not match' | [wont_match: 'wont_match']                                                               || []
+             '2 properties, only one match'   | [Contact: 'newemailforstore@bookstore.com', Contact2: 'newemailforstore2@bookstore.com'] || ['PNFDemo4']
+             '2 properties, no matches'       | [Contact: 'newemailforstore@bookstore.com', Contact2: '']                                || []
+     }
+     def 'Query cm handles on trust level'() {
+         given: 'query properties for trustlevel COMPLETE'
+             def trustLevelPropertyQueryPairs = ['trustLevel' : TrustLevel.COMPLETE.toString()]
+         when: 'the query is executed'
+             def result = objectUnderTest.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs)
+         then: 'the result only contains the completed cm handle'
+             assert result.size() == 1
+             assert result[0] == 'my completed cm handle'
      }
  
      def 'Query CmHandles using empty public properties query pair.'() {
                  cpsPath + '/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS)
                  >> Arrays.asList(cmHandleDataNode)
          when: 'get cm handles by cps path is invoked'
 -            def result = objectUnderTest.queryCmHandleDataNodesByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS)
 +            def result = objectUnderTest.queryCmHandleAncestorsByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS)
          then: 'the returned result is a list of data nodes returned by cps data service'
              assert result.contains(cmHandleDataNode)
      }