package org.onap.cps.ncmp.api.impl.operations;
-import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_RUNNING;
-import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.READ;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA;
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
+import io.micrometer.core.annotation.Timed;
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.NcmpResponseStatus;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
+import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException;
import org.onap.cps.ncmp.api.impl.executor.TaskExecutor;
-import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer;
+import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
+import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
+import org.onap.cps.ncmp.api.impl.utils.data.operation.ResourceDataOperationRequestUtils;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.api.models.DataOperationRequest;
import org.onap.cps.spi.exceptions.CpsException;
import org.onap.cps.utils.JsonObjectMapper;
-import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.util.UriComponentsBuilder;
/**
* Operations class for DMI data.
public class DmiDataOperations extends DmiOperations {
private static final long DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS = 30000L;
- private static final String NO_CM_HANDLE_ID = "";
public DmiDataOperations(final InventoryPersistence inventoryPersistence,
final JsonObjectMapper jsonObjectMapper,
* @param optionsParamInQuery options query
* @param topicParamInQuery topic name for (triggering) async responses
* @param requestId requestId for async responses
+ * @param authorization contents of Authorization header, or null if not present
* @return {@code ResponseEntity} response entity
*/
+ @Timed(value = "cps.ncmp.dmi.get",
+ description = "Time taken to fetch the resource data from operational data store for given cm handle "
+ + "identifier on given resource using dmi client")
public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
final String cmHandleId,
final String resourceId,
final String optionsParamInQuery,
final String topicParamInQuery,
- final String requestId) {
+ final String requestId,
+ final String authorization) {
final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
yangModelCmHandle);
final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, resourceId, optionsParamInQuery,
topicParamInQuery, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
- return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ);
- }
-
- /**
- * This method fetches the resource data by data store for given list of cm handles using dmi client.
- *
- * @param dataStoreName data store name
- * @param cmHandleIds list of cm handles
- * @param resourceId resource identifier
- * @param optionsParamInQuery options query
- * @param topicParamInQuery topic name for (triggering) async responses
- * @param requestId requestId for async responses
- * @return {@code ResponseEntity} response entity
- */
- public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
- final List<String> cmHandleIds,
- final String resourceId,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String requestId) {
- final Collection<YangModelCmHandle> yangModelCmHandles
- = inventoryPersistence.getYangModelCmHandles(cmHandleIds);
- final Map<String, Map<String, Map<String, String>>> dmiServiceNameCmHandlePropertiesMap =
- DmiServiceNameOrganizer.getDmiPropertiesPerCmHandleIdPerServiceName(yangModelCmHandles);
-
- buildBulkResourceDataRequestAndSend(dataStoreName, resourceId, optionsParamInQuery,
- topicParamInQuery, requestId, dmiServiceNameCmHandlePropertiesMap);
- return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, authorization);
}
/**
* 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
+ * @param dataStoreName data store name
+ * @param cmHandleId network resource identifier
+ * @param requestId requestId for async responses
* @return {@code ResponseEntity} response entity
*/
public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
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 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);
+ return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, null);
+ }
+
+ /**
+ * 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
+ * @param authorization contents of Authorization header, or null if not present
+ */
+ public void requestResourceDataFromDmi(final String topicParamInQuery,
+ final DataOperationRequest dataOperationRequest,
+ final String requestId,
+ final String authorization) {
+
+ final Set<String> cmHandlesIds
+ = getDistinctCmHandleIdsFromDataOperationRequest(dataOperationRequest);
+
+ final Collection<YangModelCmHandle> yangModelCmHandles
+ = inventoryPersistence.getYangModelCmHandles(cmHandlesIds);
+
+ final Map<String, List<DmiDataOperation>> operationsOutPerDmiServiceName
+ = ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(topicParamInQuery,
+ requestId, dataOperationRequest, yangModelCmHandles);
+
+ buildDataOperationRequestUrlAndSendToDmiService(topicParamInQuery, requestId, operationsOutPerDmiServiceName,
+ authorization);
}
/**
* 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
+ * @param authorization contents of Authorization header, or null if not present
* @return {@code ResponseEntity} response entity
*/
public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleId,
final String resourceId,
- final OperationEnum operation,
+ final OperationType operationType,
final String requestData,
- final String dataType) {
+ final String dataType,
+ final String authorization) {
final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
- final String jsonRequestBody = getDmiRequestBody(operation, null, requestData, dataType,
+ final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType,
yangModelCmHandle);
- final String dmiUrl = getDmiRequestUrl(PASSTHROUGH_RUNNING.getValue(), cmHandleId, resourceId,
+ 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, operation);
+ return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operationType, authorization);
}
private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
return inventoryPersistence.getYangModelCmHandle(cmHandleId);
}
- private String getDmiRequestBody(final OperationEnum operation, final String requestId, final String requestData,
- final String dataType, final YangModelCmHandle yangModelCmHandle) {
+ 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)
+ .operationType(operationType)
.requestId(requestId)
.data(requestData)
.dataType(dataType)
return jsonObjectMapper.asJsonString(dmiRequestBody);
}
- private String getDmiBulkRequestBody(final OperationEnum operation,
- final String requestId,
- final String requestData) {
- final DmiRequestBody dmiBulkRequestBody = DmiRequestBody.builder()
- .operation(operation)
- .requestId(requestId)
- .data(requestData)
- .build();
- return jsonObjectMapper.asJsonString(dmiBulkRequestBody);
- }
-
private String getDmiRequestUrl(final String dataStoreName,
final String cmHandleId,
final String resourceId,
cmHandleId));
}
- private String getDmiServiceBulkRequestUrl(final String dataStoreName,
- final String resourceId,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String dmiServiceName) {
- return dmiServiceUrlBuilder.getBulkRequestUrl(
- dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
- topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName,
- NO_CM_HANDLE_ID));
+ private String getDmiServiceDataOperationRequestUrl(final String dmiServiceName,
+ final String topicParamInQuery,
+ final String requestId) {
+ final MultiValueMap<String, String> dataOperationRequestQueryParams = dmiServiceUrlBuilder
+ .getDataOperationRequestQueryParams(topicParamInQuery, requestId);
+ return dmiServiceUrlBuilder.getDataOperationRequestUrl(dataOperationRequestQueryParams,
+ dmiServiceUrlBuilder.populateDataOperationRequestUriVariables(dmiServiceName));
}
private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle,
}
}
- private void buildBulkResourceDataRequestAndSend(final String dataStoreName,
- final String resourceId,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String requestId,
- final Map<String, Map<String, Map<String, String>>>
- dmiServiceNameCmHandlePropertiesMap) {
- dmiServiceNameCmHandlePropertiesMap.entrySet().parallelStream().forEach(
- dmiServiceNameCmHandlePropertiesEntry -> {
- final String dmiBulkResourceDataUrl = getDmiServiceBulkRequestUrl(dataStoreName, resourceId,
- optionsParamInQuery, topicParamInQuery, dmiServiceNameCmHandlePropertiesEntry.getKey());
- final String jsonRequestBodyAsJsonString =
- jsonObjectMapper.asJsonString(dmiServiceNameCmHandlePropertiesEntry.getValue());
- final String jsonRequestBody
- = getDmiBulkRequestBody(READ, requestId, jsonRequestBodyAsJsonString);
- sendDmiResourceDataRequestToDmiService(dmiBulkResourceDataUrl, jsonRequestBody);
- });
+ private static Set<String> getDistinctCmHandleIdsFromDataOperationRequest(final DataOperationRequest
+ dataOperationRequest) {
+ return dataOperationRequest.getDataOperationDefinitions().stream()
+ .flatMap(dataOperationDefinition ->
+ dataOperationDefinition.getCmHandleIds().stream()).collect(Collectors.toSet());
}
- private void sendDmiResourceDataRequestToDmiService(final String dmiBulkResourceDataUrl,
- final String dmiResourceDataRequestAsJsonString) {
- TaskExecutor.executeTask(() ->
- dmiRestClient.postOperationWithJsonData(dmiBulkResourceDataUrl,
- dmiResourceDataRequestAsJsonString, READ),
+ private void buildDataOperationRequestUrlAndSendToDmiService(final String topicParamInQuery,
+ final String requestId,
+ final Map<String, List<DmiDataOperation>>
+ groupsOutPerDmiServiceName,
+ final String authorization) {
+
+ groupsOutPerDmiServiceName.forEach((dmiServiceName, dmiDataOperationRequestBodies) -> {
+ final String dmiDataOperationResourceUrl =
+ getDmiServiceDataOperationRequestUrl(dmiServiceName, topicParamInQuery, requestId);
+ sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies,
+ authorization);
+ });
+ }
+
+ private void sendDataOperationRequestToDmiService(final String dataOperationResourceUrl,
+ final List<DmiDataOperation> dmiDataOperationRequestBodies,
+ final String authorization) {
+ final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder()
+ .operations(dmiDataOperationRequestBodies).build();
+ final String dmiDataOperationRequestAsJsonString =
+ jsonObjectMapper.asJsonString(dmiDataOperationRequest);
+ TaskExecutor.executeTask(() -> dmiRestClient.postOperationWithJsonData(dataOperationResourceUrl,
+ dmiDataOperationRequestAsJsonString, READ, authorization),
DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS)
- .whenCompleteAsync(this::handleTaskCompletion);
+ .whenCompleteAsync((response, throwable) -> handleTaskCompletionException(throwable,
+ dataOperationResourceUrl, dmiDataOperationRequestBodies));
}
- 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)
+ private void handleTaskCompletionException(final Throwable throwable,
+ final String dataOperationResourceUrl,
+ final List<DmiDataOperation> dmiDataOperationRequestBodies) {
+ if (throwable != null) {
+ final MultiValueMap<String, String> dataOperationResourceUrlParameters =
+ UriComponentsBuilder.fromUriString(dataOperationResourceUrl).build().getQueryParams();
+ final String topicName = dataOperationResourceUrlParameters.get("topic").get(0);
+ final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0);
+
+ final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus, List<String>>>
+ cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
+
+ dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> {
+ final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream()
+ .map(CmHandle::getId).toList();
+ if (throwable.getCause() instanceof HttpClientRequestException) {
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
+ Map.of(UNABLE_TO_READ_RESOURCE_DATA, cmHandleIds));
+ } else {
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
+ Map.of(DMI_SERVICE_NOT_RESPONDING, cmHandleIds));
+ }
+ });
+ ResourceDataOperationRequestUtils.publishErrorMessageToClientTopic(topicName, requestId,
+ cmHandleIdsPerResponseCodesPerOperation);
+ }
}
}