2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-2023 Nordix Foundation
4 * Modifications Copyright (C) 2022 Bell Canada
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.cps.ncmp.api.impl.operations;
24 import static org.onap.cps.ncmp.api.impl.operations.DataStoreEnum.PASSTHROUGH_RUNNING;
25 import static org.onap.cps.ncmp.api.impl.operations.OperationEnum.READ;
27 import java.util.Collection;
28 import java.util.List;
30 import lombok.extern.slf4j.Slf4j;
31 import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
32 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
33 import org.onap.cps.ncmp.api.impl.executor.TaskExecutor;
34 import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer;
35 import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
36 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
37 import org.onap.cps.ncmp.api.inventory.CmHandleState;
38 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
39 import org.onap.cps.spi.exceptions.CpsException;
40 import org.onap.cps.utils.JsonObjectMapper;
41 import org.springframework.http.HttpStatus;
42 import org.springframework.http.ResponseEntity;
43 import org.springframework.stereotype.Component;
46 * Operations class for DMI data.
50 public class DmiDataOperations extends DmiOperations {
52 private static final long DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS = 30000L;
53 private static final String NO_CM_HANDLE_ID = "";
55 public DmiDataOperations(final InventoryPersistence inventoryPersistence,
56 final JsonObjectMapper jsonObjectMapper,
57 final NcmpConfiguration.DmiProperties dmiProperties,
58 final DmiRestClient dmiRestClient,
59 final DmiServiceUrlBuilder dmiServiceUrlBuilder) {
60 super(inventoryPersistence, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder);
64 * This method fetches the resource data from operational data store for given cm handle
65 * identifier on given resource using dmi client.
67 * @param dataStoreName name of data store
68 * @param cmHandleId network resource identifier
69 * @param resourceId resource identifier
70 * @param optionsParamInQuery options query
71 * @param topicParamInQuery topic name for (triggering) async responses
72 * @param requestId requestId for async responses
73 * @return {@code ResponseEntity} response entity
75 public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
76 final String cmHandleId,
77 final String resourceId,
78 final String optionsParamInQuery,
79 final String topicParamInQuery,
80 final String requestId) {
81 final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
82 final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
83 validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
84 final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null,
86 final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, resourceId, optionsParamInQuery,
87 topicParamInQuery, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
88 return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ);
92 * This method fetches the resource data by data store for given list of cm handles using dmi client.
94 * @param dataStoreName data store name
95 * @param cmHandleIds list of cm handles
96 * @param resourceId resource identifier
97 * @param optionsParamInQuery options query
98 * @param topicParamInQuery topic name for (triggering) async responses
99 * @param requestId requestId for async responses
100 * @return {@code ResponseEntity} response entity
102 public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
103 final List<String> cmHandleIds,
104 final String resourceId,
105 final String optionsParamInQuery,
106 final String topicParamInQuery,
107 final String requestId) {
108 final Collection<YangModelCmHandle> yangModelCmHandles
109 = inventoryPersistence.getYangModelCmHandles(cmHandleIds);
110 final Map<String, Map<String, Map<String, String>>> dmiServiceNameCmHandlePropertiesMap =
111 DmiServiceNameOrganizer.getDmiPropertiesPerCmHandleIdPerServiceName(yangModelCmHandles);
113 buildBulkResourceDataRequestAndSend(dataStoreName, resourceId, optionsParamInQuery,
114 topicParamInQuery, requestId, dmiServiceNameCmHandlePropertiesMap);
115 return new ResponseEntity<>(HttpStatus.ACCEPTED);
119 * This method fetches all the resource data from operational data store for given cm handle
120 * identifier using dmi client.
122 * @param dataStoreName data store name
123 * @param cmHandleId network resource identifier
124 * @param requestId requestId for async responses
125 * @return {@code ResponseEntity} response entity
127 public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
128 final String cmHandleId,
129 final String requestId) {
130 final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
131 final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null,
133 final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, "/", null,
134 null, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
135 final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
136 validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
137 return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody,
142 * This method creates the resource data from pass-through running data store for given cm handle
143 * identifier on given resource using dmi client.
145 * @param cmHandleId network resource identifier
146 * @param resourceId resource identifier
147 * @param operation operation enum
148 * @param requestData the request data
149 * @param dataType data type
150 * @return {@code ResponseEntity} response entity
152 public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleId,
153 final String resourceId,
154 final OperationEnum operation,
155 final String requestData,
156 final String dataType) {
157 final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
158 final String jsonRequestBody = getDmiRequestBody(operation, null, requestData, dataType,
160 final String dmiUrl = getDmiRequestUrl(PASSTHROUGH_RUNNING.getValue(), cmHandleId, resourceId,
162 yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
163 final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
164 validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
165 return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operation);
168 private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
169 return inventoryPersistence.getYangModelCmHandle(cmHandleId);
172 private String getDmiRequestBody(final OperationEnum operation, final String requestId, final String requestData,
173 final String dataType, final YangModelCmHandle yangModelCmHandle) {
174 final DmiRequestBody dmiRequestBody = DmiRequestBody.builder()
175 .operation(operation)
176 .requestId(requestId)
180 dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties());
181 return jsonObjectMapper.asJsonString(dmiRequestBody);
184 private String getDmiBulkRequestBody(final OperationEnum operation,
185 final String requestId,
186 final String requestData) {
187 final DmiRequestBody dmiBulkRequestBody = DmiRequestBody.builder()
188 .operation(operation)
189 .requestId(requestId)
192 return jsonObjectMapper.asJsonString(dmiBulkRequestBody);
195 private String getDmiRequestUrl(final String dataStoreName,
196 final String cmHandleId,
197 final String resourceId,
198 final String optionsParamInQuery,
199 final String topicParamInQuery,
200 final String dmiServiceName) {
201 return dmiServiceUrlBuilder.getDmiDatastoreUrl(
202 dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
203 topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName,
207 private String getDmiServiceBulkRequestUrl(final String dataStoreName,
208 final String resourceId,
209 final String optionsParamInQuery,
210 final String topicParamInQuery,
211 final String dmiServiceName) {
212 return dmiServiceUrlBuilder.getBulkRequestUrl(
213 dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
214 topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName,
218 private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle,
219 final CmHandleState cmHandleState) {
220 if (cmHandleState != CmHandleState.READY) {
221 throw new CpsException("State mismatch exception.", "Cm-Handle not in READY state. "
222 + "cm handle state is "
223 + yangModelCmHandle.getCompositeState().getCmHandleState());
227 private void buildBulkResourceDataRequestAndSend(final String dataStoreName,
228 final String resourceId,
229 final String optionsParamInQuery,
230 final String topicParamInQuery,
231 final String requestId,
232 final Map<String, Map<String, Map<String, String>>>
233 dmiServiceNameCmHandlePropertiesMap) {
234 dmiServiceNameCmHandlePropertiesMap.entrySet().parallelStream().forEach(
235 dmiServiceNameCmHandlePropertiesEntry -> {
236 final String dmiBulkResourceDataUrl = getDmiServiceBulkRequestUrl(dataStoreName, resourceId,
237 optionsParamInQuery, topicParamInQuery, dmiServiceNameCmHandlePropertiesEntry.getKey());
238 final String jsonRequestBodyAsJsonString =
239 jsonObjectMapper.asJsonString(dmiServiceNameCmHandlePropertiesEntry.getValue());
240 final String jsonRequestBody
241 = getDmiBulkRequestBody(READ, requestId, jsonRequestBodyAsJsonString);
242 sendDmiResourceDataRequestToDmiService(dmiBulkResourceDataUrl, jsonRequestBody);
246 private void sendDmiResourceDataRequestToDmiService(final String dmiBulkResourceDataUrl,
247 final String dmiResourceDataRequestAsJsonString) {
248 TaskExecutor.executeTask(() ->
249 dmiRestClient.postOperationWithJsonData(dmiBulkResourceDataUrl,
250 dmiResourceDataRequestAsJsonString, READ),
251 DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS)
252 .whenCompleteAsync(this::handleTaskCompletion);
255 private void handleTaskCompletion(final Object response, final Throwable throwable) {
256 // TODO Need to publish an error response to client given topic.
257 // Code should be implemented into https://jira.onap.org/browse/CPS-1558 (
258 // NCMP : Handle non responding DMI-Plugin)