Create Endpoint For Get Cm Handles By Name
[cps.git] / cps-ncmp-service / src / main / java / org / onap / cps / ncmp / api / impl / NetworkCmProxyDataServiceImpl.java
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 highstreet technologies GmbH
4  *  Modifications Copyright (C) 2021-2022 Nordix Foundation
5  *  Modifications Copyright (C) 2021 Pantheon.tech
6  *  Modifications Copyright (C) 2021 Bell Canada
7  *  ================================================================================
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  *
20  *  SPDX-License-Identifier: Apache-2.0
21  *  ============LICENSE_END=========================================================
22  */
23
24 package org.onap.cps.ncmp.api.impl;
25
26 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DATASPACE_NAME;
27 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DMI_REGISTRY_ANCHOR;
28 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NCMP_DMI_REGISTRY_PARENT;
29 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
30 import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMESTAMP;
31 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum;
32 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
33
34 import com.fasterxml.jackson.core.JsonProcessingException;
35 import java.util.Collection;
36 import java.util.HashMap;
37 import java.util.LinkedHashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.stream.Collectors;
41 import lombok.RequiredArgsConstructor;
42 import lombok.extern.slf4j.Slf4j;
43 import org.onap.cps.api.CpsAdminService;
44 import org.onap.cps.api.CpsDataService;
45 import org.onap.cps.api.CpsModuleService;
46 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
47 import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException;
48 import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
49 import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations;
50 import org.onap.cps.ncmp.api.impl.operations.DmiOperations;
51 import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever;
52 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
53 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandlesList;
54 import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
55 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
56 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
57 import org.onap.cps.spi.exceptions.DataValidationException;
58 import org.onap.cps.spi.model.ModuleReference;
59 import org.onap.cps.utils.JsonObjectMapper;
60 import org.springframework.http.ResponseEntity;
61 import org.springframework.stereotype.Service;
62
63 @Slf4j
64 @Service
65 @RequiredArgsConstructor
66 public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService {
67
68     private final CpsDataService cpsDataService;
69
70     private final JsonObjectMapper jsonObjectMapper;
71
72     private final DmiDataOperations dmiDataOperations;
73
74     private final DmiModelOperations dmiModelOperations;
75
76     private final CpsModuleService cpsModuleService;
77
78     private final CpsAdminService cpsAdminService;
79
80     private final NetworkCmProxyDataServicePropertyHandler networkCmProxyDataServicePropertyHandler;
81
82     private final YangModelCmHandleRetriever yangModelCmHandleRetriever;
83
84     @Override
85     public void updateDmiRegistrationAndSyncModule(final DmiPluginRegistration dmiPluginRegistration) {
86         dmiPluginRegistration.validateDmiPluginRegistration();
87         try {
88             if (!dmiPluginRegistration.getCreatedCmHandles().isEmpty()) {
89                 parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration);
90             }
91             if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) {
92                 parseAndUpdateCmHandlesInDmiRegistration(dmiPluginRegistration);
93             }
94             parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration);
95         } catch (final JsonProcessingException | DataNodeNotFoundException e) {
96             final String errorMessage = String.format(
97                     "Error occurred while processing the CM-handle registration request, caused by : [%s]",
98                     e.getMessage());
99             throw new DataValidationException(errorMessage, e.getMessage(), e);
100         }
101     }
102
103     @Override
104     public Object getResourceDataOperationalForCmHandle(final String cmHandleId,
105                                                         final String resourceIdentifier,
106                                                         final String acceptParamInHeader,
107                                                         final String optionsParamInQuery) {
108         return handleResponse(dmiDataOperations.getResourceDataFromDmi(
109             cmHandleId,
110             resourceIdentifier,
111             optionsParamInQuery,
112             acceptParamInHeader,
113             DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL), "Not able to get resource data.");
114     }
115
116     @Override
117     public Object getResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
118                                                                final String resourceIdentifier,
119                                                                final String acceptParamInHeader,
120                                                                final String optionsParamInQuery) {
121         return handleResponse(dmiDataOperations.getResourceDataFromDmi(
122             cmHandleId,
123             resourceIdentifier,
124             optionsParamInQuery,
125             acceptParamInHeader,
126             DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING), "Not able to get resource data.");
127     }
128
129     @Override
130     public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
131                                                                final String resourceIdentifier,
132                                                                final OperationEnum operation,
133                                                                final String requestData,
134                                                                final String dataType) {
135         return handleResponse(
136             dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(
137                 cmHandleId, resourceIdentifier, operation, requestData, dataType),
138             "Not able to " + operation + " resource data.");
139     }
140
141
142     @Override
143     public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) {
144         return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId);
145     }
146
147     /**
148      * Retrieve cm handle identifiers for the given list of module names.
149      *
150      * @param moduleNames module names.
151      * @return a collection of anchor identifiers
152      */
153     @Override
154     public Collection<String> executeCmHandleHasAllModulesSearch(final Collection<String> moduleNames) {
155         return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNames);
156     }
157
158     /**
159      * Retrieve cm handle details for a given cm handle.
160      * @param cmHandleId cm handle identifier
161      * @return cm handle details
162      */
163     @Override
164     public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) {
165         final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle();
166         final YangModelCmHandle yangModelCmHandle =
167             yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId);
168         final List<YangModelCmHandle.Property> dmiProperties = yangModelCmHandle.getDmiProperties();
169         final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties();
170         ncmpServiceCmHandle.setCmHandleID(yangModelCmHandle.getId());
171         setDmiProperties(dmiProperties, ncmpServiceCmHandle);
172         setPublicProperties(publicProperties, ncmpServiceCmHandle);
173         return ncmpServiceCmHandle;
174     }
175
176     private void setDmiProperties(final List<YangModelCmHandle.Property> dmiProperties,
177                                   final NcmpServiceCmHandle ncmpServiceCmHandle) {
178         final Map<String, String> dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size());
179         asPropertiesMap(dmiProperties, dmiPropertiesMap);
180         ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap);
181     }
182
183     private void setPublicProperties(final List<YangModelCmHandle.Property> publicProperties,
184                                      final NcmpServiceCmHandle ncmpServiceCmHandle) {
185         final Map<String, String> publicPropertiesMap = new LinkedHashMap<>();
186         asPropertiesMap(publicProperties, publicPropertiesMap);
187         ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap);
188     }
189
190     private void asPropertiesMap(final List<YangModelCmHandle.Property> properties,
191                                  final Map<String, String> propertiesMap) {
192         for (final YangModelCmHandle.Property property: properties) {
193             propertiesMap.put(property.getName(), property.getValue());
194         }
195     }
196
197     /**
198      * THis method registers a cm handle and initiates modules sync.
199      *
200      * @param dmiPluginRegistration dmi plugin registration information.
201      * @throws JsonProcessingException thrown if json is malformed or missing.
202      */
203     public void parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(
204         final DmiPluginRegistration dmiPluginRegistration) throws JsonProcessingException {
205         final YangModelCmHandlesList createdYangModelCmHandlesList =
206             getUpdatedYangModelCmHandlesList(dmiPluginRegistration,
207                 dmiPluginRegistration.getCreatedCmHandles());
208         registerAndSyncNewCmHandles(createdYangModelCmHandlesList);
209     }
210
211     private static Object handleResponse(final ResponseEntity<?> responseEntity,
212                                          final String exceptionMessage) {
213         if (responseEntity.getStatusCode().is2xxSuccessful()) {
214             return responseEntity.getBody();
215         } else {
216             throw new ServerNcmpException(exceptionMessage,
217                     "DMI status code: " + responseEntity.getStatusCodeValue()
218                             + ", DMI response body: " + responseEntity.getBody());
219         }
220     }
221
222     private void parseAndUpdateCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
223         networkCmProxyDataServicePropertyHandler.updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles());
224     }
225
226     private YangModelCmHandlesList getUpdatedYangModelCmHandlesList(
227         final DmiPluginRegistration dmiPluginRegistration,
228         final List<NcmpServiceCmHandle> updatedCmHandles) {
229         return YangModelCmHandlesList.toYangModelCmHandlesList(
230             dmiPluginRegistration.getDmiPlugin(),
231             dmiPluginRegistration.getDmiDataPlugin(),
232             dmiPluginRegistration.getDmiModelPlugin(),
233             updatedCmHandles);
234     }
235
236     private void registerAndSyncNewCmHandles(final YangModelCmHandlesList yangModelCmHandlesList) {
237         final String cmHandleJsonData = jsonObjectMapper.asJsonString(yangModelCmHandlesList);
238         cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
239                 cmHandleJsonData, NO_TIMESTAMP);
240
241         for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandlesList.getYangModelCmHandles()) {
242             syncModulesAndCreateAnchor(yangModelCmHandle);
243         }
244     }
245
246     protected void syncModulesAndCreateAnchor(final YangModelCmHandle yangModelCmHandle) {
247         syncAndCreateSchemaSet(yangModelCmHandle);
248         createAnchor(yangModelCmHandle);
249     }
250
251     private void parseAndRemoveCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
252         for (final String cmHandle : dmiPluginRegistration.getRemovedCmHandles()) {
253             try {
254                 attemptToDeleteSchemaSetWithCascade(cmHandle);
255                 cpsDataService.deleteListOrListElement(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
256                     "/dmi-registry/cm-handles[@id='" + cmHandle + "']", NO_TIMESTAMP);
257             } catch (final DataNodeNotFoundException e) {
258                 log.warn("Datanode {} not deleted message {}", cmHandle, e.getMessage());
259             }
260         }
261     }
262
263     private void attemptToDeleteSchemaSetWithCascade(final String schemaSetName) {
264         try {
265             cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName,
266                 CASCADE_DELETE_ALLOWED);
267         } catch (final Exception e) {
268             log.warn("Schema set {} delete failed, reason {}", schemaSetName, e.getMessage());
269         }
270     }
271
272     private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle) {
273         final Collection<ModuleReference> moduleReferencesFromCmHandle =
274             dmiModelOperations.getModuleReferences(yangModelCmHandle);
275
276         final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService
277             .identifyNewModuleReferences(moduleReferencesFromCmHandle);
278
279         final Collection<ModuleReference> existingModuleReferencesFromCmHandle =
280             moduleReferencesFromCmHandle.stream().filter(moduleReferenceFromCmHandle ->
281                 !identifiedNewModuleReferencesFromCmHandle.contains(moduleReferenceFromCmHandle)
282             ).collect(Collectors.toList());
283
284         final Map<String, String> newModuleNameToContentMap;
285         if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) {
286             newModuleNameToContentMap = new HashMap<>();
287         } else {
288             newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
289                 identifiedNewModuleReferencesFromCmHandle);
290         }
291         cpsModuleService
292             .createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, yangModelCmHandle.getId(),
293                 newModuleNameToContentMap, existingModuleReferencesFromCmHandle);
294     }
295
296     private void createAnchor(final YangModelCmHandle yangModelCmHandle) {
297         cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, yangModelCmHandle.getId(),
298             yangModelCmHandle.getId());
299     }
300 }