Fix tapi get-topology-details functional test
[transportpce.git] / tapi / src / main / java / org / opendaylight / transportpce / tapi / R2RTapiLinkDiscovery.java
1 /*
2  * Copyright © 2021 Nokia.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.transportpce.tapi;
9
10 import java.nio.charset.Charset;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Optional;
17 import java.util.UUID;
18 import java.util.concurrent.ExecutionException;
19 import java.util.stream.Collectors;
20 import java.util.stream.Stream;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.mdsal.binding.api.MountPoint;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.transportpce.common.Timeouts;
25 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
26 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.Network;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.cp.to.degree.CpToDegree;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.mapping.Mapping;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.network.Nodes;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.network.NodesKey;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev170929.Direction;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Protocols;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.Protocols1;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.lldp.container.lldp.NbrList;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.lldp.container.lldp.nbr.list.IfName;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.AdministrativeState;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.CapacityUnit;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Context;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.ForwardingDirection;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LayerProtocolName;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.capacity.TotalSizeBuilder;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.capacity.pac.AvailableCapacityBuilder;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.capacity.pac.TotalPotentialCapacityBuilder;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.Name;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameBuilder;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.ProtectionType;
54 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.RestorationPolicy;
55 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext;
56 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.link.NodeEdgePoint;
57 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.link.NodeEdgePointBuilder;
58 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.link.NodeEdgePointKey;
59 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.link.ResilienceTypeBuilder;
60 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePoint;
61 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointKey;
62 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.risk.parameter.pac.RiskCharacteristic;
63 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.risk.parameter.pac.RiskCharacteristicBuilder;
64 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Link;
65 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.LinkBuilder;
66 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.LinkKey;
67 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node;
68 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.NodeKey;
69 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology;
70 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.TopologyKey;
71 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.transfer.cost.pac.CostCharacteristic;
72 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.transfer.cost.pac.CostCharacteristicBuilder;
73 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.transfer.timing.pac.LatencyCharacteristic;
74 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.transfer.timing.pac.LatencyCharacteristicBuilder;
75 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.validation.pac.ValidationMechanism;
76 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.validation.pac.ValidationMechanismBuilder;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
78 import org.opendaylight.yangtools.yang.common.Uint64;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
81
82 public class R2RTapiLinkDiscovery {
83
84     private static final Logger LOG = LoggerFactory.getLogger(R2RTapiLinkDiscovery.class);
85
86     private final NetworkTransactionService networkTransactionService;
87     private final DeviceTransactionManager deviceTransactionManager;
88     private static final String PHTNC_MEDIA = "PHOTONIC_MEDIA";
89
90     public R2RTapiLinkDiscovery(NetworkTransactionService networkTransactionService,
91                                 DeviceTransactionManager deviceTransactionManager) {
92         this.networkTransactionService = networkTransactionService;
93         this.deviceTransactionManager = deviceTransactionManager;
94     }
95
96     public Map<LinkKey, Link> readLLDP(NodeId nodeId, int nodeVersion, Uuid tapiTopoUuid) {
97         LOG.info("Tapi R2R Link Node version = {}", nodeVersion);
98         // TODO -> waiting for device 7.1 in network model to change this to a switch statement and include
99         //  support for 7.1 devices
100         switch (nodeVersion) {
101             case 1:
102                 // 1.2.1
103                 InstanceIdentifier<Protocols> protocols121IID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
104                     .child(Protocols.class);
105                 Optional<Protocols> protocol121Object = this.deviceTransactionManager.getDataFromDevice(
106                     nodeId.getValue(), LogicalDatastoreType.OPERATIONAL, protocols121IID, Timeouts.DEVICE_READ_TIMEOUT,
107                     Timeouts.DEVICE_READ_TIMEOUT_UNIT);
108                 if (!protocol121Object.isPresent()
109                         || (protocol121Object.get().augmentation(Protocols1.class) == null)) {
110                     LOG.warn("LLDP subtree is missing : isolated openroadm device");
111                     return new HashMap<>();
112                 }
113                 // get neighbor list
114                 NbrList nbr121List = protocol121Object.get().augmentation(Protocols1.class).getLldp().getNbrList();
115                 LOG.info("LLDP subtree is present. Device has {} neighbours", nbr121List.getIfName().size());
116                 // try to create rdm2rdm link
117                 return rdm2rdmLinkCreatev121(nodeId, tapiTopoUuid, nbr121List);
118             case 2:
119                 // 2.2.1
120                 InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device
121                     .container.org.openroadm.device.Protocols> protocols221IID =
122                         InstanceIdentifier.create(org.opendaylight.yang.gen.v1.http
123                             .org.openroadm.device.rev181019.org.openroadm.device.container.OrgOpenroadmDevice.class)
124                             .child(org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019
125                                 .org.openroadm.device.container.org.openroadm.device.Protocols.class);
126                 Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.org.openroadm.device
127                     .container.org.openroadm.device.Protocols> protocol221Object = this.deviceTransactionManager
128                     .getDataFromDevice(nodeId.getValue(), LogicalDatastoreType.OPERATIONAL, protocols221IID,
129                         Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
130                 if (!protocol221Object.isPresent() || (protocol221Object.get().augmentation(
131                         org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev181019.Protocols1.class) == null)) {
132                     LOG.warn("LLDP subtree is missing : isolated openroadm device");
133                     return new HashMap<>();
134                 }
135                 org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev181019.lldp.container.lldp.@Nullable NbrList
136                     nbr221List = protocol221Object.get().augmentation(org.opendaylight.yang.gen.v1.http
137                         .org.openroadm.lldp.rev181019.Protocols1.class).getLldp().getNbrList();
138                 LOG.info("LLDP subtree is present. Device has {} neighbours", nbr221List.getIfName().size());
139                 return rdm2rdmLinkCreatev221(nodeId, tapiTopoUuid, nbr221List);
140             case 3:
141                 // 7.1.0
142                 LOG.info("Not yet supported?");
143                 return new HashMap<>();
144             default:
145                 LOG.error("Unable to read LLDP data for unmanaged openroadm device version");
146                 return new HashMap<>();
147         }
148     }
149
150     private Map<LinkKey, Link> rdm2rdmLinkCreatev221(NodeId nodeId, Uuid tapiTopoUuid,
151             org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev181019.lldp.container.lldp.NbrList nbrList) {
152         Map<LinkKey, Link> linkMap = new HashMap<>();
153         for (org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev181019.lldp.container.lldp.nbr.list.IfName
154                 ifName : nbrList.nonnullIfName().values()) {
155             if (ifName.getRemoteSysName() == null) {
156                 LOG.warn("Tapi R2R Link LLDP subtree neighbour is empty for nodeId: {}, ifName: {}",
157                     nodeId.getValue(),ifName.getIfName());
158                 continue;
159             }
160             Optional<MountPoint> mps = this.deviceTransactionManager.getDeviceMountPoint(ifName.getRemoteSysName());
161             if (!mps.isPresent()) {
162                 LOG.warn("Tapi R2R Link Neighbouring nodeId: {} is not mounted yet", ifName.getRemoteSysName());
163                 // The controller raises a warning rather than an error because the first node to
164                 // mount cannot see its neighbors yet. The link will be detected when processing
165                 // the neighbor node.
166                 continue;
167             }
168             Link omsLink = createR2RTapiLink(nodeId, ifName.getIfName(), ifName.getRemoteSysName(),
169                 ifName.getRemotePortId(), tapiTopoUuid);
170             if (omsLink != null) {
171                 linkMap.put(omsLink.key(), omsLink);
172             } else {
173                 LOG.error("Link was not created");
174             }
175         }
176         return linkMap;
177     }
178
179     private Map<LinkKey, Link> rdm2rdmLinkCreatev121(NodeId nodeId, Uuid tapiTopoUuid, NbrList nbrList) {
180         Map<LinkKey, Link> linkMap = new HashMap<>();
181         for (IfName ifName : nbrList.nonnullIfName().values()) {
182             if (ifName.getRemoteSysName() == null) {
183                 LOG.warn("Tapi R2R Link LLDP subtree neighbour is empty for nodeId: {}, ifName: {}",
184                     nodeId.getValue(),ifName.getIfName());
185                 continue;
186             }
187             Optional<MountPoint> mps = this.deviceTransactionManager.getDeviceMountPoint(ifName
188                 .getRemoteSysName());
189             if (!mps.isPresent()) {
190                 LOG.warn("Tapi R2R Link Neighbouring nodeId: {} is not mounted yet", ifName.getRemoteSysName());
191                 // The controller raises a warning rather than an error because the first node to
192                 // mount cannot see its neighbors yet. The link will be detected when processing
193                 // the neighbor node.
194                 continue;
195             }
196             Link omsLink = createR2RTapiLink(nodeId, ifName.getIfName(), ifName.getRemoteSysName(),
197                 ifName.getRemotePortId(), tapiTopoUuid);
198             if (omsLink != null) {
199                 linkMap.put(omsLink.key(), omsLink);
200             } else {
201                 LOG.error("Link was not created");
202             }
203         }
204         return linkMap;
205     }
206
207     public Link createR2RTapiLink(NodeId nodeId, String interfaceName, String remoteSystemName,
208                                  String remoteInterfaceName, Uuid tapiTopoUuid) {
209         String srcTpTx = null;
210         String srcTpRx = null;
211         String destTpTx = null;
212         String destTpRx = null;
213         // Find which degree is associated with ethernet interface
214         Integer srcDegId = getDegFromInterface(nodeId, interfaceName);
215         if (srcDegId == null) {
216             LOG.error("Tapi R2R Link Couldnt find degree connected to Ethernet interface for nodeId: {}", nodeId);
217             return null;
218         }
219         // Check whether degree is Unidirectional or Bidirectional by counting
220         // number of
221         // circuit-packs under degree subtree
222         Direction sourceDirection = getDegreeDirection(srcDegId, nodeId);
223         if (Direction.NotApplicable == sourceDirection) {
224             LOG.error("Tapi R2R Link Couldnt find degree direction for nodeId: {} and degree: {}", nodeId, srcDegId);
225             return null;
226         } else if (Direction.Bidirectional == sourceDirection) {
227             srcTpTx = "DEG" + srcDegId + "-TTP-TXRX";
228             srcTpRx = "DEG" + srcDegId + "-TTP-TXRX";
229         } else {
230             srcTpTx = "DEG" + srcDegId + "-TTP-TX";
231             srcTpRx = "DEG" + srcDegId + "-TTP-RX";
232         }
233         LOG.debug("Tapi R2R Link SrcTPTx {}, SrcTPRx {}", srcTpTx, srcTpRx);
234         // Find degree for which Ethernet interface is created on other end
235         NodeId destNodeId = new NodeId(remoteSystemName);
236         Integer destDegId = getDegFromInterface(destNodeId, remoteInterfaceName);
237         if (destDegId == null) {
238             LOG.error("Tapi R2R Link Couldnt find degree connected to Ethernet interface for nodeId: {}", nodeId);
239             return null;
240         }
241         // Check whether degree is Unidirectional or Bidirectional by counting
242         // number of
243         // circuit-packs under degree subtree
244         Direction destinationDirection = getDegreeDirection(destDegId, destNodeId);
245         if (Direction.NotApplicable == destinationDirection) {
246             LOG.error("Tapi R2R Link Couldnt find degree direction for nodeId: {} and degree: {}",
247                 destNodeId, destDegId);
248             return null;
249         } else if (Direction.Bidirectional == destinationDirection) {
250             destTpTx = "DEG" + destDegId + "-TTP-TXRX";
251             destTpRx = "DEG" + destDegId + "-TTP-TXRX";
252         } else {
253             destTpTx = "DEG" + destDegId + "-TTP-TX";
254             destTpRx = "DEG" + destDegId + "-TTP-RX";
255         }
256         // Todo -> only handling for the bidirectional case. I assume all tps are of the type bidirectional
257         LOG.debug("Tapi R2R Link DstTPTx {}, DstTPRx {}", destTpTx, srcTpRx);
258
259         // Create OMS Tapi Link
260         LOG.info("Tapi R2R Link Found a neighbor SrcNodeId: {} , SrcDegId: {} , SrcTPId: {}, DestNodeId:{} , "
261             + "DestDegId: {}, DestTPId: {}", nodeId.getValue(), srcDegId, srcTpTx, destNodeId, destDegId, destTpRx);
262         Link omsLink = createTapiLink(nodeId.getValue(), srcTpTx, destNodeId.getValue(), destTpRx, tapiTopoUuid);
263         LOG.info("Tapi R2R Link OMS link created = {}", omsLink);
264         return omsLink;
265     }
266
267     private Link createTapiLink(String sourceNode, String sourceTp, String destNode, String destTp, Uuid tapiTopoUuid) {
268         Map<NodeEdgePointKey, NodeEdgePoint> nepList = new HashMap<>();
269         Uuid sourceUuidNode = new Uuid(UUID.nameUUIDFromBytes((String.join("+", sourceNode,
270             PHTNC_MEDIA)).getBytes(Charset.forName("UTF-8"))).toString());
271         Uuid sourceUuidTp = new Uuid(UUID.nameUUIDFromBytes((String.join("+", sourceNode, PHTNC_MEDIA, sourceTp))
272             .getBytes(Charset.forName("UTF-8"))).toString());
273         Uuid destUuidNode = new Uuid(UUID.nameUUIDFromBytes((String.join("+", destNode,
274             PHTNC_MEDIA)).getBytes(Charset.forName("UTF-8"))).toString());
275         Uuid destUuidTp = new Uuid(UUID.nameUUIDFromBytes((String.join("+", destNode, PHTNC_MEDIA, destTp))
276             .getBytes(Charset.forName("UTF-8"))).toString());
277         NodeEdgePoint sourceNep = new NodeEdgePointBuilder()
278             .setTopologyUuid(tapiTopoUuid)
279             .setNodeUuid(sourceUuidNode)
280             .setNodeEdgePointUuid(sourceUuidTp)
281             .build();
282         nepList.put(sourceNep.key(), sourceNep);
283         NodeEdgePoint destNep = new NodeEdgePointBuilder()
284             .setTopologyUuid(tapiTopoUuid)
285             .setNodeUuid(destUuidNode)
286             .setNodeEdgePointUuid(destUuidTp)
287             .build();
288         nepList.put(destNep.key(), destNep);
289         OperationalState sourceOperState = getOperState(tapiTopoUuid, sourceUuidTp, sourceUuidNode);
290         OperationalState destOperState = getOperState(tapiTopoUuid, destUuidTp, destUuidNode);
291         if (sourceOperState == null || destOperState == null) {
292             LOG.error("No link can be created, as the operational state was not found in the TAPI topology");
293             return null;
294         }
295         AdministrativeState sourceAdminState = getAdminState(tapiTopoUuid, sourceUuidTp, sourceUuidNode);
296         AdministrativeState destAdminState = getAdminState(tapiTopoUuid, destUuidTp, destUuidNode);
297         if (sourceAdminState == null || destAdminState == null) {
298             LOG.error("No link can be created, as the administrative state was not found in the TAPI topology");
299             return null;
300         }
301         OperationalState operState = (OperationalState.ENABLED.equals(sourceOperState)
302                 && OperationalState.ENABLED.equals(destOperState))
303                 ? OperationalState.ENABLED : OperationalState.DISABLED;
304         AdministrativeState adminState = (AdministrativeState.UNLOCKED.equals(sourceAdminState)
305                 && AdministrativeState.UNLOCKED.equals(destAdminState))
306                 ? AdministrativeState.UNLOCKED : AdministrativeState.LOCKED;
307         String linkNameValue = String.join("-", sourceNode, sourceTp.split("-")[0], sourceTp)
308             + "to" + String.join("-", destNode, destTp.split("-")[0], destTp);
309         Name linkName = new NameBuilder().setValueName("OMS link name")
310             .setValue(linkNameValue)
311             .build();
312         CostCharacteristic costCharacteristic = new CostCharacteristicBuilder()
313             .setCostAlgorithm("Restricted Shortest Path - RSP")
314             .setCostName("HOP_COUNT")
315             .setCostValue("12345678")
316             .build();
317         LatencyCharacteristic latencyCharacteristic = new LatencyCharacteristicBuilder()
318             .setFixedLatencyCharacteristic("12345678")
319             .setQueingLatencyCharacteristic("12345678")
320             .setJitterCharacteristic("12345678")
321             .setWanderCharacteristic("12345678")
322             .setTrafficPropertyName("FIXED_LATENCY")
323             .build();
324         RiskCharacteristic riskCharacteristic = new RiskCharacteristicBuilder()
325             .setRiskCharacteristicName("risk characteristic")
326             .setRiskIdentifierList(List.of("risk identifier1", "risk identifier2"))
327             .build();
328         ValidationMechanism validationMechanism = new ValidationMechanismBuilder()
329             .setValidationMechanism("validation mechanism")
330             .setValidationRobustness("validation robustness")
331             .setLayerProtocolAdjacencyValidated("layer protocol adjacency")
332             .build();
333         return new LinkBuilder()
334             .setUuid(new Uuid(
335                 UUID.nameUUIDFromBytes(linkNameValue.getBytes(Charset.forName("UTF-8")))
336                     .toString()))
337             .setName(Map.of(linkName.key(), linkName))
338             .setLayerProtocolName(List.of(LayerProtocolName.PHOTONICMEDIA))
339             .setTransitionedLayerProtocolName(new ArrayList<>())
340             .setNodeEdgePoint(nepList)
341             .setDirection(ForwardingDirection.BIDIRECTIONAL)
342             .setResilienceType(new ResilienceTypeBuilder().setProtectionType(ProtectionType.NOPROTECTON)
343                 .setRestorationPolicy(RestorationPolicy.NA)
344                 .build())
345             .setAdministrativeState(adminState)
346             .setOperationalState(operState)
347             .setLifecycleState(LifecycleState.INSTALLED)
348             .setTotalPotentialCapacity(new TotalPotentialCapacityBuilder().setTotalSize(
349                 new TotalSizeBuilder().setUnit(CapacityUnit.GBPS)
350                     .setValue(Uint64.valueOf(100)).build()).build())
351             .setAvailableCapacity(new AvailableCapacityBuilder().setTotalSize(
352                 new TotalSizeBuilder().setUnit(CapacityUnit.MBPS)
353                     .setValue(Uint64.valueOf(100)).build())
354                 .build())
355             .setCostCharacteristic(Map.of(costCharacteristic.key(), costCharacteristic))
356             .setLatencyCharacteristic(Map.of(latencyCharacteristic.key(), latencyCharacteristic))
357             .setRiskCharacteristic(Map.of(riskCharacteristic.key(), riskCharacteristic))
358             .setErrorCharacteristic("error")
359             .setLossCharacteristic("loss")
360             .setRepeatDeliveryCharacteristic("repeat delivery")
361             .setDeliveryOrderCharacteristic("delivery order")
362             .setUnavailableTimeCharacteristic("unavailable time")
363             .setServerIntegrityProcessCharacteristic("server integrity process")
364             .setValidationMechanism(Map.of(validationMechanism.key(), validationMechanism))
365             .build();
366     }
367
368     private Integer getDegFromInterface(NodeId nodeId, String interfaceName) {
369         InstanceIdentifier<Nodes> nodesIID = InstanceIdentifier.builder(Network.class)
370             .child(Nodes.class, new NodesKey(nodeId.getValue())).build();
371         try {
372
373             Optional<Nodes> nodesObject = this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,
374                 nodesIID).get();
375             if (nodesObject.isEmpty() || (nodesObject.get().getCpToDegree() == null)) {
376                 LOG.warn("Could not find mapping for Interface {} for nodeId {}", interfaceName,
377                     nodeId.getValue());
378                 return null;
379             }
380             Collection<CpToDegree> cpToDeg = nodesObject.get().nonnullCpToDegree().values();
381             Stream<CpToDegree> cpToDegStream = cpToDeg.stream().filter(cp -> cp.getInterfaceName() != null)
382                 .filter(cp -> cp.getInterfaceName().equals(interfaceName));
383             if (cpToDegStream != null) {
384                 @SuppressWarnings("unchecked") Optional<CpToDegree> firstCpToDegree = cpToDegStream.findFirst();
385                 if (firstCpToDegree.isEmpty() || (firstCpToDegree == null)) {
386                     LOG.debug("Not found so returning nothing");
387                     return null;
388                 }
389                 LOG.debug("Found and returning {}",firstCpToDegree.get().getDegreeNumber().intValue());
390                 return firstCpToDegree.get().getDegreeNumber().intValue();
391             } else {
392                 LOG.warn("CircuitPack stream couldnt find anything for nodeId: {} and interfaceName: {}",
393                     nodeId.getValue(),interfaceName);
394             }
395         } catch (InterruptedException | ExecutionException ex) {
396             LOG.error("Unable to read mapping for Interface : {} for nodeId {}", interfaceName, nodeId, ex);
397         }
398         return null;
399     }
400
401     public Direction getDegreeDirection(Integer degreeCounter, NodeId nodeId) {
402         InstanceIdentifier<Nodes> nodesIID = InstanceIdentifier.builder(Network.class)
403             .child(Nodes.class, new NodesKey(nodeId.getValue())).build();
404         try {
405             Optional<Nodes> nodesObject = this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,
406                 nodesIID).get();
407             if (nodesObject.isPresent() && (nodesObject.get().getMapping() != null)) {
408                 Collection<Mapping> mappingList = nodesObject.get().nonnullMapping().values();
409                 mappingList = mappingList.stream().filter(mp -> mp.getLogicalConnectionPoint().contains("DEG"
410                     + degreeCounter)).collect(Collectors.toList());
411                 if (mappingList.size() == 1) {
412                     return Direction.Bidirectional;
413                 } else if (mappingList.size() > 1) {
414                     return Direction.Tx;
415                 }
416             }
417         } catch (InterruptedException | ExecutionException e) {
418             LOG.error("Failed getting Mapping data from portMapping",e);
419         }
420         return Direction.NotApplicable;
421     }
422
423     private OperationalState getOperState(Uuid tapiTopoUuid, Uuid nepUuid, Uuid nodeUuid) {
424         InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
425                 .augmentation(Context1.class).child(TopologyContext.class)
426                 .child(Topology.class, new TopologyKey(tapiTopoUuid)).child(Node.class, new NodeKey(nodeUuid))
427                 .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid))
428                 .build();
429         try {
430             Optional<OwnedNodeEdgePoint> optionalOnep = this.networkTransactionService.read(
431                 LogicalDatastoreType.OPERATIONAL, onepIID).get();
432             if (!optionalOnep.isPresent()) {
433                 LOG.error("No NEP {} object present in datastore", nepUuid);
434                 return null;
435             }
436             return optionalOnep.get().getOperationalState();
437         } catch (InterruptedException | ExecutionException e) {
438             LOG.error("Failed getting Mapping data from portMapping",e);
439             return null;
440         }
441     }
442
443     private AdministrativeState getAdminState(Uuid tapiTopoUuid, Uuid nepUuid, Uuid nodeUuid) {
444         InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
445                 .augmentation(Context1.class).child(TopologyContext.class)
446                 .child(Topology.class, new TopologyKey(tapiTopoUuid)).child(Node.class, new NodeKey(nodeUuid))
447                 .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid))
448                 .build();
449         try {
450             Optional<OwnedNodeEdgePoint> optionalOnep = this.networkTransactionService.read(
451                 LogicalDatastoreType.OPERATIONAL, onepIID).get();
452             if (!optionalOnep.isPresent()) {
453                 LOG.error("No NEP {} object present in datastore", nepUuid);
454                 return null;
455             }
456             return optionalOnep.get().getAdministrativeState();
457         } catch (InterruptedException | ExecutionException e) {
458             LOG.error("Failed getting Mapping data from portMapping",e);
459             return null;
460         }
461     }
462 }