4b55f16812c6a8a1c417e4b514e312b372f9d7f2
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
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  * ============LICENSE_END=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.devicemanager.oran.dataprovider;
23
24 import java.time.Instant;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.Objects;
30 import java.util.Optional;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 import org.eclipse.jdt.annotation.NonNull;
34 import org.eclipse.jdt.annotation.Nullable;
35 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.NetconfTimeStamp;
36 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.types.NetconfTimeStampImpl;
37 import org.onap.ccsdk.features.sdnr.wt.devicemanager.oran.util.ORanDMDOMUtility;
38 import org.onap.ccsdk.features.sdnr.wt.devicemanager.oran.util.ORanDeviceManagerQNames;
39 import org.onap.ccsdk.features.sdnr.wt.devicemanager.oran.yangspecs.ORANFM;
40 import org.onap.ccsdk.features.sdnr.wt.devicemanager.oran.yangspecs.OnapSystem;
41 import org.opendaylight.mdsal.dom.api.DOMEvent;
42 import org.opendaylight.mdsal.dom.api.DOMNotification;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.FaultlogBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.FaultlogEntity;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.Guicutthrough;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.GuicutthroughBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.Inventory;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.InventoryBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.SeverityType;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.SourceType;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
54 import org.opendaylight.yangtools.yang.binding.CodeHelpers;
55 import org.opendaylight.yangtools.yang.common.Uint32;
56 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
57 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
58 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
59 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
60 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
61 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
62 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 public class ORanDOMToInternalDataModel {
67
68     private static final Logger LOG = LoggerFactory.getLogger(ORanDOMToInternalDataModel.class);
69     private static final NetconfTimeStamp NETCONFTIME_CONVERTER = NetconfTimeStampImpl.getConverter();
70
71     public static List<Inventory> getInventoryList(NodeId nodeId, NormalizedNode hwData) {
72
73         List<Inventory> inventoryResultList = new ArrayList<Inventory>();
74         ContainerNode hwContainer = (ContainerNode) hwData;
75         MapNode componentMap = (MapNode) hwContainer
76                 .getChildByArg(new NodeIdentifier(ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST));
77         Collection<MapEntryNode> componentMapEntries = componentMap.body();
78
79         for (MapEntryNode componentMapEntryNode : getRootComponents(componentMapEntries)) {
80             inventoryResultList =
81                     recurseGetInventory(nodeId, componentMapEntryNode, componentMapEntries, 0, inventoryResultList);
82         }
83         // Verify if result is complete
84         if (componentMapEntries.size() != inventoryResultList.size()) {
85             LOG.warn(
86                     "Not all data were written to the Inventory. Potential entries with missing "
87                             + "contained-child. Node Id = {}, Components Found = {}, Entries written to Database = {}",
88                     nodeId.getValue(), componentMapEntries.size(), inventoryResultList.size());
89         }
90         return inventoryResultList;
91     }
92
93     private static List<Inventory> recurseGetInventory(NodeId nodeId, MapEntryNode component,
94             Collection<MapEntryNode> componentList, int treeLevel, List<Inventory> inventoryResultList) {
95         //Add element to list, if conversion successfull
96         Optional<Inventory> oInventory = getInternalEquipment(nodeId, component, treeLevel);
97         if (oInventory.isPresent()) {
98             inventoryResultList.add(oInventory.get());
99         }
100         //Walk through list of child keys and add to list
101         for (String childUuid : CodeHelpers.nonnull(new ArrayList<>(ORanDMDOMUtility.getLeafListValue(component,
102                 ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_CONTAINS_CHILD)))) {
103             for (MapEntryNode c : getComponentsByName(childUuid, componentList)) {
104                 inventoryResultList = recurseGetInventory(nodeId, c, componentList, treeLevel + 1, inventoryResultList);
105             }
106         }
107         return inventoryResultList;
108     }
109
110     public static List<MapEntryNode> getRootComponents(Collection<MapEntryNode> componentMapEntries) {
111         List<MapEntryNode> resultList = new ArrayList<>();
112         for (MapEntryNode componentMapEntryNode : componentMapEntries) {
113             if (ORanDMDOMUtility.getLeafValue(componentMapEntryNode,
114                     ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_PARENT) == null) { // Root elements do not have a parent
115                 resultList.add(componentMapEntryNode);
116             }
117         }
118         return resultList;
119     }
120
121     private static List<MapEntryNode> getComponentsByName(String name, Collection<MapEntryNode> componentList) {
122         List<MapEntryNode> resultList = new ArrayList<>();
123         for (MapEntryNode c : componentList) {
124             if (name.equals(ORanDMDOMUtility.getKeyValue(c))) { // <-- Component list is flat search for child's of name
125                 resultList.add(c);
126             }
127         }
128         return resultList;
129     }
130
131     public static Optional<Inventory> getInternalEquipment(NodeId nodeId, MapEntryNode component, int treeLevel) {
132
133         // Make sure that expected data are not null
134         Objects.requireNonNull(nodeId);
135         Objects.requireNonNull(component);
136
137         // Read mandatory data
138
139         @Nullable
140         String nodeIdString = nodeId.getValue();
141         @Nullable
142         String uuid = ORanDMDOMUtility.getKeyValue(component);
143         @Nullable
144         String idParent =
145                 ORanDMDOMUtility.getLeafValue(component, ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_PARENT);
146         @Nullable
147         String uuidParent = idParent != null ? idParent : uuid; //<- Passt nicht
148
149         // do consistency check if all mandatory parameters are there
150         if (treeLevel >= 0 && nodeIdString != null && uuid != null && uuidParent != null) {
151             // Build output data
152
153             InventoryBuilder inventoryBuilder = new InventoryBuilder();
154
155             // General assumed as mandatory
156             inventoryBuilder.setNodeId(nodeIdString);
157             inventoryBuilder.setUuid(uuid);
158             inventoryBuilder.setParentUuid(uuidParent);
159             inventoryBuilder.setTreeLevel(Uint32.valueOf(treeLevel));
160
161             // -- String list with ids of holders (optional)
162             inventoryBuilder.setContainedHolder(ORanDMDOMUtility.getLeafListValue(component,
163                     ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_CONTAINS_CHILD));
164
165             // -- Manufacturer related things (optional)
166             @Nullable
167             String mfgName =
168                     ORanDMDOMUtility.getLeafValue(component, ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_MFG_NAME);
169             inventoryBuilder.setManufacturerName(mfgName);
170             inventoryBuilder.setManufacturerIdentifier(mfgName);
171
172             // Equipment type (optional)
173             inventoryBuilder.setDescription(
174                     ORanDMDOMUtility.getLeafValue(component, ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_DESC));
175             inventoryBuilder.setModelIdentifier(ORanDMDOMUtility.getLeafValue(component,
176                     ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_MODEL_NAME));
177
178             inventoryBuilder.setPartTypeId(
179                     ORanDMDOMUtility.getLeafValue(component, ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_CLASS));
180
181             inventoryBuilder.setTypeName(ORanDMDOMUtility.getKeyValue(component));
182             inventoryBuilder.setVersion(
183                     ORanDMDOMUtility.getLeafValue(component, ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_HW_REV));
184
185             // Equipment instance (optional)
186             @Nullable
187             String mfgDate =
188                     ORanDMDOMUtility.getLeafValue(component, ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_MFG_DATE);
189             if (mfgDate != null) {
190                 inventoryBuilder.setDate(mfgDate);
191             }
192             inventoryBuilder.setSerial(
193                     ORanDMDOMUtility.getLeafValue(component, ORanDeviceManagerQNames.IETF_HW_COMPONENT_LIST_SER_NUM));
194
195             return Optional.of(inventoryBuilder.build());
196         }
197         return Optional.empty();
198     }
199
200     /**
201      * If system data is available convert
202      *
203      * @param sys
204      * @return
205      */
206     public static Optional<Guicutthrough> getGuicutthrough(@Nullable AugmentationNode onapSysAugData,  @NonNull OnapSystem onapSys) {
207
208         if (onapSysAugData != null) {
209             String name = ORanDMDOMUtility.getLeafValue(onapSysAugData, onapSys.getName());
210             @Nullable
211             Uri uri = new Uri(ORanDMDOMUtility.getLeafValue(onapSysAugData, onapSys.getWebUi()));
212             if (uri.getValue() != null) {
213                 GuicutthroughBuilder gcBuilder = new GuicutthroughBuilder();
214                 if (name != null) {
215                     gcBuilder.setName(name);
216                 }
217                 gcBuilder.setWeburi(uri.getValue());
218                 return Optional.of(gcBuilder.build());
219             }
220             LOG.warn("Uri not set to invoke a Gui cut through session to the device. Please set the Uri in the device");
221         }
222         LOG.warn("Retrieving augmented System details failed. Gui cut through information not available");
223         return Optional.empty();
224     }
225
226     /**
227      * Convert fault notification into data-provider FaultLogEntity
228      *
229      * @param notification with O-RAN notification
230      * @param oranfm
231      * @param nodeId of node to handle
232      * @param counter to be integrated into data
233      * @return FaultlogEntity with data
234      */
235     public static FaultlogEntity getFaultLog(DOMNotification notification, @NonNull ORANFM oranfm, NodeId nodeId, Integer counter) {
236         ContainerNode cn = notification.getBody();
237         FaultlogBuilder faultAlarm = new FaultlogBuilder();
238         faultAlarm.setNodeId(nodeId.getValue());
239         faultAlarm.setObjectId(ORanDMDOMUtility.getLeafValue(cn, oranfm.getFaultSourceQName()));
240         faultAlarm.setProblem(ORanDMDOMUtility.getLeafValue(cn, oranfm.getFaultTextQName()));
241         faultAlarm.setSeverity(getSeverityType(
242                 ORanDMDOMUtility.getLeafValue(cn, oranfm.getFaultSeverityQName()),
243                 ORanDMDOMUtility.getLeafValue(cn, oranfm.getFaultIsClearedQName()).equals("true")));
244         faultAlarm.setCounter(counter);
245         faultAlarm.setId(ORanDMDOMUtility.getLeafValue(cn, oranfm.getFaultIdQName()));
246         faultAlarm.setSourceType(SourceType.Netconf);
247         faultAlarm.setTimestamp(getEventTime(notification));
248         return faultAlarm.build();
249     }
250
251     public static FaultlogEntity getFaultLog(UnkeyedListEntryNode activeAlarmEntry, ORANFM oranfm, NodeId nodeId, Integer counter) {
252         FaultlogBuilder faultAlarm = new FaultlogBuilder();
253         faultAlarm.setNodeId(nodeId.getValue());
254         faultAlarm.setObjectId(getObjectId(
255                 ORanDMDOMUtility.getLeafValue(activeAlarmEntry, oranfm.getFaultSourceQName())));
256         faultAlarm.setProblem(
257                 ORanDMDOMUtility.getLeafValue(activeAlarmEntry, oranfm.getFaultTextQName()));
258         faultAlarm.setSeverity(getSeverityType(
259                 ORanDMDOMUtility.getLeafValue(activeAlarmEntry, oranfm.getFaultSeverityQName()),
260                 ORanDMDOMUtility.getLeafValue(activeAlarmEntry, oranfm.getFaultIsClearedQName())
261                         .equals("true")));
262         faultAlarm.setCounter(counter);
263         faultAlarm.setId(ORanDMDOMUtility.getLeafValue(activeAlarmEntry, oranfm.getFaultIdQName()));
264         faultAlarm.setSourceType(SourceType.Netconf);
265         faultAlarm.setTimestamp(NetconfTimeStampImpl.getConverter().getTimeStamp(
266                 ORanDMDOMUtility.getLeafValue(activeAlarmEntry, oranfm.getFaultEventTimeQName())));
267         return faultAlarm.build();
268
269     }
270
271     /**
272      * Convert Instant to NETCONF DateAndTime
273      * @param eventTimeInstant
274      * @return DateAndTime
275      */
276     public static DateAndTime getDateAndTimeOfInstant(Instant eventTimeInstant) {
277         Date eventDate = Date.from(eventTimeInstant);
278         return new DateAndTime(NETCONFTIME_CONVERTER.getTimeStamp(eventDate));
279     }
280
281     private static DateAndTime getEventTime(DOMNotification notification) {
282         DateAndTime eventTime;
283         Instant notificationEventTime = null;
284         if (notification instanceof DOMEvent) {
285             notificationEventTime = ((DOMEvent) notification).getEventInstant();
286             eventTime = NetconfTimeStampImpl.getConverter().getTimeStamp(notificationEventTime.toString());
287         } else {
288             eventTime = NetconfTimeStampImpl.getConverter().getTimeStamp();
289         }
290         return eventTime;
291     }
292
293     /**
294      * Convert O-RAN specific severity into data-provider severity
295      *
296      * @param faultSeverity O-RAN severity
297      * @param isCleared clear indicator
298      * @return data-provider severity type
299      * @throws IllegalArgumentException if conversion not possible.
300      */
301     private static SeverityType getSeverityType(@Nullable String faultSeverity, @Nullable Boolean isCleared)
302             throws IllegalArgumentException {
303         if (isCleared != null && isCleared) {
304             return SeverityType.NonAlarmed;
305         }
306         if (faultSeverity != null) {
307             switch (faultSeverity) {
308                 case "CRITICAL":
309                     return SeverityType.Critical;
310                 case "MAJOR":
311                     return SeverityType.Major;
312                 case "MINOR":
313                     return SeverityType.Minor;
314                 case "WARNING":
315                     return SeverityType.Warning;
316             }
317         }
318         throw new IllegalArgumentException("Unknown Alarm state represent as Critical. isCleared=" + isCleared
319                 + " faultSeverity=" + faultSeverity);
320     }
321
322     private static String getObjectId(String leafValue) {
323         // fault-source = /ietf-hardware:hardware/component[name='slot0-logical0']
324         Pattern p = Pattern.compile("\\/ietf-hardware:hardware\\/component\\[name=\\'(.*)\\']");
325         Matcher m = p.matcher(leafValue);
326         if (m.find()) {
327             return m.group(1);
328         }
329         return leafValue;
330     }
331
332 }