X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=cps-ncmp-service%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fcps%2Fncmp%2Fapi%2Fimpl%2Foperations%2FDmiDataOperations.java;h=8596c56dca03156a81673456501b1471a641a398;hb=7090a07b05517e0a748cb82ffac8840de82c7fa5;hp=68de9d5c6b5541f5d2bb5f083264c330196e4292;hpb=697caa85dd35d5996d604935987e43b61b5811c2;p=cps.git diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java index 68de9d5c6..8596c56dc 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation + * Copyright (C) 2021-2023 Nordix Foundation + * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,77 +16,126 @@ * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= + * ============LICENSE_END========================================================= */ package org.onap.cps.ncmp.api.impl.operations; -import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING; -import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum; -import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ; +import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING; +import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration; +import org.onap.cps.ncmp.api.impl.executor.TaskExecutor; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; +import org.onap.cps.ncmp.api.impl.utils.ResourceDataOperationRequestUtils; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.inventory.CmHandleState; +import org.onap.cps.ncmp.api.inventory.InventoryPersistence; +import org.onap.cps.ncmp.api.models.DataOperationRequest; +import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; /** * Operations class for DMI data. */ @Component +@Slf4j public class DmiDataOperations extends DmiOperations { - /** - * Constructor for {@code DmiOperations}. This method also manipulates url properties. - * - * @param dmiRestClient {@code DmiRestClient} - */ - public DmiDataOperations(final YangModelCmHandleRetriever cmHandlePropertiesRetriever, + private static final long DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS = 30000L; + + public DmiDataOperations(final InventoryPersistence inventoryPersistence, final JsonObjectMapper jsonObjectMapper, final NcmpConfiguration.DmiProperties dmiProperties, - final DmiRestClient dmiRestClient, final DmiServiceUrlBuilder dmiServiceUrlBuilder) { - super(cmHandlePropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder); + final DmiRestClient dmiRestClient, + final DmiServiceUrlBuilder dmiServiceUrlBuilder) { + super(inventoryPersistence, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder); } /** * This method fetches the resource data from operational data store for given cm handle * identifier on given resource using dmi client. * - * @param cmHandleId network resource identifier - * @param resourceId resource identifier + * @param dataStoreName name of data store + * @param cmHandleId network resource identifier + * @param resourceId resource identifier * @param optionsParamInQuery options query - * @param acceptParamInHeader accept parameter - * @param dataStore data store enum - * @param requestId requestId for async responses * @param topicParamInQuery topic name for (triggering) async responses + * @param requestId requestId for async responses * @return {@code ResponseEntity} response entity */ - public ResponseEntity getResourceDataFromDmi(final String cmHandleId, + public ResponseEntity getResourceDataFromDmi(final String dataStoreName, + final String cmHandleId, final String resourceId, final String optionsParamInQuery, - final String acceptParamInHeader, - final DataStoreEnum dataStore, - final String requestId, - final String topicParamInQuery) { - final YangModelCmHandle yangModelCmHandle = - yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId); - final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() - .operation(READ) - .requestId(requestId) - .build(); - dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); - final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody); + final String topicParamInQuery, + final String requestId) { + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); + final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); + validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); + final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, + yangModelCmHandle); + final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, resourceId, optionsParamInQuery, + topicParamInQuery, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA)); + return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ); + } - final var dmiResourceDataUrl = dmiServiceUrlBuilder.getDmiDatastoreUrl( - dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery, - topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables( - yangModelCmHandle, cmHandleId, dataStore)); - final var httpHeaders = prepareHeader(acceptParamInHeader); - return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonBody, httpHeaders); + /** + * This method fetches all the resource data from operational data store for given cm handle + * identifier using dmi client. + * + * @param dataStoreName data store name + * @param cmHandleId network resource identifier + * @param requestId requestId for async responses + * @return {@code ResponseEntity} response entity + */ + public ResponseEntity getResourceDataFromDmi(final String dataStoreName, + final String cmHandleId, + final String requestId) { + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); + final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, + yangModelCmHandle); + final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, "/", + null, null, + yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA)); + final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); + validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); + return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ); + } + + /** + * This method requests the resource data by data store for given list of cm handles using dmi client. + * The data wil be returned as message on the topic specified. + * + * @param topicParamInQuery topic name for (triggering) async responses + * @param dataOperationRequest data operation request to execute operations + * @param requestId requestId for as a response + */ + public void requestResourceDataFromDmi(final String topicParamInQuery, + final DataOperationRequest dataOperationRequest, + final String requestId) { + + final Set cmHandlesIds + = getDistinctCmHandleIdsFromDataOperationRequest(dataOperationRequest); + + final Collection yangModelCmHandles + = getYangModelCmHandlesInReadyState(cmHandlesIds); + + final Map> operationsOutPerDmiServiceName + = ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(dataOperationRequest, + yangModelCmHandles); + + buildDataOperationRequestUrlAndSendToDmiService(topicParamInQuery, requestId, operationsOutPerDmiServiceName); } /** @@ -93,31 +143,120 @@ public class DmiDataOperations extends DmiOperations { * identifier on given resource using dmi client. * * @param cmHandleId network resource identifier - * @param resourceId resource identifier - * @param operation operation enum - * @param requestData the request data - * @param dataType data type + * @param resourceId resource identifier + * @param operationType operation enum + * @param requestData the request data + * @param dataType data type * @return {@code ResponseEntity} response entity */ public ResponseEntity writeResourceDataPassThroughRunningFromDmi(final String cmHandleId, final String resourceId, - final OperationEnum operation, + final OperationType operationType, final String requestData, final String dataType) { - final YangModelCmHandle yangModelCmHandle = - yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId); + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); + final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType, + yangModelCmHandle); + final String dmiUrl = getDmiRequestUrl(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleId, resourceId, + null, null, + yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA)); + final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); + validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); + return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operationType); + } + + private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) { + return inventoryPersistence.getYangModelCmHandle(cmHandleId); + } + + private String getDmiRequestBody(final OperationType operationType, + final String requestId, + final String requestData, + final String dataType, + final YangModelCmHandle yangModelCmHandle) { final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() - .operation(operation) - .data(requestData) - .dataType(dataType) - .build(); + .operationType(operationType) + .requestId(requestId) + .data(requestData) + .dataType(dataType) + .build(); dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties()); - final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody); - final String dmiUrl = - dmiServiceUrlBuilder.getDmiDatastoreUrl(dmiServiceUrlBuilder.populateQueryParams(resourceId, - null, null), - dmiServiceUrlBuilder.populateUriVariables(yangModelCmHandle, cmHandleId, PASSTHROUGH_RUNNING)); - return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonBody, new HttpHeaders()); + return jsonObjectMapper.asJsonString(dmiRequestBody); } + private String getDmiRequestUrl(final String dataStoreName, + final String cmHandleId, + final String resourceId, + final String optionsParamInQuery, + final String topicParamInQuery, + final String dmiServiceName) { + return dmiServiceUrlBuilder.getDmiDatastoreUrl( + dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery, + topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName, + cmHandleId)); + } + + private String getDmiServiceDataOperationRequestUrl(final String dmiServiceName, + final String topicParamInQuery, + final String requestId) { + final MultiValueMap dataOperationRequestQueryParams = dmiServiceUrlBuilder + .getDataOperationRequestQueryParams(topicParamInQuery, requestId); + return dmiServiceUrlBuilder.getDataOperationRequestUrl(dataOperationRequestQueryParams, + dmiServiceUrlBuilder.populateDataOperationRequestUriVariables(dmiServiceName)); + } + + private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle, + final CmHandleState cmHandleState) { + if (cmHandleState != CmHandleState.READY) { + throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. " + + "cm handle state is " + + yangModelCmHandle.getCompositeState().getCmHandleState()); + } + } + + private static Set getDistinctCmHandleIdsFromDataOperationRequest(final DataOperationRequest + dataOperationRequest) { + return dataOperationRequest.getDataOperationDefinitions().stream() + .flatMap(dataOperationDefinition -> + dataOperationDefinition.getCmHandleIds().stream()).collect(Collectors.toSet()); + } + + private Collection getYangModelCmHandlesInReadyState(final Set requestedCmHandleIds) { + // TODO Need to publish an error response to client given topic. + // Code should be implemented into https://jira.onap.org/browse/CPS-1614 ( + // NCMP : Error handling for non-ready cm handle state) + return inventoryPersistence.getYangModelCmHandles(requestedCmHandleIds).stream() + .filter(yangModelCmHandle -> yangModelCmHandle.getCompositeState().getCmHandleState() + == CmHandleState.READY).collect(Collectors.toList()); + } + + private void buildDataOperationRequestUrlAndSendToDmiService(final String topicParamInQuery, + final String requestId, + final Map> + groupsOutPerDmiServiceName) { + + groupsOutPerDmiServiceName.entrySet().forEach(groupsOutPerDmiServiceNameEntry -> { + final String dmiServiceName = groupsOutPerDmiServiceNameEntry.getKey(); + final List dmiDataOperationRequestBodies = groupsOutPerDmiServiceNameEntry.getValue(); + final String dmiDataOperationResourceUrl = + getDmiServiceDataOperationRequestUrl(dmiServiceName, topicParamInQuery, requestId); + sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies); + }); + } + + private void sendDataOperationRequestToDmiService(final String dataOperationResourceUrl, + final List dmiDataOperationRequestBodies) { + final String dataOperationRequestBodiesAsJsonString = + jsonObjectMapper.asJsonString(dmiDataOperationRequestBodies); + TaskExecutor.executeTask(() -> dmiRestClient.postOperationWithJsonData(dataOperationResourceUrl, + dataOperationRequestBodiesAsJsonString, READ), + DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS) + .whenCompleteAsync(this::handleTaskCompletion); + } + + private void handleTaskCompletion(final Object response, final Throwable throwable) { + // TODO Need to publish an error response to client given topic. + // Code should be implemented into https://jira.onap.org/browse/CPS-1558 ( + // NCMP : Handle non responding DMI-Plugin) + } }