2 * Copyright © 2016 AT&T and others. All rights reserved.
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
8 package org.opendaylight.transportpce.networkmodel.service;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
15 import java.util.Objects;
16 import java.util.Optional;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20 import java.util.stream.Collectors;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.transportpce.common.NetworkUtils;
24 import org.opendaylight.transportpce.common.mapping.PortMapping;
25 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
26 import org.opendaylight.transportpce.networkmodel.R2RLinkDiscovery;
27 import org.opendaylight.transportpce.networkmodel.dto.TopologyShard;
28 import org.opendaylight.transportpce.networkmodel.util.ClliNetwork;
29 import org.opendaylight.transportpce.networkmodel.util.LinkIdUtil;
30 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmNetwork;
31 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmOtnTopology;
32 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev201012.network.nodes.NodeInfo;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev201012.network.nodes.NodeInfo.OpenroadmVersion;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1Builder;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1Builder;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.Ports;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.Link1;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.TerminationPoint1;
44 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev201019.OtnLinkType;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeBuilder;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeKey;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1Builder;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkBuilder;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkKey;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointBuilder;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.termination.point.SupportingTerminationPoint;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
66 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
67 import org.opendaylight.yangtools.yang.common.Uint32;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
71 public class NetworkModelServiceImpl implements NetworkModelService {
73 private static final Logger LOG = LoggerFactory.getLogger(NetworkModelServiceImpl.class);
75 private NetworkTransactionService networkTransactionService;
76 private final R2RLinkDiscovery linkDiscovery;
77 private final PortMapping portMapping;
78 private Map<String, TopologyShard> topologyShardMountedDevice;
79 private Map<String, TopologyShard> otnTopologyShardMountedDevice;
80 // Maps that include topology component changed with its new operational state <id, state>
81 private Map<String, State> linksChanged;
82 private Map<String, State> terminationPointsChanged;
84 public NetworkModelServiceImpl(final NetworkTransactionService networkTransactionService,
85 final R2RLinkDiscovery linkDiscovery, PortMapping portMapping) {
87 this.networkTransactionService = networkTransactionService;
88 this.linkDiscovery = linkDiscovery;
89 this.portMapping = portMapping;
90 this.topologyShardMountedDevice = new HashMap<String, TopologyShard>();
91 this.otnTopologyShardMountedDevice = new HashMap<String, TopologyShard>();
92 this.linksChanged = new HashMap<String, State>();
93 this.terminationPointsChanged = new HashMap<String, State>();
100 public void close() {
104 public void createOpenRoadmNode(String nodeId, String openRoadmVersion) {
106 LOG.info("createOpenROADMNode: {} ", nodeId);
108 if (!portMapping.createMappingData(nodeId, openRoadmVersion)) {
109 LOG.warn("Could not generate port mapping for {} skipping network model creation", nodeId);
112 NodeInfo nodeInfo = portMapping.getNode(nodeId).getNodeInfo();
113 // node creation in clli-network
114 Node clliNode = ClliNetwork.createNode(nodeId, nodeInfo);
115 InstanceIdentifier<Node> iiClliNode = InstanceIdentifier.builder(Networks.class)
116 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID)))
117 .child(Node.class, clliNode.key())
119 LOG.info("creating node in {}", NetworkUtils.CLLI_NETWORK_ID);
120 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiClliNode, clliNode);
122 // node creation in openroadm-network
123 Node openroadmNetworkNode = OpenRoadmNetwork.createNode(nodeId, nodeInfo);
124 InstanceIdentifier<Node> iiopenroadmNetworkNode = InstanceIdentifier.builder(Networks.class)
125 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID)))
126 .child(Node.class, openroadmNetworkNode.key())
128 LOG.info("creating node in {}", NetworkUtils.UNDERLAY_NETWORK_ID);
129 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiopenroadmNetworkNode,
130 openroadmNetworkNode);
132 // nodes/links creation in openroadm-topology
133 TopologyShard topologyShard = OpenRoadmTopology.createTopologyShard(portMapping.getNode(nodeId));
134 if (topologyShard != null) {
135 this.topologyShardMountedDevice.put(nodeId, topologyShard);
136 for (Node openRoadmTopologyNode : topologyShard.getNodes()) {
137 LOG.info("creating node {} in {}", openRoadmTopologyNode.getNodeId().getValue(),
138 NetworkUtils.OVERLAY_NETWORK_ID);
139 InstanceIdentifier<Node> iiOpenRoadmTopologyNode = InstanceIdentifier.builder(Networks.class)
140 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
141 .child(Node.class, openRoadmTopologyNode.key())
143 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode,
144 openRoadmTopologyNode);
146 for (Link openRoadmTopologyLink : topologyShard.getLinks()) {
147 LOG.info("creating link {} in {}", openRoadmTopologyLink.getLinkId().getValue(),
148 NetworkUtils.OVERLAY_NETWORK_ID);
149 InstanceIdentifier<Link> iiOpenRoadmTopologyLink = InstanceIdentifier.builder(Networks.class)
150 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
151 .augmentation(Network1.class)
152 .child(Link.class, openRoadmTopologyLink.key())
154 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink,
155 openRoadmTopologyLink);
158 LOG.error("Unable to create openroadm-topology shard for node {}!", nodeId);
160 // nodes/links creation in otn-topology
161 if (nodeInfo.getNodeType().getIntValue() == 2 && (nodeInfo.getOpenroadmVersion().getIntValue() != 1)) {
162 createOpenRoadmOtnNode(nodeId);
164 networkTransactionService.commit().get();
165 // neighbour links through LLDP
166 if (nodeInfo.getNodeType().getIntValue() == 1) {
167 this.linkDiscovery.readLLDP(new NodeId(nodeId), openRoadmVersion);
169 LOG.info("all nodes and links created");
170 } catch (InterruptedException | ExecutionException e) {
171 LOG.error("ERROR: ", e);
176 public void setOpenRoadmNodeStatus(String nodeId, NetconfNodeConnectionStatus.ConnectionStatus connectionStatus) {
177 LOG.info("setOpenROADMNodeStatus: {} {}", nodeId, connectionStatus.name());
179 TODO: set connection status of the device in model,
180 TODO: so we don't need to keep it in memory (Set<String> currentMountedDevice)
181 TODO: unfortunately there is no connection status OpenROADM in network models
182 TODO: waiting for new model version
187 @see org.opendaylight.transportpce.networkmodel.service.NetworkModelService# deleteOpenROADMnode(java.lang.String)
191 public void deleteOpenRoadmnode(String nodeId) {
193 NodeKey nodeIdKey = new NodeKey(new NodeId(nodeId));
195 LOG.info("deleting node in {}", NetworkUtils.UNDERLAY_NETWORK_ID);
196 InstanceIdentifier<Node> iiopenroadmNetworkNode = InstanceIdentifier.builder(Networks.class)
197 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID)))
198 .child(Node.class, nodeIdKey)
200 this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiopenroadmNetworkNode);
202 TopologyShard topologyShard = this.topologyShardMountedDevice.get(nodeId);
203 if (topologyShard != null) {
204 for (Node openRoadmTopologyNode : topologyShard.getNodes()) {
205 LOG.info("deleting node {} in {}", openRoadmTopologyNode.getNodeId().getValue(),
206 NetworkUtils.OVERLAY_NETWORK_ID);
207 InstanceIdentifier<Node> iiOpenRoadmTopologyNode = InstanceIdentifier.builder(Networks.class)
208 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
209 .child(Node.class, openRoadmTopologyNode.key())
211 this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode);
213 for (Link openRoadmTopologyLink : topologyShard.getLinks()) {
214 LOG.info("deleting link {} in {}", openRoadmTopologyLink.getLinkId().getValue(),
215 NetworkUtils.OVERLAY_NETWORK_ID);
216 InstanceIdentifier<Link> iiOpenRoadmTopologyLink = InstanceIdentifier.builder(Networks.class)
217 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
218 .augmentation(Network1.class)
219 .child(Link.class, openRoadmTopologyLink.key())
221 this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink);
224 LOG.warn("TopologyShard for node '{}' is not present", nodeId);
227 OpenroadmVersion deviceVersion = this.portMapping.getNode(nodeId).getNodeInfo().getOpenroadmVersion();
229 NodeTypes nodeType = this.portMapping.getNode(nodeId).getNodeInfo().getNodeType();
230 if (nodeType.getIntValue() == 2 && deviceVersion.getIntValue() != 1) {
231 TopologyShard otnTopologyShard = this.otnTopologyShardMountedDevice.get(nodeId);
232 if (otnTopologyShard != null) {
233 LOG.info("suppression de otnTopologyShard = {}", otnTopologyShard.toString());
234 for (Node otnTopologyNode : otnTopologyShard.getNodes()) {
235 LOG.info("deleting node {} in {}", otnTopologyNode.getNodeId().getValue(),
236 NetworkUtils.OTN_NETWORK_ID);
237 InstanceIdentifier<Node> iiotnTopologyNode = InstanceIdentifier.builder(Networks.class)
238 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
239 .child(Node.class, otnTopologyNode.key())
241 this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiotnTopologyNode);
243 for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
244 LOG.info("deleting link {} in {}", otnTopologyLink.getLinkId().getValue(),
245 NetworkUtils.OTN_NETWORK_ID);
246 InstanceIdentifier<Link> iiotnTopologyLink = InstanceIdentifier.builder(Networks.class)
247 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
248 .augmentation(Network1.class)
249 .child(Link.class, otnTopologyLink.key())
251 this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiotnTopologyLink);
256 LOG.info("deleteOpenROADMnode: {} version {}", nodeId, deviceVersion.getName());
257 this.portMapping.deleteMappingData(nodeId);
259 this.networkTransactionService.commit().get(1, TimeUnit.SECONDS);
260 LOG.info("all nodes and links deleted ! ");
261 } catch (InterruptedException | ExecutionException | TimeoutException e) {
262 LOG.error("Error when trying to delete node : {}", nodeId, e);
267 public void updateOpenRoadmNetworkTopology(String nodeId, CircuitPacks changedCpack) {
268 // Clear maps for each NETCONF notification received
269 this.linksChanged.clear();
270 this.terminationPointsChanged.clear();
271 // 1. Get the list links and nodes of the current openroadm network topology
272 List<Link> linkList = null;
273 List<Node> nodesList = null;
275 InstanceIdentifier.InstanceIdentifierBuilder<Network1> network1IID =
276 InstanceIdentifier.builder(Networks.class)
277 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
278 .augmentation(Network1.class);
279 InstanceIdentifier.InstanceIdentifierBuilder<Network> networkIID =
280 InstanceIdentifier.builder(Networks.class)
281 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)));
282 Optional<Network> networkOptional = this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,
283 networkIID.build()).get();
284 Optional<Network1> network1Optional =
285 this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, network1IID.build()).get();
286 if (network1Optional.isPresent()) {
288 linkList = new ArrayList<>(Objects.requireNonNull(network1Optional.get().getLink()).values());
290 if (networkOptional.isPresent()) {
292 nodesList = new ArrayList<>(Objects.requireNonNull(networkOptional.get().getNode()).values());
294 } catch (InterruptedException e) {
295 LOG.error("Couldn't get list of links in the network. Error={}", e.getMessage());
296 Thread.currentThread().interrupt();
297 } catch (ExecutionException e) {
298 LOG.error("Couldn't get list of links in the network. Error={}", e.getMessage());
300 /* 2. For simplicity the update is only considered in the case of a WSSDEG circuit pack change where client and
301 line ports (external ports) of a node are included and there is a 1-to-1 port mapping to the nodes TPs. The
302 mapping between ports and TPs internal of a node is a bit different as the is a 1-to-many port mapping */
303 String cpackType = changedCpack.getCircuitPackType();
306 LOG.info("ADDROP circuit pack modified");
307 setTerminationPointsChangedMap(changedCpack);
308 // setTpStateHashmap(changedCpack);
311 LOG.info("WSSDEG circuit pack modified");
312 setTerminationPointsChangedMap(changedCpack);
313 // 3. Update the termination points of the node that sent a NETCONF notification
314 updateOpenRoadmNetworkTopologyTPs(nodesList, nodeId);
315 // 4. Update the links of the topology affected by the changes on TPs (if any)
316 updateOpenRoadmNetworkTopologyLinks(linkList, nodesList);
317 // TODO: send notification to service handler
320 LOG.info("port circuit pack modified");
323 LOG.info("pluggable circuit pack modified");
326 LOG.warn("Circuitp pack of type {} not recognized", cpackType);
331 public void createOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ, OtnLinkType linkType) {
332 TopologyShard otnTopologyShard;
335 otnTopologyShard = OpenRoadmOtnTopology.createOtnLinks(nodeA, tpA, nodeZ, tpZ, linkType);
338 String nodeTopoA = new StringBuilder(nodeA).append("-").append(tpA.split("-")[0]).toString();
339 String nodeTopoZ = new StringBuilder(nodeZ).append("-").append(tpZ.split("-")[0]).toString();
340 List<LinkId> linkIdList = new ArrayList<>();
341 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "OTU4"));
342 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "OTU4"));
343 List<Link> supportedOtu4links = getOtnLinks(linkIdList);
344 List<TerminationPoint> tps = getOtnNodeTps(nodeTopoA, tpA, nodeTopoZ, tpZ);
346 otnTopologyShard = OpenRoadmOtnTopology.createOtnLinks(supportedOtu4links, tps);
349 LOG.error("unknown otn link type {}", linkType);
350 otnTopologyShard = new TopologyShard(null, null);
352 if (otnTopologyShard.getLinks() != null) {
353 for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
354 LOG.info("creating and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
355 NetworkUtils.OVERLAY_NETWORK_ID);
356 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
357 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
358 .augmentation(Network1.class)
359 .child(Link.class, otnTopologyLink.key())
361 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
364 if (otnTopologyShard.getTps() != null) {
365 for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
366 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
367 List<SupportingTerminationPoint> supportingTerminationPoint =
368 new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
369 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
370 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
371 .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
372 .augmentation(Node1.class)
373 .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
375 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
379 networkTransactionService.commit().get();
380 } catch (InterruptedException | ExecutionException e) {
381 LOG.error("Error adding OTN links in otn-topology", e);
383 LOG.info("OTN links created");
387 public void deleteOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ, OtnLinkType linkType) {
388 TopologyShard otnTopologyShard;
389 String nodeTopoA = new StringBuilder(nodeA).append("-").append(tpA.split("-")[0]).toString();
390 String nodeTopoZ = new StringBuilder(nodeZ).append("-").append(tpZ.split("-")[0]).toString();
391 List<Link> otu4Links;
392 List<LinkId> linkIdList = new ArrayList<>();
395 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "OTU4"));
396 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "OTU4"));
397 otu4Links = getOtnLinks(linkIdList);
398 if (checkLinks(otu4Links)) {
399 deleteLinks(otu4Links);
401 LOG.error("Error deleting OTU4 links");
403 otnTopologyShard = new TopologyShard(null, null);
406 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "ODU4"));
407 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "ODU4"));
408 List<Link> odu4Links = getOtnLinks(linkIdList);
409 List<TerminationPoint> tps = getOtnNodeTps(nodeTopoA, tpA, nodeTopoZ, tpZ);
410 if (checkLinks(odu4Links) && checkTerminationPoints(tps)) {
411 deleteLinks(odu4Links);
413 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, "OTU4"));
414 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, "OTU4"));
415 otu4Links = getOtnLinks(linkIdList);
416 otnTopologyShard = OpenRoadmOtnTopology.deleteOtnLinks(otu4Links, tps);
418 LOG.error("Error deleting ODU4 links");
419 otnTopologyShard = new TopologyShard(null, null);
423 LOG.error("unknown otn link type {}", linkType);
424 otnTopologyShard = new TopologyShard(null, null);
426 if (otnTopologyShard.getLinks() != null) {
427 for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
428 LOG.info("deleting and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
429 NetworkUtils.OVERLAY_NETWORK_ID);
430 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
431 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
432 .augmentation(Network1.class)
433 .child(Link.class, otnTopologyLink.key())
435 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
438 if (otnTopologyShard.getTps() != null) {
439 for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
440 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
441 List<SupportingTerminationPoint> supportingTerminationPoint =
442 new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
443 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
444 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
445 .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
446 .augmentation(Node1.class)
447 .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
449 networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
453 networkTransactionService.commit().get();
454 } catch (InterruptedException | ExecutionException e) {
455 LOG.error("Error deleting OTN links in otn-topology", e);
457 LOG.info("OTN links deletion terminated");
461 public void updateOtnLinks(List<String> nodeTps, String serviceRate, Short tribPortNb, Short tribSoltNb,
462 boolean isDeletion) {
463 List<Link> supportedOdu4Links = getSupportingOdu4Links(nodeTps);
464 List<TerminationPoint> tps = getOtnNodeTps(nodeTps);
465 TopologyShard otnTopologyShard;
466 otnTopologyShard = OpenRoadmOtnTopology.updateOtnLinks(supportedOdu4Links, tps, serviceRate, tribPortNb,
467 tribSoltNb, isDeletion);
468 if (otnTopologyShard.getLinks() != null) {
469 for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
470 LOG.info("creating and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
471 NetworkUtils.OVERLAY_NETWORK_ID);
472 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
473 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
474 .augmentation(Network1.class)
475 .child(Link.class, new LinkKey(new LinkId(otnTopologyLink.getLinkId().getValue())))
477 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
480 if (otnTopologyShard.getTps() != null) {
481 for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
482 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
483 List<SupportingTerminationPoint> supportingTerminationPoint =
484 new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
485 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
486 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
487 .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
488 .augmentation(Node1.class)
489 .child(TerminationPoint.class, new TerminationPointKey(new TpId(otnTopologyTp.getTpId()
493 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
495 networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
500 networkTransactionService.commit().get();
501 } catch (InterruptedException | ExecutionException e) {
502 LOG.error("Error updating OTN links in otn-topology", e);
506 private List<Link> getOtnLinks(List<LinkId> linkIds) {
507 List<Link> links = new ArrayList<>();
508 for (LinkId linkId : linkIds) {
509 InstanceIdentifier<Link> iiLink = InstanceIdentifier.builder(Networks.class)
510 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
511 .augmentation(Network1.class)
512 .child(Link.class, new LinkKey(linkId))
514 ListenableFuture<Optional<Link>> linkOptLf = networkTransactionService
515 .read(LogicalDatastoreType.CONFIGURATION, iiLink);
516 if (linkOptLf.isDone()) {
518 if (linkOptLf.get().isPresent()) {
519 links.add(linkOptLf.get().get());
521 } catch (InterruptedException | ExecutionException e) {
522 LOG.error("Error retreiving OTN links from otn-topology", e);
525 LOG.error("Error retreiving link {} from otn-topology", linkId.getValue());
531 private boolean checkLinks(List<Link> links) {
532 if (links.isEmpty()) {
535 for (Link link : links) {
536 if (link.augmentation(Link1.class) != null
537 && !link.augmentation(Link1.class).getUsedBandwidth().equals(Uint32.valueOf(0))) {
544 private boolean checkTerminationPoints(List<TerminationPoint> tps) {
548 for (TerminationPoint tp : tps) {
549 if (tp.augmentation(TerminationPoint1.class) != null && tp.augmentation(TerminationPoint1.class)
550 .getXpdrTpPortConnectionAttributes().getTsPool() != null && tp.augmentation(TerminationPoint1.class)
551 .getXpdrTpPortConnectionAttributes().getTsPool().size() != 80) {
558 private List<TerminationPoint> getOtnNodeTps(String nodeTopoA, String tpA, String nodeTopoZ, String tpZ) {
559 List<TerminationPoint> tps = new ArrayList<>();
560 InstanceIdentifier<TerminationPoint> iiTpA = InstanceIdentifier.builder(Networks.class)
561 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
562 .child(Node.class, new NodeKey(new NodeId(nodeTopoA)))
563 .augmentation(Node1.class)
564 .child(TerminationPoint.class, new TerminationPointKey(new TpId(tpA)))
566 Optional<TerminationPoint> tpAOpt = Optional.empty();
567 InstanceIdentifier<TerminationPoint> iiTpZ = InstanceIdentifier.builder(Networks.class)
568 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
569 .child(Node.class, new NodeKey(new NodeId(nodeTopoZ)))
570 .augmentation(Node1.class)
571 .child(TerminationPoint.class, new TerminationPointKey(new TpId(tpZ)))
573 Optional<TerminationPoint> tpZOpt = Optional.empty();
575 if (networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).isDone()
576 && networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).isDone()) {
578 tpAOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).get();
579 tpZOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).get();
580 } catch (InterruptedException | ExecutionException e) {
581 LOG.error("Error retreiving tp {} of node {} or tp {} from node {} from otn-topology", tpA, nodeTopoA,
585 LOG.error("error getting node termination points from the datastore");
588 if (tpAOpt.isPresent() && tpZOpt.isPresent()) {
589 tps.add(tpAOpt.get());
590 tps.add(tpZOpt.get());
595 private List<TerminationPoint> getOtnNodeTps(List<String> nodeTopoTps) {
596 List<TerminationPoint> tps = new ArrayList<>();
597 for (String str : nodeTopoTps) {
598 String nodeId = str.split("--")[0];
599 String tp = str.split("--")[1];
600 InstanceIdentifier<TerminationPoint> iiTp = InstanceIdentifier.builder(Networks.class)
601 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
602 .child(Node.class, new NodeKey(new NodeId(nodeId)))
603 .augmentation(Node1.class)
604 .child(TerminationPoint.class, new TerminationPointKey(new TpId(tp)))
606 Optional<TerminationPoint> tpOpt;
607 if (networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTp).isDone()) {
609 tpOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTp).get();
610 if (tpOpt.isPresent()) {
611 tps.add(tpOpt.get());
613 } catch (InterruptedException | ExecutionException e) {
614 LOG.error("Error retreiving tp {} of node {} from otn-topology", tp, nodeId, e);
617 LOG.error("error getting node termination points from the datastore");
621 LOG.warn("returning null");
624 LOG.info("returning tps = {}", tps.toString());
629 private void deleteLinks(List<Link> links) {
630 for (Link otnTopologyLink : links) {
631 LOG.info("deleting link {} from {}", otnTopologyLink.getLinkId().getValue(),
632 NetworkUtils.OVERLAY_NETWORK_ID);
633 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
634 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
635 .augmentation(Network1.class)
636 .child(Link.class, otnTopologyLink.key())
638 networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink);
641 networkTransactionService.commit().get();
642 } catch (InterruptedException | ExecutionException e) {
643 LOG.error("Error deleting OTN links from otn-topology", e);
647 private List<Link> getSupportingOdu4Links(List<String> nodesTopoTps) {
648 InstanceIdentifier<Network1> iiOtnTopologyLinks = InstanceIdentifier.builder(Networks.class)
649 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
650 .augmentation(Network1.class)
652 ListenableFuture<Optional<Network1>> netw1Fl = networkTransactionService
653 .read(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLinks);
654 Optional<Network1> netw1Opt = Optional.empty();
655 if (netw1Fl.isDone()) {
657 netw1Opt = netw1Fl.get();
658 } catch (InterruptedException | ExecutionException e) {
659 LOG.error("Error retreiving list of links from otn-topology", e);
662 List<Link> odu4links = null;
663 if (netw1Opt.isPresent() && netw1Opt.get().getLink() != null) {
666 .nonnullLink().values()
667 .stream().filter(lk -> lk.getLinkId().getValue().startsWith("ODU4"))
668 .collect(Collectors.toList());
670 List<Link> links = new ArrayList<>();
671 if (odu4links != null) {
672 for (String str : nodesTopoTps) {
673 String[] nodeAndTp = str.split("--");
674 if (nodeAndTp.length >= 2) {
675 String nodeId = nodeAndTp[0];
676 String tp = nodeAndTp[1];
677 Link slink = odu4links.stream().filter(lk -> lk.getSource().getSourceNode().getValue()
678 .equals(nodeId) && lk.getSource().getSourceTp().toString().equals(tp)).findFirst().get();
679 if (!links.contains(slink)) {
682 Link dlink = odu4links.stream().filter(lk -> lk.getDestination().getDestNode().getValue()
683 .equals(nodeId) && lk.getDestination().getDestTp().toString().equals(tp)).findFirst().get();
684 if (!links.contains(dlink)) {
689 LOG.debug("odu4links = {}", links.toString());
696 private void createOpenRoadmOtnNode(String nodeId) {
697 TopologyShard otnTopologyShard = OpenRoadmOtnTopology.createTopologyShard(portMapping.getNode(nodeId));
698 if (otnTopologyShard != null) {
699 this.otnTopologyShardMountedDevice.put(nodeId, otnTopologyShard);
700 for (Node otnTopologyNode : otnTopologyShard.getNodes()) {
701 LOG.info("creating otn node {} in {}", otnTopologyNode.getNodeId().getValue(),
702 NetworkUtils.OTN_NETWORK_ID);
703 InstanceIdentifier<Node> iiOtnTopologyNode = InstanceIdentifier.builder(Networks.class)
704 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
705 .child(Node.class, otnTopologyNode.key())
707 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyNode, otnTopologyNode);
709 for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
710 LOG.info("creating otn link {} in {}", otnTopologyLink.getLinkId().getValue(),
711 NetworkUtils.OVERLAY_NETWORK_ID);
712 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
713 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
714 .augmentation(Network1.class)
715 .child(Link.class, otnTopologyLink.key())
717 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
720 LOG.error("Unable to create OTN topology shard for node {}!", nodeId);
725 private void setTerminationPointsChangedMap(CircuitPacks changedCpack) {
726 List<Ports> portsList = new ArrayList<>(Objects.requireNonNull(changedCpack.getPorts()).values());
727 for (Ports port : portsList) {
728 String lcp = port.getLogicalConnectionPoint();
729 if (lcp != null && !this.terminationPointsChanged.containsKey(lcp)) {
730 this.terminationPointsChanged.put(lcp, State.forValue(port.getOperationalState().getIntValue()));
735 private void updateOpenRoadmNetworkTopologyTPs(List<Node> nodesList, String nodeId) {
736 /* 1. The nodes in nodesList are abstract nodes (i.e. ROADMA01-DEG1) and we have the id of the node that has
737 a change (i.e. ROADMA01). So we only need to look for the abstract nodes that belong to the physical node. */
738 String abstractNodeId;
739 for (Node node : nodesList) {
740 abstractNodeId = Objects.requireNonNull(node.getNodeId()).getValue();
741 // Checking if the node is operationally inService
742 if (abstractNodeId.contains(nodeId) && node.augmentation(org.opendaylight.yang.gen.v1.http
743 .org.openroadm.common.network.rev200529.Node1.class)
744 .getOperationalState().equals(State.InService)) {
745 /* 2. Check if the state of the termination points from the topology shard are equal to the state of
746 the termination points in the previously created map. */
747 List<TerminationPoint> tpList = new ArrayList<>(Objects.requireNonNull(node.augmentation(Node1.class))
748 .getTerminationPoint().values());
749 Map<TerminationPointKey, TerminationPoint> updatedTpMap = new HashMap<>();
750 for (TerminationPoint tp : tpList) {
751 String tpId = Objects.requireNonNull(tp.getTpId()).getValue();
752 State tpState = Objects.requireNonNull(tp.augmentation(org.opendaylight.yang.gen.v1.http
753 .org.openroadm.common.network.rev200529.TerminationPoint1.class)).getOperationalState();
754 if (this.terminationPointsChanged.containsKey(tpId) && !this.terminationPointsChanged.get(tpId)
756 // The state of a termination point has changed... updating
757 State newTpOperationalState = null;
758 AdminStates newTpAdminState = null;
759 /* 3. If the TP has changed its state, it has to be added to the links Map, as a Link state
760 is defined by the state of the TPs that model the link. */
761 switch (this.terminationPointsChanged.get(tpId)) {
763 newTpAdminState = AdminStates.InService;
764 newTpOperationalState = State.InService;
765 // Add TP and state inService to the links Map
766 this.linksChanged.put(tpId, State.InService);
767 // TODO: update change list for service handler notification
770 newTpAdminState = AdminStates.OutOfService;
771 newTpOperationalState = State.OutOfService;
772 // Add TP and state outOfService to the links Map
773 this.linksChanged.put(tpId, State.OutOfService);
774 // TODO: update change list for service handler notification
777 LOG.warn("Operational state Degraded not handled");
780 LOG.warn("Unrecognized state!");
782 // 4. Add modified TP to the updated List.
783 TerminationPoint updTp = new TerminationPointBuilder().withKey(tp.key())
784 .setTpId(tp.getTpId())
785 .addAugmentation(new TerminationPoint1Builder()
786 .setAdministrativeState(newTpAdminState)
787 .setOperationalState(newTpOperationalState)
790 updatedTpMap.put(tp.key(), updTp);
792 // 5. Update the list of termination points of the corresponding node and merge to the datastore.
793 if (!updatedTpMap.isEmpty()) {
794 Node updNode = new NodeBuilder().setNodeId(node.getNodeId()).addAugmentation(new Node1Builder()
795 .setTerminationPoint(updatedTpMap).build()).build();
796 InstanceIdentifier<Node> iiOpenRoadmTopologyNode = InstanceIdentifier.builder(
797 Networks.class).child(Network.class, new NetworkKey(
798 new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).child(Node.class, node.key())
800 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode,
803 networkTransactionService.commit().get();
804 } catch (InterruptedException e) {
805 LOG.error("Couldnt commit change to openroadm topology.", e);
806 Thread.currentThread().interrupt();
807 } catch (ExecutionException e) {
808 LOG.error("Couldnt commit change to openroadm topology.", e);
816 private void updateOpenRoadmNetworkTopologyLinks(List<Link> linkList, List<Node> nodesList) {
817 for (Link link : linkList) {
818 String srcTp = link.getSource().getSourceTp().toString();
819 String dstTp = link.getDestination().getDestTp().toString();
820 String srcNode = link.getSource().getSourceNode().getValue();
821 String dstNode = link.getDestination().getDestNode().getValue();
822 State linkState = link.augmentation(org.opendaylight.yang.gen.v1.http
823 .org.openroadm.common.network.rev200529.Link1.class).getOperationalState();
824 /* 1. Check the current state of the source and dest tps of the link. If these tps exist on the links Map
825 and the states are different, then we need to update the link state accordingly.
826 There are several cases depending on the current link state:
827 - TPs were both inService and one of them (or both) is (are) now outOfService --> link to outOfService
828 - TPs were both outOfService and both of them are now inService --> link to inService
829 However, if only one TP exists on the Link map, we will need to check the state of the other end in order to
830 make a decision: i.e. we cannot assume that if a TP has changed from outOfService to inService the link will
831 become inService, as this can only happen if both TPs are inService, therefore we need to check the other
835 if (this.linksChanged.containsKey(srcTp) && this.linksChanged.containsKey(dstTp)) {
836 // Both TPs of the link have been updated. If one of them is outOfService --> link outOfService
837 if (State.OutOfService.equals(this.linksChanged.get(srcTp)) || State.OutOfService.equals(this
838 .linksChanged.get(dstTp))) {
839 updateLinkStates(link, State.OutOfService, AdminStates.OutOfService);
841 } else if (this.linksChanged.containsKey(srcTp) && State.OutOfService.equals(this.linksChanged
843 // Source TP has been changed to outOfService --> link outOfService
844 updateLinkStates(link, State.OutOfService, AdminStates.OutOfService);
845 } else if (this.linksChanged.containsKey(dstTp) && State.OutOfService.equals(this.linksChanged
847 // Destination TP has been changed to outOfService --> link outOfService
848 updateLinkStates(link, State.OutOfService, AdminStates.OutOfService);
852 if (this.linksChanged.containsKey(srcTp) && this.linksChanged.containsKey(dstTp)) {
853 // Both TPs of the link have been updated. If both of them are inService --> link inService
854 if (State.InService.equals(this.linksChanged.get(srcTp)) || State.InService.equals(this
855 .linksChanged.get(dstTp))) {
856 updateLinkStates(link, State.InService, AdminStates.InService);
858 } else if (this.linksChanged.containsKey(srcTp) && State.InService.equals(this.linksChanged
860 // Source TP has been changed to inService --> check the second TP and update link to inService
861 // only if both TPs are inService
862 if (tpInService(dstNode, dstTp, nodesList)) {
863 updateLinkStates(link, State.InService, AdminStates.InService);
865 } else if (this.linksChanged.containsKey(dstTp) && State.InService.equals(this.linksChanged
867 // Destination TP has been changed to to inService --> check the second TP and update link to
868 // inService only if both TPs are inService
869 if (tpInService(srcNode, srcTp, nodesList)) {
870 updateLinkStates(link, State.InService, AdminStates.InService);
875 LOG.warn("Link state degraded not handled");
878 LOG.warn("Unrecognized state!");
883 private boolean tpInService(String nodeId, String tpId, List<Node> nodesList) {
884 // Check the node with dstNode id and check the state of the TP with id dstTP id
885 for (Node node : nodesList) {
886 if (Objects.requireNonNull(node.getNodeId()).getValue().equals(nodeId)) {
887 List<TerminationPoint> tpList = new ArrayList<>(Objects.requireNonNull(Objects.requireNonNull(node
888 .augmentation(Node1.class)).getTerminationPoint()).values());
889 for (TerminationPoint tp : tpList) {
890 if (Objects.requireNonNull(tp.getTpId()).getValue().equals(tpId)) {
891 if (State.InService.equals(tp.augmentation(org.opendaylight.yang.gen.v1.http
892 .org.openroadm.common.network.rev200529.TerminationPoint1.class)
893 .getOperationalState())) {
894 // The second TP is also inService
906 private void updateLinkStates(Link link, State state, AdminStates adminStates) {
907 // TODO: add change to list of changes
908 org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1 link1 = new Link1Builder()
909 .setOperationalState(state).setAdministrativeState(adminStates).build();
910 Link updLink = new LinkBuilder().withKey(link.key()).addAugmentation(link1).build();
911 InstanceIdentifier.InstanceIdentifierBuilder<Link> linkIID = InstanceIdentifier.builder(Networks.class)
912 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
913 .augmentation(Network1.class).child(Link.class, link.key());
914 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, linkIID.build(), updLink);
916 networkTransactionService.commit().get();
917 } catch (InterruptedException e) {
918 LOG.error("Couldnt commit changed to openroadm topology. Error={}", e.getMessage());
919 Thread.currentThread().interrupt();
920 } catch (ExecutionException e) {
921 LOG.error("Couldnt commit changed to openroadm topology. Error={}", e.getMessage());