Improve networkmodel util OpenRoadmOtnTopology 2/2
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / util / OpenRoadmOtnTopology.java
1 /*
2  * Copyright © 2020 Orange. 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
9 package org.opendaylight.transportpce.networkmodel.util;
10
11 import com.google.common.collect.ImmutableMap;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.stream.Collectors;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.transportpce.common.NetworkUtils;
19 import org.opendaylight.transportpce.networkmodel.dto.OtnTopoNode;
20 import org.opendaylight.transportpce.networkmodel.dto.TopologyShard;
21 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220114.mapping.Mapping;
22 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220114.network.Nodes;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.XpdrNodeTypes;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev200327.xpdr.odu.switching.pools.OduSwitchingPools;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev200327.xpdr.odu.switching.pools.OduSwitchingPoolsBuilder;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev200327.xpdr.odu.switching.pools.OduSwitchingPoolsKey;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev200327.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingList;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev200327.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingListBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev200327.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingListKey;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmLinkType;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmNodeType;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmTpType;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.xpdr.tp.supported.interfaces.SupportedInterfaceCapability;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.xpdr.tp.supported.interfaces.SupportedInterfaceCapabilityBuilder;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.xpdr.tp.supported.interfaces.SupportedInterfaceCapabilityKey;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODTU4TsAllocated;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODTUCnTs;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODU0;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODU2;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODU2e;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODU4;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OdtuTypeIdentity;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OduRateIdentity;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.Link1;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.Link1Builder;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.Node1Builder;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.TerminationPoint1;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.TerminationPoint1Builder;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.networks.network.node.SwitchingPoolsBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.networks.network.node.TpBandwidthSharingBuilder;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.networks.network.node.XpdrAttributesBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.networks.network.node.termination.point.TpSupportedInterfacesBuilder;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.networks.network.node.termination.point.XpdrTpPortConnectionAttributesBuilder;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev200327.SupportedIfCapability;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.switching.pool.types.rev191129.SwitchingPoolTypes;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev200529.xpdr.otn.tp.attributes.OdtuTpnPool;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev200529.xpdr.otn.tp.attributes.OdtuTpnPoolBuilder;
60 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.OtnLinkType;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeBuilder;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeKey;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNode;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNodeBuilder;
68 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNodeKey;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkBuilder;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointBuilder;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.termination.point.SupportingTerminationPoint;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.termination.point.SupportingTerminationPointBuilder;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.termination.point.SupportingTerminationPointKey;
78 import org.opendaylight.yangtools.yang.common.Uint16;
79 import org.opendaylight.yangtools.yang.common.Uint32;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
82
83 public final class OpenRoadmOtnTopology {
84
85     private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmOtnTopology.class);
86     private static final String CLIENT = "-CLIENT";
87     private static final String NETWORK = "-NETWORK";
88     private static final String XPDR = "-XPDR";
89     private static final String OTN_PARAMS_ERROR = "Error with otn parameters of supported link {}";
90     private static final int NB_TRIB_PORTS = 80;
91     private static final int NB_TRIB_SLOTS = 80;
92
93     private static Map<String, Class<? extends OduRateIdentity>> rateMap = Map.of(
94         "If100GEODU4", ODU4.class,
95         "IfOCHOTU4ODU4", ODU4.class,
96         "If1GEODU0", ODU0.class,
97         "If10GEODU2", ODU2.class,
98         "If10GEODU2e", ODU2e.class);
99     private static Map<OtnLinkType, Long> otnLinkTypeBwMap = Map.of(
100         OtnLinkType.ODTU4, 100000L,
101         OtnLinkType.ODUC4, 400000L,
102         OtnLinkType.ODUC3, 300000L,
103         OtnLinkType.ODUC2, 200000L);
104     private static Map<OtnLinkType, Long> otnOtuLinkTypeBwMap = Map.of(
105         OtnLinkType.OTU4, 100000L,
106         OtnLinkType.OTUC4, 400000L);
107     private static Map<Uint32, Long> serviceRateBwIncrMap = Map.of(
108         Uint32.valueOf(1), 1000L,
109         Uint32.valueOf(10), 10000L,
110         Uint32.valueOf(100), 100000L);
111     private static Map<Uint32, Class<? extends OdtuTypeIdentity>> serviceRateOdtuTypeClassMap = Map.of(
112         Uint32.valueOf(1), ODTU4TsAllocated.class,
113         Uint32.valueOf(10), ODTU4TsAllocated.class,
114         Uint32.valueOf(100), ODTUCnTs.class);
115
116     private OpenRoadmOtnTopology() {
117     }
118
119     public static TopologyShard createTopologyShard(Nodes mappingNode) {
120         List<Node> nodes = new ArrayList<>();
121         List<Link> links = new ArrayList<>();
122         Map<Integer, OtnTopoNode> xpdrMap = convertPortMappingToOtnNodeList(mappingNode);
123         for (OtnTopoNode node : xpdrMap.values()) {
124             switch (node.getNodeType()) {
125                 case Tpdr:
126                     nodes.add(createTpdr(node));
127                     break;
128                 case Mpdr:
129                     nodes.add(createMuxpdr(node));
130                     break;
131                 case Switch:
132                     nodes.add(createSwitch(node));
133                     break;
134                 default:
135                     LOG.error("unknown otn node type {}", node.getNodeType().getName());
136                     return null;
137             }
138         }
139         return new TopologyShard(nodes, links);
140     }
141
142     public static TopologyShard createOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ,
143             OtnLinkType linkType) {
144
145         return new TopologyShard(
146             null,
147             otnOtuLinkTypeBwMap.containsKey(linkType)
148                 ? initialiseOtnLinks(nodeA, tpA, nodeZ, tpZ, linkType)
149                 : null);
150     }
151
152     public static TopologyShard createOtnLinks(
153             org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp
154                 .Link notifLink,
155             OtnLinkType linkType) {
156
157         return new TopologyShard(
158             null,
159             initialiseOtnLinks(notifLink.getATermination().getNodeId(),
160             notifLink.getATermination().getTpId(),
161             notifLink.getZTermination().getNodeId(),
162             notifLink.getZTermination().getTpId(),
163             linkType));
164     }
165
166     public static TopologyShard createOtnLinks(
167             org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp
168                 .Link notifLink,
169             List<Link> supportedOtu4links, List<TerminationPoint> supportedTPs, OtnLinkType linkType) {
170
171         if (otnOtuLinkTypeBwMap.containsKey(linkType)) {
172             return new TopologyShard(
173                 null,
174                 initialiseOtnLinks(
175                     notifLink.getATermination().getNodeId(), notifLink.getATermination().getTpId(),
176                     notifLink.getZTermination().getNodeId(), notifLink.getZTermination().getTpId(), linkType));
177         } else if (otnLinkTypeBwMap.containsKey(linkType)) {
178             List<Link> links = initialiseOtnLinks(
179                 notifLink.getATermination().getNodeId(), notifLink.getATermination().getTpId(),
180                 notifLink.getZTermination().getNodeId(), notifLink.getZTermination().getTpId(), linkType);
181             links.addAll(updateOtnLinkBwParameters(supportedOtu4links, linkType));
182             List<TerminationPoint> updatedTPs = new ArrayList<>();
183             for (TerminationPoint tp : supportedTPs) {
184                 updatedTPs.add(updateTp(tp, true, linkType));
185             }
186             return new TopologyShard(null, links, updatedTPs);
187         } else {
188             return null;
189         }
190     }
191
192     public static TopologyShard createOtnLinks(List<Link> suppOtuLinks, List<TerminationPoint> oldTps,
193             OtnLinkType linkType) {
194
195         List<Link> links = new ArrayList<>();
196         for (Link link : suppOtuLinks) {
197             if (link.augmentation(Link1.class) == null) {
198                 LOG.error("Error with OTN parameters of supported link {}", link.getLinkId().getValue());
199                 continue;
200             }
201             if (!otnLinkTypeBwMap.containsKey(linkType)) {
202                 LOG.error("Error with link {} : unsupported OTN link type", link.getLinkId().getValue());
203                 continue;
204             }
205             if (link.augmentation(Link1.class).getAvailableBandwidth().longValue() < otnLinkTypeBwMap.get(linkType)) {
206                 LOG.error("Error with link {} : unsufficient available bandwith", link.getLinkId().getValue());
207                 continue;
208             }
209             links.add(updateOtnLinkBwParameters(link, 0L, otnLinkTypeBwMap.get(linkType)));
210         }
211         if (links.size() == 2) {
212             links.addAll(initialiseOtnLinks(suppOtuLinks.get(0).getSource().getSourceNode().getValue(),
213                 suppOtuLinks.get(0).getSource().getSourceTp().getValue(),
214                 suppOtuLinks.get(0).getDestination().getDestNode().getValue(),
215                 suppOtuLinks.get(0).getDestination().getDestTp().getValue(),
216                 linkType));
217         }
218         List<TerminationPoint> tps = new ArrayList<>();
219         for (TerminationPoint tp : oldTps) {
220             tps.add(updateTp(tp, true, linkType));
221         }
222         return links.size() == 4 && tps.size() == 2
223             ?  new TopologyShard(null, links, tps)
224             :  new TopologyShard(null, null, null);
225     }
226
227     public static TopologyShard updateOtnLinks(List<Link> suppOduLinks, List<TerminationPoint> oldTps,
228             Uint32 serviceRate, Short tribPortNb, Short minTribSlotNb, Short maxTribSlotNb, boolean isDeletion) {
229
230         List<Link> links = new ArrayList<>();
231         if (!serviceRateBwIncrMap.containsKey(serviceRate)) {
232             LOG.warn("Error with not managed service rate {}", serviceRate.toString());
233             return new TopologyShard(null, null, null);
234         }
235         Long bwIncr = serviceRateBwIncrMap.get(serviceRate);
236         for (Link link : suppOduLinks) {
237             if (link.augmentation(Link1.class) == null
238                     || link.augmentation(Link1.class).getAvailableBandwidth() == null
239                     || link.augmentation(Link1.class).getUsedBandwidth() == null) {
240                 LOG.error(OTN_PARAMS_ERROR, link.getLinkId().getValue());
241             } else {
242                 Uint32 avlBw = link.augmentation(Link1.class).getAvailableBandwidth();
243                 Uint32 usedBw = link.augmentation(Link1.class).getUsedBandwidth();
244                 if (avlBw.toJava() < bwIncr) {
245                     bwIncr = 0L;
246                 }
247                 links.add(
248                     isDeletion
249                         ? updateOtnLinkBwParameters(link, avlBw.toJava() + bwIncr, usedBw.toJava() - bwIncr)
250                         : updateOtnLinkBwParameters(link, avlBw.toJava() - bwIncr, usedBw.toJava() + bwIncr)
251                 );
252             }
253         }
254         List<TerminationPoint> tps = new ArrayList<>();
255         for (TerminationPoint tp : oldTps) {
256             if (bwIncr > 0L) {
257                 tps.add(updateNodeTpTsPool(tp, serviceRate, tribPortNb, minTribSlotNb, maxTribSlotNb, isDeletion));
258             }
259         }
260         if (links.isEmpty() || tps.isEmpty()) {
261             LOG.error("unable to update otn links");
262             return new TopologyShard(null, null, null);
263         } else {
264             return new TopologyShard(null, links, tps);
265         }
266     }
267
268     public static TopologyShard updateOtnLinks(List<Link> suppOtuLinks, boolean isDeletion) {
269
270         List<Link> links = new ArrayList<>();
271         for (Link link : suppOtuLinks) {
272             if (link.augmentation(Link1.class) == null
273                 || link.augmentation(Link1.class).getAvailableBandwidth() == null
274                 || link.augmentation(Link1.class).getUsedBandwidth() == null) {
275                 LOG.error(OTN_PARAMS_ERROR, link.getLinkId().getValue());
276             } else {
277                 links.add(
278                     isDeletion
279                         ? updateOtnLinkBwParameters(link, Long.valueOf(100000), Long.valueOf(0))
280                         : updateOtnLinkBwParameters(link, Long.valueOf(0), Long.valueOf(100000))
281                 );
282             }
283         }
284         if (links.isEmpty()) {
285             LOG.error("unable to update otn links");
286             return new TopologyShard(null, null, null);
287         } else {
288             return new TopologyShard(null, links, null);
289         }
290     }
291
292     public static TopologyShard deleteOtnLinks(List<Link> suppOtuLinks, List<TerminationPoint> oldTps,
293             OtnLinkType linkType) {
294
295         List<Link> links = new ArrayList<>();
296         for (Link link : suppOtuLinks) {
297             if (link.augmentation(Link1.class) == null
298                     || link.augmentation(
299                         org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.Link1.class) == null) {
300                 LOG.error(OTN_PARAMS_ERROR, link.getLinkId().getValue());
301                 return new TopologyShard(null, null, null);
302             }
303             OtnLinkType otnLinkType = link.augmentation(
304                     org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.Link1.class).getOtnLinkType();
305             if (!otnOtuLinkTypeBwMap.containsKey(otnLinkType)) {
306             //TODO shouldn't other link type listed in otnLinkTypeBwMap be handled too ?
307                 LOG.warn("Unexpected otn-link-type {} for link {}", otnLinkType, link.getLinkId());
308                 continue;
309             }
310             links.add(updateOtnLinkBwParameters(link, otnOtuLinkTypeBwMap.get(otnLinkType) , 0L));
311         }
312         List<TerminationPoint> tps = new ArrayList<>();
313         for (TerminationPoint tp : oldTps) {
314             tps.add(updateTp(tp, false, linkType));
315         }
316         return
317             links.isEmpty() || tps.isEmpty()
318                 ? new TopologyShard(null, null, null)
319                 : new TopologyShard(null, links, tps);
320     }
321
322     private static List<Link> initialiseOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ,
323             OtnLinkType linkType) {
324
325         List<Link> links = new ArrayList<>();
326         String nodeATopo = formatNodeName(nodeA, tpA);
327         String nodeZTopo = formatNodeName(nodeZ, tpZ);
328         org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.Link1 tpceLink1
329             = new org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.Link1Builder()
330                 .setOtnLinkType(linkType).build();
331         Link1Builder otnLink1Bldr = new Link1Builder()
332             .setUsedBandwidth(Uint32.valueOf(0));
333         if (otnOtuLinkTypeBwMap.containsKey(linkType)) {
334             otnLink1Bldr.setAvailableBandwidth(Uint32.valueOf(otnOtuLinkTypeBwMap.get(linkType)));
335         } else if (otnLinkTypeBwMap.containsKey(linkType)) {
336             otnLink1Bldr.setAvailableBandwidth(Uint32.valueOf(otnLinkTypeBwMap.get(linkType)));
337         } else {
338             LOG.error("unable to set available bandwidth to unknown link type");
339         }
340         // create link A-Z
341         LinkBuilder ietfLinkAZBldr = TopologyUtils.createLink(nodeATopo, nodeZTopo, tpA, tpZ, linkType.getName());
342         links.add(ietfLinkAZBldr
343             .addAugmentation(tpceLink1)
344             .addAugmentation(otnLink1Bldr.build())
345             .addAugmentation(
346                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1Builder(
347                         ietfLinkAZBldr.augmentation(
348                             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1.class))
349                     .setLinkType(OpenroadmLinkType.OTNLINK)
350                     .setOperationalState(State.InService)
351                     .setAdministrativeState(AdminStates.InService)
352                     .build())
353             .build());
354         // create link Z-A
355         LinkBuilder ietfLinkZABldr = TopologyUtils.createLink(nodeZTopo, nodeATopo, tpZ, tpA, linkType.getName());
356         links.add(ietfLinkZABldr
357             .addAugmentation(tpceLink1)
358             .addAugmentation(otnLink1Bldr.build())
359             .addAugmentation(
360                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1Builder(
361                         ietfLinkZABldr.augmentation(
362                             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1.class))
363                     .setLinkType(OpenroadmLinkType.OTNLINK)
364                     .setOperationalState(State.InService)
365                     .setAdministrativeState(AdminStates.InService)
366                     .build())
367             .build());
368         return links;
369     }
370
371     private static Link updateOtnLinkBwParameters(Link link, Long availBw, Long usedBw) {
372
373         LOG.debug("in updateOtnLinkBwParameters with availBw = {}, usedBw = {}", availBw, usedBw);
374         return new LinkBuilder(link)
375             .addAugmentation(
376                 new Link1Builder(link.augmentation(Link1.class))
377                     .setAvailableBandwidth(Uint32.valueOf(availBw))
378                     .setUsedBandwidth(Uint32.valueOf(usedBw))
379                     .build())
380             .build();
381     }
382
383     private static List<Link> updateOtnLinkBwParameters(List<Link> supportedLinks, OtnLinkType linkType) {
384
385         LOG.debug("in updateOtnLinkBwParameters with supportedLinks = {}, linkType = {}", supportedLinks, linkType);
386         List<Link> updatedlinks = new ArrayList<>();
387         for (Link link : supportedLinks) {
388             updatedlinks.add(
389                 new LinkBuilder(link)
390                     .addAugmentation(new Link1Builder(link.augmentation(Link1.class))
391                         .setAvailableBandwidth(Uint32.valueOf(0))
392                         .setUsedBandwidth(
393                             otnLinkTypeBwMap.containsKey(linkType)
394                                 ? Uint32.valueOf(otnLinkTypeBwMap.get(linkType))
395                                 : Uint32.valueOf(0))
396                         .build())
397                     .build());
398         }
399         return updatedlinks;
400     }
401
402     private static TerminationPoint updateTp(TerminationPoint originalTp, boolean addingTsTpnPoolTermination,
403             OtnLinkType linkType) {
404
405         LOG.debug("in updateTp");
406         TerminationPointBuilder tpBldr = new TerminationPointBuilder(originalTp);
407         TerminationPoint1Builder otnTp1Bldr =
408             new TerminationPoint1Builder(tpBldr.augmentation(TerminationPoint1.class));
409         XpdrTpPortConnectionAttributesBuilder xtpcaBldr =
410             new XpdrTpPortConnectionAttributesBuilder(otnTp1Bldr.getXpdrTpPortConnectionAttributes());
411         if (addingTsTpnPoolTermination) {
412             List<Uint16> tsPool = new ArrayList<>();
413             for (int i = 1; i <= NB_TRIB_SLOTS; i++) {
414                 tsPool.add(Uint16.valueOf(i));
415             }
416             xtpcaBldr.setTsPool(tsPool);
417             List<Uint16> tpnPool = new ArrayList<>();
418             int nbTribPort = NB_TRIB_PORTS;
419             if (OtnLinkType.ODUC4.equals(linkType)) {
420                 nbTribPort = 4;
421             }
422             for (int i = 1; i <= nbTribPort; i++) {
423                 tpnPool.add(Uint16.valueOf(i));
424             }
425             OdtuTpnPool oduTpnPool = new OdtuTpnPoolBuilder()
426                 .setOdtuType(ODTU4TsAllocated.class)
427                 .setTpnPool(tpnPool)
428                 .build();
429             xtpcaBldr.setOdtuTpnPool(ImmutableMap.of(oduTpnPool.key(),oduTpnPool));
430         } else {
431             xtpcaBldr.setTsPool(null);
432             xtpcaBldr.setOdtuTpnPool(ImmutableMap.of());
433         }
434         return tpBldr.addAugmentation(otnTp1Bldr.setXpdrTpPortConnectionAttributes(xtpcaBldr.build()).build()).build();
435     }
436
437     private static TerminationPoint updateNodeTpTsPool(TerminationPoint tp, Uint32 serviceRate, Short tribPortNb,
438             Short minTribSlotNb, Short maxTribSlotNb, boolean isDeletion) {
439
440         LOG.debug("in updateNodeTpTsPool");
441         TerminationPointBuilder tpBldr = new TerminationPointBuilder(tp);
442         @Nullable
443         XpdrTpPortConnectionAttributesBuilder xtpcaBldr =
444             new XpdrTpPortConnectionAttributesBuilder(
445                 tpBldr.augmentation(TerminationPoint1.class).getXpdrTpPortConnectionAttributes());
446         List<Uint16> tsPool = new ArrayList<>(xtpcaBldr.getTsPool());
447         if (isDeletion) {
448             for (int i = minTribSlotNb; i <= maxTribSlotNb; i++) {
449                 tsPool.add(Uint16.valueOf(i));
450             }
451         } else {
452             for (int i = minTribSlotNb; i <= maxTribSlotNb; i++) {
453                 tsPool.remove(Uint16.valueOf(i));
454             }
455         }
456         xtpcaBldr.setTsPool(tsPool);
457         List<Uint16> tpnPool;
458         List<OdtuTpnPool> odtuTpnPoolValues = new ArrayList<>(xtpcaBldr.getOdtuTpnPool().values());
459         if (odtuTpnPoolValues.get(0).getTpnPool() == null) {
460             tpnPool = new ArrayList<>();
461         } else {
462             tpnPool = new ArrayList<>(odtuTpnPoolValues.get(0).getTpnPool());
463             if (isDeletion) {
464                 tpnPool.add(Uint16.valueOf(tribPortNb));
465             } else {
466                 tpnPool.remove(Uint16.valueOf(tribPortNb));
467             }
468         }
469         Class<? extends OdtuTypeIdentity> odtuType;
470         if (serviceRateOdtuTypeClassMap.containsKey(serviceRate)) {
471             odtuType = serviceRateOdtuTypeClassMap.get(serviceRate);
472         } else {
473             odtuType = null;
474             LOG.warn("Unable to set the odtu-type");
475         }
476         OdtuTpnPool odtuTpnPool = new OdtuTpnPoolBuilder()
477             .setOdtuType(odtuType)
478             .setTpnPool(tpnPool)
479             .build();
480         return tpBldr
481             .addAugmentation(
482                 new TerminationPoint1Builder(tp.augmentation(TerminationPoint1.class))
483                     .setXpdrTpPortConnectionAttributes(
484                         xtpcaBldr
485                             .setOdtuTpnPool(ImmutableMap.of(odtuTpnPool.key(),odtuTpnPool))
486                             .build())
487                     .build())
488             .build();
489     }
490
491     private static Map<Integer, OtnTopoNode> convertPortMappingToOtnNodeList(Nodes mappingNode) {
492
493         List<Mapping> networkMappings =
494             mappingNode.nonnullMapping().values().stream()
495                 .filter(k -> k.getLogicalConnectionPoint().contains("NETWORK"))
496                 .collect(Collectors.toList());
497         Map<Integer, OtnTopoNode> xpdrMap = new HashMap<>();
498         for (Mapping mapping : networkMappings) {
499             Integer xpdrNb = Integer.parseInt(mapping.getLogicalConnectionPoint().split("XPDR")[1].split("-")[0]);
500             if (!xpdrMap.containsKey(xpdrNb)) {
501                 List<Mapping> xpdrNetMaps =
502                     mappingNode.nonnullMapping().values().stream()
503                         .filter(k -> k.getLogicalConnectionPoint().contains("XPDR" + xpdrNb + NETWORK))
504                         .collect(Collectors.toList());
505                 List<Mapping> xpdrClMaps =
506                     mappingNode.nonnullMapping().values().stream()
507                         .filter(k -> k.getLogicalConnectionPoint().contains("XPDR" + xpdrNb + CLIENT))
508                         .collect(Collectors.toList());
509                 xpdrMap.put(
510                     xpdrNb,
511                     new OtnTopoNode(
512                         mappingNode.getNodeId(),
513                         mappingNode.getNodeInfo().getNodeClli(),
514                         xpdrNb,
515                         mapping.getXponderType() == null
516                             ? XpdrNodeTypes.Tpdr
517                             : mapping.getXponderType(),
518                         fillConnectionMapLcp(xpdrNetMaps),
519                         fillConnectionMapLcp(xpdrClMaps),
520                         xpdrNetMaps,
521                         xpdrClMaps
522                     ));
523             }
524         }
525         LOG.debug("there are {} xpdr to build", xpdrMap.size());
526         xpdrMap.forEach((k, v) -> LOG.debug("xpdr {} = {} - {} - {} - {}",
527             k, v.getNodeId(), v.getNodeType(), v.getNbTpClient(), v.getNbTpNetwork()));
528         return xpdrMap;
529     }
530
531     private static Map<String, String> fillConnectionMapLcp(List<Mapping> mappingList) {
532
533         Map<String, String> xpdrConnectionMap = new HashMap<>();
534         for (Mapping map : mappingList) {
535             xpdrConnectionMap.put(map.getLogicalConnectionPoint(), map.getConnectionMapLcp());
536         }
537         return xpdrConnectionMap;
538     }
539
540     private static Node createTpdr(OtnTopoNode node) {
541
542         // prepare ietf node augmentation to add TP list
543         Map<TerminationPointKey,TerminationPoint> tpMap = new HashMap<>();
544         createTP(tpMap, node, OpenroadmTpType.XPONDERCLIENT, false);
545         createTP(tpMap, node, OpenroadmTpType.XPONDERNETWORK, true);
546         // return ietfNode
547         return new NodeBuilder()
548             .setNodeId(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb()))
549             .withKey(new NodeKey(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb())))
550             .setSupportingNode(createSupportingNodes(node))
551             .addAugmentation(
552                 new Node1Builder()
553                     .setXpdrAttributes(
554                         new XpdrAttributesBuilder()
555                             .setXpdrNumber(Uint16.valueOf(node.getXpdrNb()))
556                             .build())
557                     .build())
558             .addAugmentation(
559                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1Builder()
560                     .setNodeType(OpenroadmNodeType.TPDR)
561                     .setOperationalState(State.InService)
562                     .setAdministrativeState(AdminStates.InService)
563                     .build())
564             .addAugmentation(
565                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
566                     .Node1Builder()
567                         .setTerminationPoint(tpMap)
568                         .build())
569             .build();
570     }
571
572     private static Node createMuxpdr(OtnTopoNode node) {
573
574         // prepare otn-topology node augmentation
575         // TODO: will need to be completed
576         Map<NonBlockingListKey, NonBlockingList> nbMap = new HashMap<>();
577         for (int i = 1; i <= node.getNbTpClient(); i++) {
578             List<TpId> tpList = new ArrayList<>();
579             tpList.add(new TpId("XPDR" + node.getXpdrNb() + CLIENT + i));
580             tpList.add(new TpId("XPDR" + node.getXpdrNb() + "-NETWORK1"));
581             NonBlockingList nbl = new NonBlockingListBuilder()
582                 .setNblNumber(Uint16.valueOf(i))
583                 .setTpList(tpList)
584                 .setAvailableInterconnectBandwidth(Uint32.valueOf(node.getNbTpNetwork() * 10L))
585                 .setInterconnectBandwidthUnit(Uint32.valueOf(1000000000))
586                 .build();
587             nbMap.put(nbl.key(),nbl);
588         }
589         OduSwitchingPools oduSwitchPool = new OduSwitchingPoolsBuilder()
590             .setSwitchingPoolNumber(Uint16.valueOf(1))
591             .setSwitchingPoolType(SwitchingPoolTypes.NonBlocking)
592             .setNonBlockingList(nbMap)
593             .build();
594         // prepare ietf node augmentation to add TP list
595         Map<TerminationPointKey, TerminationPoint> tpMap = new HashMap<>();
596         createTP(tpMap, node, OpenroadmTpType.XPONDERCLIENT, true);
597         createTP(tpMap, node, OpenroadmTpType.XPONDERNETWORK, true);
598         // return ietfNode
599         return new NodeBuilder()
600             .setNodeId(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb()))
601             .withKey(new NodeKey(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb())))
602             .setSupportingNode(createSupportingNodes(node))
603             .addAugmentation(
604                 new Node1Builder()
605                     .setTpBandwidthSharing(new TpBandwidthSharingBuilder().build())
606                     .setXpdrAttributes(
607                         new XpdrAttributesBuilder()
608                             .setXpdrNumber(Uint16.valueOf(node.getXpdrNb()))
609                             .build())
610                     .setSwitchingPools(
611                         new SwitchingPoolsBuilder()
612                             .setOduSwitchingPools(Map.of(oduSwitchPool.key(),oduSwitchPool))
613                             .build())
614                     .build())
615             .addAugmentation(
616                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1Builder()
617                     .setNodeType(OpenroadmNodeType.MUXPDR)
618                     .setAdministrativeState(AdminStates.InService)
619                     .setOperationalState(State.InService)
620                     .build())
621             .addAugmentation(
622                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
623                     .Node1Builder()
624                         .setTerminationPoint(tpMap)
625                         .build())
626             .build();
627     }
628
629     private static Node createSwitch(OtnTopoNode node) {
630
631         List<TpId> tpl = new ArrayList<>();
632         for (int i = 1; i <= node.getNbTpClient(); i++) {
633             tpl.add(new TpId("XPDR" + node.getXpdrNb() + CLIENT + i));
634         }
635         for (int i = 1; i <= node.getNbTpNetwork(); i++) {
636             tpl.add(new TpId("XPDR" + node.getXpdrNb() + NETWORK + i));
637         }
638         Map<NonBlockingListKey, NonBlockingList> nbMap = new HashMap<>();
639         NonBlockingList nbl = new NonBlockingListBuilder()
640             .setNblNumber(Uint16.valueOf(1))
641             .setTpList(tpl)
642             .build();
643         nbMap.put(nbl.key(),nbl);
644         OduSwitchingPools oduSwitchPool = new OduSwitchingPoolsBuilder()
645             .setSwitchingPoolNumber(Uint16.valueOf(1))
646             .setSwitchingPoolType(SwitchingPoolTypes.NonBlocking)
647             .setNonBlockingList(nbMap)
648             .build();
649         Map<OduSwitchingPoolsKey, OduSwitchingPools> oduSwitchPoolList = new HashMap<>();
650         oduSwitchPoolList.put(oduSwitchPool.key(),oduSwitchPool);
651         // prepare ietf node augmentation to add TP list
652         Map<TerminationPointKey, TerminationPoint> tpMap = new HashMap<>();
653         createTP(tpMap, node, OpenroadmTpType.XPONDERCLIENT, true);
654         createTP(tpMap, node, OpenroadmTpType.XPONDERNETWORK, true);
655         // return ietfNode
656         return new NodeBuilder()
657             .setNodeId(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb()))
658             .withKey(new NodeKey(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb())))
659             .setSupportingNode(createSupportingNodes(node))
660             .addAugmentation(
661                 new Node1Builder()
662                     .setTpBandwidthSharing(new TpBandwidthSharingBuilder().build())
663                     .setXpdrAttributes(
664                         new XpdrAttributesBuilder()
665                             .setXpdrNumber(Uint16.valueOf(node.getXpdrNb()))
666                             .build())
667                     .setSwitchingPools(
668                         new SwitchingPoolsBuilder()
669                             .setOduSwitchingPools(oduSwitchPoolList)
670                             .build())
671                     .build())
672             .addAugmentation(
673                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1Builder()
674                     .setNodeType(OpenroadmNodeType.SWITCH)
675                     .setOperationalState(State.InService)
676                     .setAdministrativeState(AdminStates.InService)
677                     .build())
678             .addAugmentation(
679                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
680                     .Node1Builder()
681                         .setTerminationPoint(tpMap)
682                         .build())
683             .build();
684     }
685
686     private static void createTP(Map<TerminationPointKey, TerminationPoint> tpMap,
687             OtnTopoNode node, OpenroadmTpType tpType, boolean withRate) {
688
689         List<Mapping> mappings = null;
690         switch (tpType) {
691             case XPONDERNETWORK:
692                 mappings = node.getXpdrNetMappings();
693                 break;
694             case XPONDERCLIENT:
695                 mappings = node.getXpdrClMappings();
696                 break;
697             default:
698                 LOG.error("Error with Termination Point type {}", tpType);
699                 return;
700         }
701         fillTpMap(tpMap, node, tpType, withRate, mappings);
702     }
703
704     private static void fillTpMap(Map<TerminationPointKey, TerminationPoint> tpMap, OtnTopoNode node,
705             OpenroadmTpType tpType, boolean withRate, List<Mapping> mappings) {
706
707         for (Mapping mapping : mappings) {
708             // openroadm-otn-topoology augmentation
709             Map<SupportedInterfaceCapabilityKey, SupportedInterfaceCapability> supIfMap = new HashMap<>();
710             TerminationPoint1Builder otnTp1Bldr = new TerminationPoint1Builder();
711             if (mapping.getSupportedInterfaceCapability() == null) {
712                 LOG.warn("mapping {} of node {} has no if-cap-type",
713                     mapping.getLogicalConnectionPoint(), node.getNodeId());
714             } else {
715                 XpdrTpPortConnectionAttributesBuilder xtpcaBldr = new XpdrTpPortConnectionAttributesBuilder();
716                 for (Class<? extends SupportedIfCapability> supInterCapa : mapping.getSupportedInterfaceCapability()) {
717                     SupportedInterfaceCapability supIfCapa = new SupportedInterfaceCapabilityBuilder()
718                         .withKey(new SupportedInterfaceCapabilityKey(supInterCapa))
719                         .setIfCapType(supInterCapa)
720                         .build();
721                     supIfMap.put(supIfCapa.key(), supIfCapa);
722                 }
723                 otnTp1Bldr.setTpSupportedInterfaces(
724                     new TpSupportedInterfacesBuilder()
725                         .setSupportedInterfaceCapability(supIfMap)
726                         .build()
727                 );
728                 //TODO: It is not logical to assign a priori one of the possible rate to the TP.
729                 //Would be worth assigning per default "unallocated" at the tp creation step,
730                 //and updating it with correct rate when it supports a specific service.
731                 if (withRate) {
732                     otnTp1Bldr.setXpdrTpPortConnectionAttributes(
733                         xtpcaBldr.setRate(fixRate(mapping.getSupportedInterfaceCapability())).build());
734                 }
735             }
736             setclientNwTpAttr(
737                 tpMap,
738                 node,
739                 new TpId(mapping.getLogicalConnectionPoint()),
740                 tpType,
741                 otnTp1Bldr.build(),
742                 new org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.TerminationPoint1Builder(),
743                 mapping);
744         }
745     }
746
747     private static void setclientNwTpAttr(Map<TerminationPointKey, TerminationPoint> tpMap, OtnTopoNode node, TpId tpId,
748             OpenroadmTpType tpType, TerminationPoint1 otnTp1,
749             org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.TerminationPoint1Builder tpceTp1Bldr,
750             Mapping mapping) {
751
752         switch (tpType) {
753             case XPONDERNETWORK:
754                 if (node.getXpdrNetConnectionMap().get(tpId.getValue()) != null) {
755                     tpceTp1Bldr.setAssociatedConnectionMapPort(node.getXpdrNetConnectionMap().get(tpId.getValue()));
756                 }
757                 SupportingTerminationPoint stp = new SupportingTerminationPointBuilder()
758                     .setNetworkRef(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))
759                     .setNodeRef(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb()))
760                     .setTpRef(tpId)
761                     .build();
762                 TerminationPoint ietfTpNw =
763                     buildIetfTp(tpceTp1Bldr, otnTp1, tpType, tpId, Map.of(stp.key(), stp), mapping);
764                 tpMap.put(ietfTpNw.key(),ietfTpNw);
765                 break;
766             case XPONDERCLIENT:
767                 if (node.getXpdrCliConnectionMap().get(tpId.getValue()) != null) {
768                     tpceTp1Bldr.setAssociatedConnectionMapPort(node.getXpdrCliConnectionMap().get(tpId.getValue()));
769                 }
770                 TerminationPoint ietfTpCl = buildIetfTp(tpceTp1Bldr, otnTp1, tpType, tpId, null, mapping);
771                 tpMap.put(ietfTpCl.key(),ietfTpCl);
772                 break;
773             default:
774                 LOG.error("Undefined tpType for Termination point {} of {}", tpId.getValue(), node.getNodeId());
775                 break;
776         }
777     }
778
779     private static Class<? extends OduRateIdentity> fixRate(List<Class<? extends SupportedIfCapability>> list) {
780
781         for (Class<? extends SupportedIfCapability> class1 : list) {
782             if (rateMap.containsKey(class1.getSimpleName())) {
783                 return rateMap.get(class1.getSimpleName());
784             }
785         }
786         return null;
787     }
788
789     private static Map<SupportingNodeKey,SupportingNode> createSupportingNodes(OtnTopoNode node) {
790
791         SupportingNode suppNode1 = new SupportingNodeBuilder()
792             .setNetworkRef(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))
793             .setNodeRef(new NodeId(node.getNodeId()))
794             .withKey(
795                 new SupportingNodeKey(
796                     new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID),
797                     new NodeId(node.getNodeId())))
798             .build();
799         SupportingNode suppNode2 = new SupportingNodeBuilder()
800             .setNetworkRef(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))
801             .setNodeRef(new NodeId(node.getNodeId() + XPDR + node.getXpdrNb()))
802             .withKey(
803                 new SupportingNodeKey(
804                     new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID),
805                     new NodeId(node.getNodeId() + XPDR + node.getXpdrNb())))
806             .build();
807         SupportingNode suppNode3 = new SupportingNodeBuilder()
808             .setNetworkRef(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))
809             .setNodeRef(new NodeId(node.getClli()))
810             .withKey(
811                 new SupportingNodeKey(
812                     new NetworkId(NetworkUtils.CLLI_NETWORK_ID),
813                     new NodeId(node.getClli())))
814             .build();
815         Map<SupportingNodeKey,SupportingNode> suppNodeMap = new HashMap<>();
816         suppNodeMap.put(suppNode1.key(),suppNode1);
817         suppNodeMap.put(suppNode2.key(),suppNode2);
818         suppNodeMap.put(suppNode3.key(),suppNode3);
819         return suppNodeMap;
820     }
821
822     private static TerminationPoint buildIetfTp(
823             org.opendaylight.yang.gen.v1.http.transportpce.topology.rev220123.TerminationPoint1Builder tpceTp1Bldr,
824             TerminationPoint1 otnTp1, OpenroadmTpType tpType, TpId tpId,
825             Map<SupportingTerminationPointKey, SupportingTerminationPoint> supportTpMap, Mapping mapping) {
826
827         TerminationPointBuilder ietfTpBldr = new TerminationPointBuilder();
828         if (tpceTp1Bldr.getAssociatedConnectionMapPort() != null) {
829             ietfTpBldr.addAugmentation(tpceTp1Bldr.build());
830         }
831         if (supportTpMap != null) {
832             ietfTpBldr.setSupportingTerminationPoint(supportTpMap);
833         }
834         return ietfTpBldr
835             .setTpId(tpId)
836             .withKey(new TerminationPointKey(tpId))
837             .addAugmentation(otnTp1)
838             .addAugmentation(
839                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1Builder()
840                     .setTpType(tpType)
841                     .setAdministrativeState(TopologyUtils.setNetworkAdminState(mapping.getPortAdminState()))
842                     .setOperationalState(TopologyUtils.setNetworkOperState(mapping.getPortOperState()))
843                     .build())
844             .build();
845     }
846
847     private static String formatNodeName(String nodeName, String tpName) {
848
849         return nodeName.contains(XPDR)
850                 ? nodeName
851                 : new StringBuilder(nodeName).append("-").append(tpName.split("-")[0]).toString();
852     }
853 }