66e5460d1936f8150104e17c68b8ae29da813212
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / service / NetworkModelServiceImpl.java
1 /*
2  * Copyright © 2016 AT&T and others.  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.networkmodel.service;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Optional;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.TimeUnit;
18 import java.util.concurrent.TimeoutException;
19 import java.util.stream.Collectors;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.transportpce.common.InstanceIdentifiers;
24 import org.opendaylight.transportpce.common.NetworkUtils;
25 import org.opendaylight.transportpce.common.mapping.PortMapping;
26 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
27 import org.opendaylight.transportpce.networkmodel.R2RLinkDiscovery;
28 import org.opendaylight.transportpce.networkmodel.dto.TopologyShard;
29 import org.opendaylight.transportpce.networkmodel.util.ClliNetwork;
30 import org.opendaylight.transportpce.networkmodel.util.LinkIdUtil;
31 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmNetwork;
32 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmOtnTopology;
33 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology;
34 import org.opendaylight.transportpce.networkmodel.util.TopologyUtils;
35 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.OpenroadmNodeVersion;
36 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.mapping.Mapping;
37 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.network.nodes.NodeInfo;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.Link1;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.TerminationPoint1;
41 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev201019.OtnLinkType;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeKey;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkKey;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.termination.point.SupportingTerminationPoint;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 import org.opendaylight.yangtools.yang.common.Uint32;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 public class NetworkModelServiceImpl implements NetworkModelService {
65
66     private static final Logger LOG = LoggerFactory.getLogger(NetworkModelServiceImpl.class);
67
68     private NetworkTransactionService networkTransactionService;
69     private final R2RLinkDiscovery linkDiscovery;
70     private final PortMapping portMapping;
71     private Map<String, TopologyShard> topologyShardMountedDevice;
72     private Map<String, TopologyShard> otnTopologyShardMountedDevice;
73
74     public NetworkModelServiceImpl(final NetworkTransactionService networkTransactionService,
75             final R2RLinkDiscovery linkDiscovery, PortMapping portMapping,
76             final NotificationPublishService notificationPublishService) {
77
78         this.networkTransactionService = networkTransactionService;
79         this.linkDiscovery = linkDiscovery;
80         this.portMapping = portMapping;
81         this.topologyShardMountedDevice = new HashMap<String, TopologyShard>();
82         this.otnTopologyShardMountedDevice = new HashMap<String, TopologyShard>();
83     }
84
85     public void init() {
86         LOG.info("init ...");
87     }
88
89     public void close() {
90     }
91
92     @Override
93     public void createOpenRoadmNode(String nodeId, String openRoadmVersion) {
94         try {
95             LOG.info("createOpenROADMNode: {} ", nodeId);
96
97             if (!portMapping.createMappingData(nodeId, openRoadmVersion)) {
98                 LOG.warn("Could not generate port mapping for {} skipping network model creation", nodeId);
99                 return;
100             }
101             NodeInfo nodeInfo = portMapping.getNode(nodeId).getNodeInfo();
102             // node creation in clli-network
103             Node clliNode = ClliNetwork.createNode(nodeId, nodeInfo);
104             InstanceIdentifier<Node> iiClliNode = InstanceIdentifier.builder(Networks.class)
105                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID)))
106                 .child(Node.class, clliNode.key())
107                 .build();
108             LOG.info("creating node in {}", NetworkUtils.CLLI_NETWORK_ID);
109             networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiClliNode, clliNode);
110
111             // node creation in openroadm-network
112             Node openroadmNetworkNode = OpenRoadmNetwork.createNode(nodeId, nodeInfo);
113             InstanceIdentifier<Node> iiopenroadmNetworkNode = InstanceIdentifier.builder(Networks.class)
114                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID)))
115                 .child(Node.class, openroadmNetworkNode.key())
116                 .build();
117             LOG.info("creating node in {}", NetworkUtils.UNDERLAY_NETWORK_ID);
118             networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiopenroadmNetworkNode,
119                 openroadmNetworkNode);
120
121             // nodes/links creation in openroadm-topology
122             TopologyShard topologyShard = OpenRoadmTopology.createTopologyShard(portMapping.getNode(nodeId));
123             if (topologyShard != null) {
124                 this.topologyShardMountedDevice.put(nodeId, topologyShard);
125                 for (Node openRoadmTopologyNode : topologyShard.getNodes()) {
126                     LOG.info("creating node {} in {}", openRoadmTopologyNode.getNodeId().getValue(),
127                         NetworkUtils.OVERLAY_NETWORK_ID);
128                     InstanceIdentifier<Node> iiOpenRoadmTopologyNode = InstanceIdentifier.builder(Networks.class)
129                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
130                         .child(Node.class, openRoadmTopologyNode.key())
131                         .build();
132                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode,
133                         openRoadmTopologyNode);
134                 }
135                 for (Link openRoadmTopologyLink : topologyShard.getLinks()) {
136                     LOG.info("creating link {} in {}", openRoadmTopologyLink.getLinkId().getValue(),
137                         NetworkUtils.OVERLAY_NETWORK_ID);
138                     InstanceIdentifier<Link> iiOpenRoadmTopologyLink = InstanceIdentifier.builder(Networks.class)
139                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
140                         .augmentation(Network1.class)
141                         .child(Link.class, openRoadmTopologyLink.key())
142                         .build();
143                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink,
144                         openRoadmTopologyLink);
145                 }
146             } else {
147                 LOG.error("Unable to create openroadm-topology shard for node {}!", nodeId);
148             }
149             // nodes/links creation in otn-topology
150             if (nodeInfo.getNodeType().getIntValue() == 2 && (nodeInfo.getOpenroadmVersion().getIntValue() != 1)) {
151                 createOpenRoadmOtnNode(nodeId);
152             }
153             networkTransactionService.commit().get();
154             // neighbour links through LLDP
155             if (nodeInfo.getNodeType().getIntValue() == 1) {
156                 this.linkDiscovery.readLLDP(new NodeId(nodeId), openRoadmVersion);
157             }
158             LOG.info("all nodes and links created");
159         } catch (InterruptedException | ExecutionException e) {
160             LOG.error("ERROR: ", e);
161         }
162     }
163
164     @Override
165     public void setOpenRoadmNodeStatus(String nodeId, NetconfNodeConnectionStatus.ConnectionStatus connectionStatus) {
166         LOG.info("setOpenROADMNodeStatus: {} {}", nodeId, connectionStatus.name());
167         /*
168           TODO: set connection status of the device in model,
169           TODO: so we don't need to keep it in memory (Set<String> currentMountedDevice)
170           TODO: unfortunately there is no connection status OpenROADM in network models
171           TODO: waiting for new model version
172          */
173     }
174
175     /*
176      @see org.opendaylight.transportpce.networkmodel.service.NetworkModelService# deleteOpenROADMnode(java.lang.String)
177      */
178
179     @Override
180     public void deleteOpenRoadmnode(String nodeId) {
181         try {
182             NodeKey nodeIdKey = new NodeKey(new NodeId(nodeId));
183
184             LOG.info("deleting node in {}", NetworkUtils.UNDERLAY_NETWORK_ID);
185             InstanceIdentifier<Node> iiopenroadmNetworkNode = InstanceIdentifier.builder(Networks.class)
186                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID)))
187                 .child(Node.class, nodeIdKey)
188                 .build();
189             this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiopenroadmNetworkNode);
190
191             TopologyShard topologyShard = this.topologyShardMountedDevice.get(nodeId);
192             if (topologyShard != null) {
193                 for (Node openRoadmTopologyNode : topologyShard.getNodes()) {
194                     LOG.info("deleting node {} in {}", openRoadmTopologyNode.getNodeId().getValue(),
195                         NetworkUtils.OVERLAY_NETWORK_ID);
196                     InstanceIdentifier<Node> iiOpenRoadmTopologyNode = InstanceIdentifier.builder(Networks.class)
197                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
198                         .child(Node.class, openRoadmTopologyNode.key())
199                         .build();
200                     this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode);
201                 }
202                 for (Link openRoadmTopologyLink : topologyShard.getLinks()) {
203                     LOG.info("deleting link {} in {}", openRoadmTopologyLink.getLinkId().getValue(),
204                         NetworkUtils.OVERLAY_NETWORK_ID);
205                     InstanceIdentifier<Link> iiOpenRoadmTopologyLink = InstanceIdentifier.builder(Networks.class)
206                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
207                         .augmentation(Network1.class)
208                         .child(Link.class, openRoadmTopologyLink.key())
209                         .build();
210                     this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink);
211                 }
212             } else {
213                 LOG.warn("TopologyShard for node '{}' is not present", nodeId);
214             }
215             @Nullable
216             OpenroadmNodeVersion deviceVersion = this.portMapping.getNode(nodeId).getNodeInfo().getOpenroadmVersion();
217             @Nullable
218             NodeTypes nodeType = this.portMapping.getNode(nodeId).getNodeInfo().getNodeType();
219             if (nodeType.getIntValue() == 2 && deviceVersion.getIntValue() != 1) {
220                 TopologyShard otnTopologyShard = this.otnTopologyShardMountedDevice.get(nodeId);
221                 if (otnTopologyShard != null) {
222                     LOG.info("suppression de otnTopologyShard = {}", otnTopologyShard.toString());
223                     for (Node otnTopologyNode : otnTopologyShard.getNodes()) {
224                         LOG.info("deleting node {} in {}", otnTopologyNode.getNodeId().getValue(),
225                             NetworkUtils.OTN_NETWORK_ID);
226                         InstanceIdentifier<Node> iiotnTopologyNode = InstanceIdentifier.builder(Networks.class)
227                             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
228                             .child(Node.class, otnTopologyNode.key())
229                             .build();
230                         this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiotnTopologyNode);
231                     }
232                     for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
233                         LOG.info("deleting link {} in {}", otnTopologyLink.getLinkId().getValue(),
234                             NetworkUtils.OTN_NETWORK_ID);
235                         InstanceIdentifier<Link> iiotnTopologyLink = InstanceIdentifier.builder(Networks.class)
236                             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
237                             .augmentation(Network1.class)
238                             .child(Link.class, otnTopologyLink.key())
239                             .build();
240                         this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiotnTopologyLink);
241                     }
242                 }
243             }
244
245             LOG.info("deleteOpenROADMnode: {} version {}", nodeId, deviceVersion.getName());
246             this.portMapping.deleteMappingData(nodeId);
247
248             this.networkTransactionService.commit().get(1, TimeUnit.SECONDS);
249             LOG.info("all nodes and links deleted ! ");
250         } catch (InterruptedException | ExecutionException | TimeoutException e) {
251             LOG.error("Error when trying to delete node : {}", nodeId, e);
252         }
253     }
254
255     @Override
256     public void updateOpenRoadmTopologies(String nodeId, Mapping mapping) {
257         LOG.info("update OpenRoadm topologies after change update from: {} ", nodeId);
258         Network openroadmTopology = null;
259         Network otnTopology = null;
260         Map<LinkKey, Link> openroadmTopologyLinks = null;
261         Map<LinkKey, Link> otnTopologyLinks = null;
262         try {
263             openroadmTopology = this.networkTransactionService
264                 .read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifiers.OVERLAY_NETWORK_II)
265                 .get().get();
266             if (openroadmTopology.augmentation(Network1.class) != null) {
267                 openroadmTopologyLinks = openroadmTopology.augmentation(Network1.class).getLink();
268             }
269             otnTopology = this.networkTransactionService
270                 .read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifiers.OTN_NETWORK_II)
271                 .get().get();
272             if (otnTopology.augmentation(Network1.class) != null) {
273                 otnTopologyLinks = otnTopology.augmentation(Network1.class).getLink();
274             }
275         } catch (InterruptedException | ExecutionException e) {
276             LOG.error("Error when trying to update node : {}", nodeId, e);
277         }
278         if (openroadmTopology == null || otnTopology == null) {
279             LOG.warn("Error getting topologies from datastore");
280             return;
281         }
282         String abstractNodeid = String.join("-", nodeId, mapping.getLogicalConnectionPoint().split("-")[0]);
283         // nodes/links update in openroadm-topology
284         if (openroadmTopology.getNode() != null) {
285             TopologyShard topologyShard = TopologyUtils.updateTopologyShard(abstractNodeid, mapping,
286                 openroadmTopology.getNode(), openroadmTopologyLinks);
287             if (topologyShard.getLinks() != null) {
288                 for (Link link : topologyShard.getLinks()) {
289                     LOG.info("updating links {} in {}", link.getLinkId().getValue(),
290                         NetworkUtils.OVERLAY_NETWORK_ID);
291                     InstanceIdentifier<Link> iiTopologyLink = InstanceIdentifier.builder(Networks.class)
292                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
293                         .augmentation(Network1.class)
294                         .child(Link.class, link.key())
295                         .build();
296                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyLink, link);
297                 }
298             }
299             if (topologyShard.getTps() != null) {
300                 for (TerminationPoint tp : topologyShard.getTps()) {
301                     LOG.info("updating TP {} in openroadm-topology", tp.getTpId().getValue());
302                     InstanceIdentifier<TerminationPoint> iiTopologyTp = InstanceIdentifier.builder(Networks.class)
303                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
304                         .child(Node.class, new NodeKey(new NodeId(abstractNodeid)))
305                         .augmentation(Node1.class)
306                         .child(TerminationPoint.class, new TerminationPointKey(tp.getTpId()))
307                         .build();
308                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyTp, tp);
309                 }
310             }
311         }
312         // nodes/links update in otn-topology
313         if (otnTopology.getNode() != null
314             && otnTopology.getNode().containsKey(new NodeKey(new NodeId(abstractNodeid)))) {
315             TopologyShard otnShard = TopologyUtils.updateTopologyShard(abstractNodeid, mapping,
316                 otnTopology.getNode(), otnTopologyLinks);
317             if (otnShard.getLinks() != null) {
318                 for (Link link : otnShard.getLinks()) {
319                     LOG.info("updating links {} in {}", link.getLinkId().getValue(),
320                         NetworkUtils.OVERLAY_NETWORK_ID);
321                     InstanceIdentifier<Link> iiTopologyLink = InstanceIdentifier.builder(Networks.class)
322                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
323                         .augmentation(Network1.class)
324                         .child(Link.class, link.key())
325                         .build();
326                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyLink, link);
327                 }
328             }
329             if (otnShard.getTps() != null) {
330                 for (TerminationPoint tp : otnShard.getTps()) {
331                     LOG.info("updating TP {} in otn-topology", tp.getTpId().getValue());
332                     InstanceIdentifier<TerminationPoint> iiTopologyTp = InstanceIdentifier.builder(Networks.class)
333                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
334                         .child(Node.class, new NodeKey(new NodeId(abstractNodeid)))
335                         .augmentation(Node1.class)
336                         .child(TerminationPoint.class, new TerminationPointKey(tp.getTpId()))
337                         .build();
338                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyTp, tp);
339                 }
340             }
341         }
342         // commit datastore updates
343         try {
344             networkTransactionService.commit().get();
345         } catch (InterruptedException | ExecutionException e) {
346             LOG.error("Error updating openroadm-topology", e);
347         }
348     }
349
350     @Override
351     public void createOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ, OtnLinkType linkType) {
352         TopologyShard otnTopologyShard;
353         switch (linkType) {
354             case OTU4:
355                 otnTopologyShard = OpenRoadmOtnTopology.createOtnLinks(nodeA, tpA, nodeZ, tpZ, linkType);
356                 break;
357             case ODTU4:
358                 String nodeTopoA = new StringBuilder(nodeA).append("-").append(tpA.split("-")[0]).toString();
359                 String nodeTopoZ = new StringBuilder(nodeZ).append("-").append(tpZ.split("-")[0]).toString();
360                 List<LinkId> linkIdList = new ArrayList<>();
361                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "OTU4"));
362                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "OTU4"));
363                 List<Link> supportedOtu4links = getOtnLinks(linkIdList);
364                 List<TerminationPoint> tps = getOtnNodeTps(nodeTopoA, tpA, nodeTopoZ, tpZ);
365
366                 otnTopologyShard = OpenRoadmOtnTopology.createOtnLinks(supportedOtu4links, tps);
367                 break;
368             default:
369                 LOG.error("unknown otn link type {}", linkType);
370                 otnTopologyShard = new TopologyShard(null, null);
371         }
372         if (otnTopologyShard.getLinks() != null) {
373             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
374                 LOG.info("creating and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
375                     NetworkUtils.OVERLAY_NETWORK_ID);
376                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
377                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
378                     .augmentation(Network1.class)
379                     .child(Link.class, otnTopologyLink.key())
380                     .build();
381                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
382             }
383         }
384         if (otnTopologyShard.getTps() != null) {
385             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
386                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
387                 List<SupportingTerminationPoint> supportingTerminationPoint =
388                     new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
389                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
390                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
391                     .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
392                     .augmentation(Node1.class)
393                     .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
394                     .build();
395                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
396             }
397         }
398         try {
399             networkTransactionService.commit().get();
400         } catch (InterruptedException | ExecutionException e) {
401             LOG.error("Error adding OTN links in otn-topology", e);
402         }
403         LOG.info("OTN links created");
404     }
405
406     @Override
407     public void deleteOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ, OtnLinkType linkType) {
408         TopologyShard otnTopologyShard;
409         String nodeTopoA = new StringBuilder(nodeA).append("-").append(tpA.split("-")[0]).toString();
410         String nodeTopoZ = new StringBuilder(nodeZ).append("-").append(tpZ.split("-")[0]).toString();
411         List<Link> otu4Links;
412         List<LinkId> linkIdList = new ArrayList<>();
413         switch (linkType) {
414             case OTU4:
415                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "OTU4"));
416                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "OTU4"));
417                 otu4Links = getOtnLinks(linkIdList);
418                 if (checkLinks(otu4Links)) {
419                     deleteLinks(otu4Links);
420                 } else {
421                     LOG.error("Error deleting OTU4 links");
422                 }
423                 otnTopologyShard = new TopologyShard(null, null);
424                 break;
425             case ODTU4:
426                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "ODU4"));
427                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "ODU4"));
428                 List<Link> odu4Links = getOtnLinks(linkIdList);
429                 List<TerminationPoint> tps = getOtnNodeTps(nodeTopoA, tpA, nodeTopoZ, tpZ);
430                 if (checkLinks(odu4Links) && checkTerminationPoints(tps)) {
431                     deleteLinks(odu4Links);
432                     linkIdList.clear();
433                     linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "OTU4"));
434                     linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "OTU4"));
435                     otu4Links = getOtnLinks(linkIdList);
436                     otnTopologyShard = OpenRoadmOtnTopology.deleteOtnLinks(otu4Links, tps);
437                 } else {
438                     LOG.error("Error deleting ODU4 links");
439                     otnTopologyShard = new TopologyShard(null, null);
440                 }
441                 break;
442             default:
443                 LOG.error("unknown otn link type {}", linkType);
444                 otnTopologyShard = new TopologyShard(null, null);
445         }
446         if (otnTopologyShard.getLinks() != null) {
447             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
448                 LOG.info("deleting and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
449                     NetworkUtils.OVERLAY_NETWORK_ID);
450                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
451                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
452                     .augmentation(Network1.class)
453                     .child(Link.class, otnTopologyLink.key())
454                     .build();
455                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
456             }
457         }
458         if (otnTopologyShard.getTps() != null) {
459             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
460                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
461                 List<SupportingTerminationPoint> supportingTerminationPoint =
462                     new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
463                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
464                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
465                     .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
466                     .augmentation(Node1.class)
467                     .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
468                     .build();
469                 networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
470             }
471         }
472         try {
473             networkTransactionService.commit().get();
474         } catch (InterruptedException | ExecutionException e) {
475             LOG.error("Error deleting OTN links in otn-topology", e);
476         }
477         LOG.info("OTN links deletion terminated");
478     }
479
480     @Override
481     public void updateOtnLinks(List<String> nodeTps, String serviceRate, Short tribPortNb, Short tribSoltNb,
482             boolean isDeletion) {
483         List<Link> supportedOdu4Links = getSupportingOdu4Links(nodeTps);
484         List<TerminationPoint> tps = getOtnNodeTps(nodeTps);
485         TopologyShard otnTopologyShard;
486         otnTopologyShard = OpenRoadmOtnTopology.updateOtnLinks(supportedOdu4Links, tps, serviceRate, tribPortNb,
487             tribSoltNb, isDeletion);
488         if (otnTopologyShard.getLinks() != null) {
489             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
490                 LOG.info("creating and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
491                     NetworkUtils.OVERLAY_NETWORK_ID);
492                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
493                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
494                     .augmentation(Network1.class)
495                     .child(Link.class, new LinkKey(new LinkId(otnTopologyLink.getLinkId().getValue())))
496                     .build();
497                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
498             }
499         }
500         if (otnTopologyShard.getTps() != null) {
501             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
502                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
503                 List<SupportingTerminationPoint> supportingTerminationPoint =
504                     new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
505                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
506                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
507                     .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
508                     .augmentation(Node1.class)
509                     .child(TerminationPoint.class, new TerminationPointKey(new TpId(otnTopologyTp.getTpId()
510                         .getValue())))
511                     .build();
512                 if (isDeletion) {
513                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
514                 } else {
515                     networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
516                 }
517             }
518         }
519         try {
520             networkTransactionService.commit().get();
521         } catch (InterruptedException | ExecutionException e) {
522             LOG.error("Error updating OTN links in otn-topology", e);
523         }
524     }
525
526     private List<Link> getOtnLinks(List<LinkId> linkIds) {
527         List<Link> links = new ArrayList<>();
528         for (LinkId linkId : linkIds) {
529             InstanceIdentifier<Link> iiLink = InstanceIdentifier.builder(Networks.class)
530                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
531                 .augmentation(Network1.class)
532                 .child(Link.class, new LinkKey(linkId))
533                 .build();
534             ListenableFuture<Optional<Link>> linkOptLf = networkTransactionService
535                 .read(LogicalDatastoreType.CONFIGURATION, iiLink);
536             if (linkOptLf.isDone()) {
537                 try {
538                     if (linkOptLf.get().isPresent()) {
539                         links.add(linkOptLf.get().get());
540                     }
541                 } catch (InterruptedException | ExecutionException e) {
542                     LOG.error("Error retreiving OTN links from otn-topology", e);
543                 }
544             } else {
545                 LOG.error("Error retreiving link {} from otn-topology", linkId.getValue());
546             }
547         }
548         return links;
549     }
550
551     private boolean checkLinks(List<Link> links) {
552         if (links.isEmpty()) {
553             return false;
554         }
555         for (Link link : links) {
556             if (link.augmentation(Link1.class) != null
557                     && !link.augmentation(Link1.class).getUsedBandwidth().equals(Uint32.valueOf(0))) {
558                 return false;
559             }
560         }
561         return true;
562     }
563
564     private boolean checkTerminationPoints(List<TerminationPoint> tps) {
565         if (tps.isEmpty()) {
566             return false;
567         }
568         for (TerminationPoint tp : tps) {
569             if (tp.augmentation(TerminationPoint1.class) != null && tp.augmentation(TerminationPoint1.class)
570                     .getXpdrTpPortConnectionAttributes().getTsPool() != null && tp.augmentation(TerminationPoint1.class)
571                     .getXpdrTpPortConnectionAttributes().getTsPool().size() != 80) {
572                 return false;
573             }
574         }
575         return true;
576     }
577
578     private List<TerminationPoint> getOtnNodeTps(String nodeTopoA, String tpA, String nodeTopoZ, String tpZ) {
579         List<TerminationPoint> tps = new ArrayList<>();
580         InstanceIdentifier<TerminationPoint> iiTpA = InstanceIdentifier.builder(Networks.class)
581             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
582             .child(Node.class, new NodeKey(new NodeId(nodeTopoA)))
583             .augmentation(Node1.class)
584             .child(TerminationPoint.class, new TerminationPointKey(new TpId(tpA)))
585             .build();
586         Optional<TerminationPoint> tpAOpt = Optional.empty();
587         InstanceIdentifier<TerminationPoint> iiTpZ = InstanceIdentifier.builder(Networks.class)
588             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
589             .child(Node.class, new NodeKey(new NodeId(nodeTopoZ)))
590             .augmentation(Node1.class)
591             .child(TerminationPoint.class, new TerminationPointKey(new TpId(tpZ)))
592             .build();
593         Optional<TerminationPoint> tpZOpt = Optional.empty();
594
595         if (networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).isDone()
596                 && networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).isDone()) {
597             try {
598                 tpAOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).get();
599                 tpZOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).get();
600             } catch (InterruptedException | ExecutionException e) {
601                 LOG.error("Error retreiving tp {} of node {} or tp {} from node {} from otn-topology", tpA, nodeTopoA,
602                     tpZ, nodeTopoZ, e);
603             }
604         } else {
605             LOG.error("error getting node termination points from the datastore");
606         }
607
608         if (tpAOpt.isPresent() && tpZOpt.isPresent()) {
609             tps.add(tpAOpt.get());
610             tps.add(tpZOpt.get());
611         }
612         return tps;
613     }
614
615     private List<TerminationPoint> getOtnNodeTps(List<String> nodeTopoTps) {
616         List<TerminationPoint> tps = new ArrayList<>();
617         for (String str : nodeTopoTps) {
618             String nodeId = str.split("--")[0];
619             String tp = str.split("--")[1];
620             InstanceIdentifier<TerminationPoint> iiTp = InstanceIdentifier.builder(Networks.class)
621                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
622                 .child(Node.class, new NodeKey(new NodeId(nodeId)))
623                 .augmentation(Node1.class)
624                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(tp)))
625                 .build();
626             Optional<TerminationPoint> tpOpt;
627             if (networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTp).isDone()) {
628                 try {
629                     tpOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTp).get();
630                     if (tpOpt.isPresent()) {
631                         tps.add(tpOpt.get());
632                     }
633                 } catch (InterruptedException | ExecutionException e) {
634                     LOG.error("Error retreiving tp {} of node {} from otn-topology", tp, nodeId, e);
635                 }
636             } else {
637                 LOG.error("error getting node termination points from the datastore");
638             }
639         }
640         if (tps.isEmpty()) {
641             LOG.warn("returning null");
642             return null;
643         } else {
644             LOG.info("returning tps = {}", tps.toString());
645             return tps;
646         }
647     }
648
649     private void deleteLinks(List<Link> links) {
650         for (Link otnTopologyLink : links) {
651             LOG.info("deleting link {} from {}", otnTopologyLink.getLinkId().getValue(),
652                 NetworkUtils.OVERLAY_NETWORK_ID);
653             InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
654                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
655                 .augmentation(Network1.class)
656                 .child(Link.class, otnTopologyLink.key())
657                 .build();
658             networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink);
659         }
660         try {
661             networkTransactionService.commit().get();
662         } catch (InterruptedException | ExecutionException e) {
663             LOG.error("Error deleting OTN links from otn-topology", e);
664         }
665     }
666
667     private List<Link> getSupportingOdu4Links(List<String> nodesTopoTps) {
668         InstanceIdentifier<Network1> iiOtnTopologyLinks = InstanceIdentifier.builder(Networks.class)
669             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
670             .augmentation(Network1.class)
671             .build();
672         ListenableFuture<Optional<Network1>> netw1Fl = networkTransactionService
673             .read(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLinks);
674         Optional<Network1> netw1Opt = Optional.empty();
675         if (netw1Fl.isDone()) {
676             try {
677                 netw1Opt = netw1Fl.get();
678             } catch (InterruptedException | ExecutionException e) {
679                 LOG.error("Error retreiving list of links from otn-topology", e);
680             }
681         }
682         List<Link> odu4links = null;
683         if (netw1Opt.isPresent() && netw1Opt.get().getLink() != null) {
684             odu4links = netw1Opt
685                 .get()
686                 .nonnullLink().values()
687                 .stream().filter(lk -> lk.getLinkId().getValue().startsWith("ODU4"))
688                 .collect(Collectors.toList());
689         }
690         List<Link> links = new ArrayList<>();
691         if (odu4links != null) {
692             for (String str : nodesTopoTps) {
693                 String[] nodeAndTp = str.split("--");
694                 if (nodeAndTp.length >= 2) {
695                     String nodeId = nodeAndTp[0];
696                     String tp = nodeAndTp[1];
697                     Link slink = odu4links.stream().filter(lk -> lk.getSource().getSourceNode().getValue()
698                         .equals(nodeId) && lk.getSource().getSourceTp().toString().equals(tp)).findFirst().get();
699                     if (!links.contains(slink)) {
700                         links.add(slink);
701                     }
702                     Link dlink = odu4links.stream().filter(lk -> lk.getDestination().getDestNode().getValue()
703                         .equals(nodeId) && lk.getDestination().getDestTp().toString().equals(tp)).findFirst().get();
704                     if (!links.contains(dlink)) {
705                         links.add(dlink);
706                     }
707                 }
708             }
709             LOG.debug("odu4links = {}", links.toString());
710             return links;
711         } else {
712             return null;
713         }
714     }
715
716     private void createOpenRoadmOtnNode(String nodeId) {
717         TopologyShard otnTopologyShard = OpenRoadmOtnTopology.createTopologyShard(portMapping.getNode(nodeId));
718         if (otnTopologyShard != null) {
719             this.otnTopologyShardMountedDevice.put(nodeId, otnTopologyShard);
720             for (Node otnTopologyNode : otnTopologyShard.getNodes()) {
721                 LOG.info("creating otn node {} in {}", otnTopologyNode.getNodeId().getValue(),
722                     NetworkUtils.OTN_NETWORK_ID);
723                 InstanceIdentifier<Node> iiOtnTopologyNode = InstanceIdentifier.builder(Networks.class)
724                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
725                     .child(Node.class, otnTopologyNode.key())
726                     .build();
727                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyNode, otnTopologyNode);
728             }
729             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
730                 LOG.info("creating otn link {} in {}", otnTopologyLink.getLinkId().getValue(),
731                     NetworkUtils.OVERLAY_NETWORK_ID);
732                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
733                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
734                     .augmentation(Network1.class)
735                     .child(Link.class, otnTopologyLink.key())
736                     .build();
737                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
738             }
739         } else {
740             LOG.error("Unable to create OTN topology shard for node {}!", nodeId);
741         }
742     }
743 }