Adaptation of XPDR mapping from OR to TAPI
[transportpce.git] / tapi / src / main / java / org / opendaylight / transportpce / tapi / listeners / TapiPceListenerImpl.java
1 /*
2  * Copyright © 2021 Nokia, Inc. 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.tapi.listeners;
9
10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
11 import java.nio.charset.Charset;
12 import java.util.ArrayList;
13 import java.util.Comparator;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.UUID;
19 import java.util.concurrent.ExecutionException;
20 import java.util.stream.Collectors;
21 import org.opendaylight.mdsal.binding.api.DataBroker;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.transportpce.common.network.NetworkTransactionImpl;
24 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
25 import org.opendaylight.transportpce.common.network.RequestProcessor;
26 import org.opendaylight.transportpce.tapi.TapiStringConstants;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.ServicePathRpcResult;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.TransportpcePceListener;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.service.path.rpc.result.PathDescription;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.service.path.rpc.result.PathDescriptionBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.atoz.direction.AToZ;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.Node;
33 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.TerminationPoint;
34 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev200128.RpcStatusEx;
35 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Context;
36 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.ForwardingDirection;
37 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LayerProtocolName;
38 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.PortDirection;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.PortRole;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.Name;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameBuilder;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceInput;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1Builder;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPoint;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointBuilder;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointKey;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePoint;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePointBuilder;
54 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService;
55 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder;
56 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey;
57 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.Connection;
58 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.ConnectionBuilder;
59 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.ConnectionKey;
60 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContextBuilder;
61 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepList;
62 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepListBuilder;
63 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePoint;
64 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointBuilder;
65 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointKey;
66 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.NodeKey;
67 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology;
68 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.TopologyKey;
69 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
72
73 public class TapiPceListenerImpl implements TransportpcePceListener {
74
75     private static final Logger LOG = LoggerFactory.getLogger(TapiPceListenerImpl.class);
76
77     private ServicePathRpcResult servicePathRpcResult;
78     private CreateConnectivityServiceInput input;
79     private Uuid serviceUuid;
80     private final DataBroker dataBroker;
81     private final NetworkTransactionService networkTransactionService;
82     private final Map<org.opendaylight.yang.gen.v1.urn
83         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
84         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection>
85         connectionFullMap; // this variable is for complete connection objects
86
87     public TapiPceListenerImpl(DataBroker dataBroker) {
88         this.connectionFullMap = new HashMap<>();
89         this.dataBroker = dataBroker;
90         this.networkTransactionService = new NetworkTransactionImpl(new RequestProcessor(this.dataBroker));
91     }
92
93     @Override
94     public void onServicePathRpcResult(ServicePathRpcResult notification) {
95         if (compareServicePathRpcResult(notification)) {
96             LOG.warn("ServicePathRpcResult already wired !");
97             return;
98         }
99         servicePathRpcResult = notification;
100         switch (servicePathRpcResult.getNotificationType().getIntValue()) {
101             /* path-computation-request. */
102             case 1:
103                 onPathComputationResult(notification);
104                 break;
105             /* cancel-resource-reserve. */
106             case 2:
107                 onCancelResourceResult(notification.getServiceName());
108                 break;
109             default:
110                 break;
111         }
112     }
113
114     /**
115      * Process path computation request result.
116      * @param notification the result notification.
117      */
118     private void onPathComputationResult(ServicePathRpcResult notification) {
119         this.connectionFullMap.clear();
120         LOG.info("PCE '{}' Notification received : {}",servicePathRpcResult.getNotificationType().getName(),
121                 notification);
122         if (servicePathRpcResult.getStatus() == RpcStatusEx.Failed) {
123             LOG.error("PCE path computation failed !");
124             return;
125         } else if (servicePathRpcResult.getStatus() == RpcStatusEx.Pending) {
126             LOG.warn("PCE path computation returned a Penging RpcStatusEx code!");
127             return;
128         } else if (servicePathRpcResult.getStatus() != RpcStatusEx.Successful) {
129             LOG.error("PCE path computation returned an unknown RpcStatusEx code!");
130             return;
131         }
132
133         LOG.info("PCE calculation done OK !");
134         if (servicePathRpcResult.getPathDescription() == null) {
135             LOG.error("'PathDescription' parameter is null ");
136             return;
137         }
138         PathDescription pathDescription = new PathDescriptionBuilder()
139             .setAToZDirection(servicePathRpcResult.getPathDescription().getAToZDirection())
140             .setZToADirection(servicePathRpcResult.getPathDescription().getZToADirection())
141             .build();
142         LOG.info("PathDescription for TAPI gets : {}", pathDescription);
143         if (input == null) {
144             LOG.error("Input is null !");
145             return;
146         }
147         // Create connections and ceps for the connectivity service.
148         //  Connections must be with a locked stated. As the renderer hasnt implemented yet the oc's
149         Map<ConnectionKey, Connection> connectionMap = createConnectionsAndCepsForService(pathDescription,
150                 input.getConnectivityConstraint().getServiceLayer());
151         // add connections to connection context and to connectivity context
152         updateConnectionContextWithConn(this.connectionFullMap, connectionMap, serviceUuid);
153     }
154
155     private Map<ConnectionKey, Connection> createConnectionsAndCepsForService(PathDescription pathDescription,
156                                                                               LayerProtocolName serviceProtName) {
157         Map<ConnectionKey, Connection> connectionServMap = new HashMap<>();
158         // build lists with ROADM nodes, XPDR/MUX/SWITCH nodes, ROADM DEG TTPs, ROADM SRG TTPs, XPDR CLIENT TTPs
159         //  and XPDR NETWORK TTPs (if any). From the path description. This will help to build the uuid of the CEPs
160         //  and the connections
161         String resourceType;
162         List<String> xpdrClientTplist = new ArrayList<>();
163         List<String> xpdrNetworkTplist = new ArrayList<>();
164         List<String> rdmAddDropTplist = new ArrayList<>();
165         List<String> rdmDegTplist = new ArrayList<>();
166         List<String> rdmNodelist = new ArrayList<>();
167         List<String> xpdrNodelist = new ArrayList<>();
168         for (AToZ elem:pathDescription.getAToZDirection().getAToZ().values().stream()
169                 .sorted(Comparator.comparing(AToZ::getId)).collect(Collectors.toList())) {
170             resourceType = elem.getResource().getResource().implementedInterface().getSimpleName();
171             switch (resourceType) {
172                 case TapiStringConstants.TP:
173                     TerminationPoint tp = (TerminationPoint) elem.getResource().getResource();
174                     String tpID = tp.getTpId();
175                     String tpNode;
176                     if (tpID.contains("CLIENT")) {
177                         tpNode = tp.getTpNodeId();
178                         if (!xpdrClientTplist.contains(String.join("+", tpNode, tpID))) {
179                             xpdrClientTplist.add(String.join("+", tpNode, tpID));
180                         }
181                     }
182                     if (tpID.contains("NETWORK")) {
183                         tpNode = tp.getTpNodeId();
184                         if (!xpdrNetworkTplist.contains(String.join("+", tpNode, tpID))) {
185                             xpdrNetworkTplist.add(String.join("+", tpNode, tpID));
186                         }
187                     }
188                     if (tpID.contains("PP")) {
189                         tpNode = getIdBasedOnModelVersion(tp.getTpNodeId());
190                         LOG.info("ROADM Node of tp = {}", tpNode);
191                         if (!rdmAddDropTplist.contains(String.join("+", tpNode, tpID))) {
192                             rdmAddDropTplist.add(String.join("+", tpNode, tpID));
193                         }
194                     }
195                     if (tpID.contains("TTP")) {
196                         tpNode = getIdBasedOnModelVersion(tp.getTpNodeId());
197                         LOG.info("ROADM Node of tp = {}", tpNode);
198                         if (!rdmDegTplist.contains(String.join("+", tpNode, tpID))) {
199                             rdmDegTplist.add(String.join("+", tpNode, tpID));
200                         }
201                     }
202                     break;
203                 case TapiStringConstants.NODE:
204                     Node node = (Node) elem.getResource().getResource();
205                     String nodeId = node.getNodeId();
206                     if (nodeId.contains("XPDR") || nodeId.contains("SPDR") || nodeId.contains("MXPDR")) {
207                         LOG.info("Node id = {}", nodeId);
208                         if (!xpdrNodelist.contains(nodeId)) {
209                             xpdrNodelist.add(nodeId); // should contain only 2
210                         }
211                     }
212                     if (nodeId.contains("ROADM")) {
213                         nodeId = getIdBasedOnModelVersion(nodeId);
214                         LOG.info("Node id = {}", nodeId);
215                         if (!rdmNodelist.contains(nodeId)) {
216                             rdmNodelist.add(nodeId);
217                         }
218                     }
219                     break;
220                 default:
221                     LOG.warn("Resource is a {}", resourceType);
222             }
223         }
224         LOG.info("ROADM node list = {}", rdmNodelist.toString());
225         LOG.info("ROADM degree list = {}", rdmDegTplist.toString());
226         LOG.info("ROADM addrop list = {}", rdmAddDropTplist.toString());
227         LOG.info("XPDR node list = {}", xpdrNodelist.toString());
228         LOG.info("XPDR network list = {}", xpdrNetworkTplist.toString());
229         LOG.info("XPDR client list = {}", xpdrClientTplist.toString());
230         // TODO -> for 10GB eth and ODU services there are no ROADMs in path description as they use the OTU link,
231         //  but for 100GB eth all is created at once. Check if the roadm list is empty to determine whether we need
232         //  to trigger all the steps or not
233         String edgeRoadm1 = "";
234         String edgeRoadm2 = "";
235         if (!rdmNodelist.isEmpty()) {
236             edgeRoadm1 = rdmNodelist.get(0);
237             edgeRoadm2 = rdmNodelist.get(rdmNodelist.size() - 1);
238             LOG.info("edgeRoadm1 = {}", edgeRoadm1);
239             LOG.info("edgeRoadm2 = {}", edgeRoadm2);
240         }
241         // create corresponding CEPs and Connections. Connections should be added to the corresponding context
242         // CEPs must be included in the topology context as an augmentation for each ONEP!!
243         // TODO -> Maybe we dont need to create the connections and ceps if the previous service doesnt exist??
244         //  As mentioned above, for 100GbE service creation there are ROADMs in the path description.
245         //  What are the configurations needed here? No OTU, ODU... what kind of cross connections is needed?
246         //  this needs to be changed
247         switch (serviceProtName) {
248             case PHOTONICMEDIA:
249                 // Identify number of ROADMs
250                 // - XC Connection between MC CEPs mapped from MC NEPs (within a roadm)
251                 // - XC Connection between OTSiMC CEPs mapped from OTSiMC NEPs (within a roadm)
252                 // - Top Connection MC betwwen MC CEPs of different roadms
253                 // - Top Connection OTSiMC betwwen OTSiMC CEPs of extreme roadms
254                 connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
255                         edgeRoadm1, edgeRoadm2));
256                 if (!pathDescription.getAToZDirection().getAToZ().values().stream().findFirst().get().getId()
257                         .contains("ROADM")) {
258                     // - XC Connection OTSi betwwen iOTSi y eOTSi of xpdr
259                     // - Top connection OTSi between network ports of xpdrs in the Photonic media layer -> i_OTSi
260                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
261                 }
262                 break;
263             case ODU:
264                 // Check if OC and OTU are created
265                 if (!rdmNodelist.isEmpty()) {
266                     connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
267                         edgeRoadm1, edgeRoadm2));
268                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
269                 }
270                 // - XC Connection OTSi betwwen iODU and eODU of xpdr
271                 // - Top connection in the ODU layer, between xpdr iODU ports (?)
272                 connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
273                 break;
274             case DSR:
275                 // Check if OC, OTU and ODU are created
276                 // Check if OC, OTU and ODU are created
277                 // TODO differentiate between 100GbE and OTN 10GbE services
278                 if (!rdmNodelist.isEmpty()) {
279                     connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
280                         edgeRoadm1, edgeRoadm2));
281                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
282                     connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
283                 }
284                 // Top connection in the DSR layer, between client ports of the xpdrs
285                 connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist,
286                     xpdrNodelist));
287                 break;
288             default:
289                 LOG.error("Service type format {} not supported", serviceProtName.getName());
290         }
291         return connectionServMap;
292     }
293
294     /**
295      * Process cancel resource result.
296      * @param serviceName Service name to build uuid.
297      */
298     private void onCancelResourceResult(String serviceName) {
299         if (servicePathRpcResult.getStatus() == RpcStatusEx.Failed) {
300             LOG.info("PCE cancel resource failed !");
301             return;
302         } else if (servicePathRpcResult.getStatus() == RpcStatusEx.Pending) {
303             LOG.warn("PCE cancel returned a Penging RpcStatusEx code!");
304             return;
305         } else if (servicePathRpcResult.getStatus() != RpcStatusEx.Successful) {
306             LOG.error("PCE cancel returned an unknown RpcStatusEx code!");
307             return;
308         }
309         LOG.info("PCE cancel resource done OK !");
310         Uuid suuid = new Uuid(UUID.nameUUIDFromBytes(serviceName.getBytes(Charset.forName("UTF-8")))
311                 .toString());
312         // get connections of connectivity service and remove them from tapi context and then remove
313         //  service from context. The CEPs are maintained as they could be reused by another service
314         ConnectivityService connService = getConnectivityService(suuid);
315         if (connService == null) {
316             LOG.error("Service doesnt exist in tapi context");
317             return;
318         }
319         for (Connection connection:connService.getConnection().values()) {
320             deleteConnection(connection.getConnectionUuid());
321         }
322         deleteConnectivityService(suuid);
323     }
324
325     @SuppressFBWarnings(
326             value = "ES_COMPARING_STRINGS_WITH_EQ",
327             justification = "false positives, not strings but real object references comparisons")
328     private Boolean compareServicePathRpcResult(ServicePathRpcResult notification) {
329         if (servicePathRpcResult == null) {
330             return false;
331         }
332         if (servicePathRpcResult.getNotificationType() != notification.getNotificationType()) {
333             return false;
334         }
335         if (servicePathRpcResult.getServiceName() != notification.getServiceName()) {
336             return false;
337         }
338         if (servicePathRpcResult.getStatus() != notification.getStatus()) {
339             return false;
340         }
341         if (servicePathRpcResult.getStatusMessage() != notification.getStatusMessage()) {
342             return false;
343         }
344         return true;
345     }
346
347     private Map<ConnectionKey,Connection> createXpdrCepsAndConnectionsDsr(List<String> xpdrClientTplist,
348                                                                           List<String> xpdrNetworkTplist,
349                                                                           List<String> xpdrNodelist) {
350         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
351         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
352             ConnectionEndPoint> cepMapDsr = new HashMap<>();
353         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
354             ConnectionEndPoint> cepMapOdu = new HashMap<>();
355
356         // Create 1 cep per Xpdr in the CLIENT, 1 cep per Xpdr eODU, 1 XC between eODU and iODE,
357         // 1 top connection between eODU and a top connection DSR between the CLIENT xpdrs
358         for (String xpdr:xpdrNodelist) {
359             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
360             String spcXpdrClient = xpdrClientTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get();
361
362             ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR,
363                 LayerProtocolName.DSR);
364             putXpdrCepInTopologyContext(xpdr, spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR, netCep1);
365
366             ConnectionEndPoint netCep2 = createCepXpdr(spcXpdrClient, TapiStringConstants.E_ODU,
367                 TapiStringConstants.DSR, LayerProtocolName.ODU);
368             putXpdrCepInTopologyContext(xpdr, spcXpdrClient, TapiStringConstants.E_ODU, TapiStringConstants.DSR,
369                 netCep2);
370
371             String spcXpdrNetwork = getAssociatedNetworkPort(spcXpdrClient, xpdrNetworkTplist);
372             ConnectionEndPoint netCep3 = getAssociatediODUCep(spcXpdrNetwork);
373
374             cepMapDsr.put(netCep1.key(), netCep1);
375             cepMapOdu.put(netCep2.key(), netCep2);
376             // Create x connection between I_ODU and E_ODU within xpdr
377             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
378                 connection = createXCBetweenCeps(netCep2, netCep3, spcXpdrClient, spcXpdrNetwork,
379                 TapiStringConstants.ODU, LayerProtocolName.ODU);
380             this.connectionFullMap.put(connection.key(), connection);
381
382             // Create X connection that will be added to the service object
383             Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
384             connServMap.put(conn.key(), conn);
385         }
386
387         // DSR top connection between edge xpdr CLIENT DSR
388         String spcXpdr1 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist
389             .get(0))).findFirst().get();
390         String spcXpdr2 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist
391             .get(xpdrNodelist.size() - 1))).findFirst().get();
392
393         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
394             connectionOdu = createTopConnection(spcXpdr1, spcXpdr2, cepMapOdu, TapiStringConstants.E_ODU,
395             LayerProtocolName.ODU);
396         this.connectionFullMap.put(connectionOdu.key(), connectionOdu);
397
398         // ODU top connection that will be added to the service object
399         Connection conn = new ConnectionBuilder().setConnectionUuid(connectionOdu.getUuid()).build();
400         connServMap.put(conn.key(), conn);
401
402         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
403             connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR,
404             LayerProtocolName.DSR);
405         this.connectionFullMap.put(connectionDsr.key(), connectionDsr);
406
407         // DSR top connection that will be added to the service object
408         Connection conn1 = new ConnectionBuilder().setConnectionUuid(connectionDsr.getUuid()).build();
409         connServMap.put(conn1.key(), conn1);
410
411         return connServMap;
412     }
413
414     private Map<ConnectionKey, Connection> createXpdrCepsAndConnectionsOdu(List<String> xpdrNetworkTplist,
415                                                                            List<String> xpdrNodelist) {
416         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
417         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
418             ConnectionEndPoint> cepMap = new HashMap<>();
419         // Create 1 cep per Xpdr in the I_ODU and a top
420         // connection iODU between the xpdrs
421         for (String xpdr:xpdrNodelist) {
422             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
423             String spcXpdrNetwork = xpdrNetworkTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get();
424
425             ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.I_ODU,
426                 TapiStringConstants.DSR, LayerProtocolName.ODU);
427             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.I_ODU, TapiStringConstants.DSR,
428                 netCep1);
429
430             cepMap.put(netCep1.key(), netCep1);
431         }
432
433         // ODU top connection between edge xpdr i_ODU
434         String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
435             .get(0))).findFirst().get();
436         String spcXpdr2 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
437             .get(xpdrNodelist.size() - 1))).findFirst().get();
438         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
439             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_ODU,
440             LayerProtocolName.ODU);
441         this.connectionFullMap.put(connection.key(), connection);
442
443         // ODU top connection that will be added to the service object
444         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
445         connServMap.put(conn.key(), conn);
446
447         return connServMap;
448     }
449
450     private Map<ConnectionKey, Connection> createXpdrCepsAndConnectionsPht(List<String> xpdrNetworkTplist,
451                                                                            List<String> xpdrNodelist) {
452         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
453         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
454             ConnectionEndPoint> cepMap = new HashMap<>();
455
456         // create ceps and x connections within xpdr
457         for (String xpdr:xpdrNodelist) {
458             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
459             String spcXpdrNetwork = xpdrNetworkTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get();
460             // There should be 1 network tp per xpdr
461             // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
462             //  3 different MC CEPs giving different IDs to show that they are different
463             // Create 3 CEPs for each xpdr otsi node and the corresponding cross connection matchin the NEPs
464             ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.PHTNC_MEDIA,
465                 TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
466             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.PHTNC_MEDIA, TapiStringConstants.OTSI,
467                 netCep1);
468             ConnectionEndPoint netCep2 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.E_OTSI,
469                 TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
470             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.E_OTSI, TapiStringConstants.OTSI,
471                 netCep2);
472             ConnectionEndPoint netCep3 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.I_OTSI,
473                 TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
474             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.I_OTSI, TapiStringConstants.OTSI,
475                 netCep3);
476             cepMap.put(netCep1.key(), netCep1);
477             cepMap.put(netCep2.key(), netCep2);
478             cepMap.put(netCep3.key(), netCep3);
479
480             // Create x connection between I_OTSi and E_OTSi within xpdr
481             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
482                 connection = createXCBetweenCeps(netCep2, netCep3, spcXpdrNetwork, spcXpdrNetwork,
483                 TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
484             this.connectionFullMap.put(connection.key(), connection);
485
486             // Create X connection that will be added to the service object
487             Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
488             connServMap.put(conn.key(), conn);
489         }
490         // OTSi top connection between edge I_OTSI Xpdr
491         String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
492             .get(0))).findFirst().get();
493         String spcXpdr2 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
494             .get(xpdrNodelist.size() - 1))).findFirst().get();
495         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
496             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_OTSI,
497             LayerProtocolName.PHOTONICMEDIA);
498         this.connectionFullMap.put(connection.key(), connection);
499
500         // OTSi top connection that will be added to the service object
501         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
502         connServMap.put(conn.key(), conn);
503
504
505         return connServMap;
506     }
507
508     private Map<ConnectionKey, Connection> createRoadmCepsAndConnections(List<String> rdmAddDropTplist,
509                                                                          List<String> rdmDegTplist,
510                                                                          List<String> rdmNodelist,
511                                                                          String edgeRoadm1, String edgeRoadm2) {
512         // TODO: will need to check if things exist already or not
513         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
514         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
515             ConnectionEndPoint> cepMap = new HashMap<>();
516         // create ceps and x connections within roadm
517         for (String roadm : rdmNodelist) {
518             LOG.info("Creating ceps and xc for roadm {}", roadm);
519             String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
520             LOG.info("AD port of ROADm {} = {}", roadm, spcRdmAD);
521             // There should be only 1 AD and 1 DEG per roadm
522             // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
523             //  3 different MC CEPs giving different IDs to show that they are different
524             // Create 3 CEPs for each AD and DEG and the corresponding cross connections, matching the NEPs
525             // created in the topology creation
526             // add CEPs to the topology to the corresponding ONEP
527             ConnectionEndPoint adCep1 = createCepRoadm(spcRdmAD, TapiStringConstants.PHTNC_MEDIA);
528             putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.PHTNC_MEDIA, adCep1);
529             ConnectionEndPoint adCep2 = createCepRoadm(spcRdmAD, TapiStringConstants.MC);
530             putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.MC, adCep2);
531             ConnectionEndPoint adCep3 = createCepRoadm(spcRdmAD, TapiStringConstants.OTSI_MC);
532             putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.OTSI_MC, adCep3);
533             cepMap.put(adCep1.key(), adCep1);
534             cepMap.put(adCep2.key(), adCep2);
535             cepMap.put(adCep3.key(), adCep3);
536
537             String spcRdmDEG = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
538             LOG.info("Degree port of ROADm {} = {}", roadm, spcRdmDEG);
539
540             ConnectionEndPoint degCep1 = createCepRoadm(spcRdmDEG, TapiStringConstants.PHTNC_MEDIA);
541             putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.PHTNC_MEDIA, degCep1);
542             ConnectionEndPoint degCep2 = createCepRoadm(spcRdmDEG, TapiStringConstants.MC);
543             putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.MC, degCep2);
544             ConnectionEndPoint degCep3 = createCepRoadm(spcRdmDEG, TapiStringConstants.OTSI_MC);
545             putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.OTSI_MC, degCep3);
546             cepMap.put(degCep1.key(), degCep1);
547             cepMap.put(degCep2.key(), degCep2);
548             cepMap.put(degCep3.key(), degCep3);
549
550             LOG.info("Going to create cross connections for ROADM {}", roadm);
551             // Create X connections between MC and OTSi_MC for full map
552             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
553                 connection1 = createXCBetweenCeps(adCep2, degCep2, spcRdmAD, spcRdmDEG, TapiStringConstants.MC,
554                 LayerProtocolName.PHOTONICMEDIA);
555             LOG.info("Cross connection 1 created = {}", connection1.toString());
556             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
557                 connection2 = createXCBetweenCeps(adCep3, degCep3, spcRdmAD, spcRdmDEG, TapiStringConstants.OTSI_MC,
558                 LayerProtocolName.PHOTONICMEDIA);
559             LOG.info("Cross connection 2 created = {}", connection2.toString());
560             this.connectionFullMap.put(connection1.key(), connection1);
561             this.connectionFullMap.put(connection2.key(), connection2);
562
563             // Create X connections that will be added to the service object
564             Connection conn1 = new ConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
565             Connection conn2 = new ConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
566             connServMap.put(conn1.key(), conn1);
567             connServMap.put(conn2.key(), conn2);
568         }
569         LOG.info("Going to create top connections betwee roadms");
570         // create top connections between roadms: MC connections between AD MC CEPs of roadms
571         for (int i = 0; i < rdmNodelist.size(); i++) {
572             if (rdmNodelist.size() <= (i + 1)) {
573                 LOG.info("Reached last roadm. No more MC connections");
574                 break;
575             }
576             // Current roadm with roadm i + 1 --> MC
577             String roadm1 = rdmNodelist.get(i);
578             String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm1)).findFirst().get();
579             String roadm2 = rdmNodelist.get(i + 1);
580             String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm2)).findFirst().get();
581             LOG.info("Creating top connection from {} to {} between tps: {}-{}", roadm1, roadm2, spcRdmAD1, spcRdmAD2);
582
583             // Create top connections between MC for full map
584             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
585                 connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC,
586                 LayerProtocolName.PHOTONICMEDIA);
587             this.connectionFullMap.put(connection.key(), connection);
588             LOG.info("Top connection created = {}", connection.toString());
589
590             // Create top connections that will be added to the service object
591             Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
592             connServMap.put(conn.key(), conn);
593         }
594
595         // OTSiMC top connection between edge roadms
596         LOG.info("Going to created top connection between OTSiMC");
597         String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm1)).findFirst().get();
598         String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm2)).findFirst().get();
599         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
600             connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC,
601             LayerProtocolName.PHOTONICMEDIA);
602         this.connectionFullMap.put(connection.key(), connection);
603         LOG.info("Top connection created = {}", connection.toString());
604
605         // OTSiMC top connections that will be added to the service object
606         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
607         connServMap.put(conn.key(), conn);
608         return connServMap;
609     }
610
611     private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
612             createTopConnection(String tp1, String tp2,
613                         Map<org.opendaylight.yang.gen.v1.urn
614                                 .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
615                                 ConnectionEndPoint> cepMap, String qual, LayerProtocolName topPortocol) {
616         // find cep for each AD MC of roadm 1 and 2
617         LOG.info("Top connection name = {}", String.join("+", "TOP", tp1, tp2, qual));
618         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep1 =
619             cepMap.get(new org.opendaylight.yang.gen.v1.urn
620                 .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
621                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp1.split("\\+")[0],
622                     qual, tp1.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
623                     .toString())));
624         LOG.info("ADCEP1 = {}", adCep1.toString());
625         org.opendaylight.yang.gen.v1.urn
626             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep1 =
627             new org.opendaylight.yang.gen.v1.urn
628                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
629                 .setNodeEdgePointUuid(adCep1.getClientNodeEdgePoint()
630                     .values().stream().findFirst().get().getNodeEdgePointUuid())
631                 .setTopologyUuid(adCep1.getClientNodeEdgePoint()
632                     .values().stream().findFirst().get().getTopologyUuid())
633                 .setNodeUuid(adCep1.getClientNodeEdgePoint()
634                     .values().stream().findFirst().get().getNodeUuid())
635                 .setConnectionEndPointUuid(adCep1.getUuid())
636                 .build();
637         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep2 =
638             cepMap.get(new org.opendaylight.yang.gen.v1.urn
639                 .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
640                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp2.split("\\+")[0],
641                     qual, tp2.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
642                     .toString())));
643         LOG.info("ADCEP2 = {}", adCep2.toString());
644         org.opendaylight.yang.gen.v1.urn
645             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep2 =
646             new org.opendaylight.yang.gen.v1.urn
647                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
648                 .setNodeEdgePointUuid(adCep2.getClientNodeEdgePoint()
649                     .values().stream().findFirst().get().getNodeEdgePointUuid())
650                 .setTopologyUuid(adCep2.getClientNodeEdgePoint()
651                     .values().stream().findFirst().get().getTopologyUuid())
652                 .setNodeUuid(adCep2.getClientNodeEdgePoint()
653                     .values().stream().findFirst().get().getNodeUuid())
654                 .setConnectionEndPointUuid(adCep1.getUuid())
655                 .build();
656         Map<ConnectionEndPointKey, org.opendaylight.yang.gen.v1.urn
657             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint> ceps = new HashMap<>();
658         ceps.put(cep1.key(), cep1);
659         ceps.put(cep2.key(), cep2);
660         Name connName = new NameBuilder()
661             .setValueName("Connection name")
662             .setValue(String.join("+", "TOP", tp1, tp2, qual))
663             .build();
664         // TODO: lower connection, supported link.......
665         return new org.opendaylight.yang.gen.v1.urn
666             .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
667             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "TOP", tp1, tp2, qual))
668                 .getBytes(Charset.forName("UTF-8"))).toString()))
669             .setName(Map.of(connName.key(), connName))
670             .setConnectionEndPoint(ceps)
671             .setOperationalState(OperationalState.DISABLED)
672             .setLayerProtocolName(topPortocol)
673             .setLifecycleState(LifecycleState.POTENTIALAVAILABLE)
674             .setDirection(ForwardingDirection.BIDIRECTIONAL)
675             .build();
676     }
677
678     private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
679             createXCBetweenCeps(ConnectionEndPoint cep1, ConnectionEndPoint cep2, String tp1, String tp2, String qual,
680                         LayerProtocolName xcProtocol) {
681         LOG.info("Creation cross connection between: {} and {}", tp1, tp2);
682         LOG.info("Cross connection name = {}", String.join("+", "XC", tp1, tp2, qual));
683         LOG.info("CEP1 = {}", cep1.getClientNodeEdgePoint().toString());
684         LOG.info("CEP2 = {}", cep2.getClientNodeEdgePoint().toString());
685         org.opendaylight.yang.gen.v1.urn
686             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ1 =
687             new org.opendaylight.yang.gen.v1.urn
688                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
689                 .setNodeEdgePointUuid(cep1.getClientNodeEdgePoint()
690                     .values().stream().findFirst().get().getNodeEdgePointUuid())
691                 .setTopologyUuid(cep1.getClientNodeEdgePoint()
692                     .values().stream().findFirst().get().getTopologyUuid())
693                 .setNodeUuid(cep1.getClientNodeEdgePoint()
694                     .values().stream().findFirst().get().getNodeUuid())
695                 .setConnectionEndPointUuid(cep1.getUuid())
696                 .build();
697         org.opendaylight.yang.gen.v1.urn
698             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ2 =
699             new org.opendaylight.yang.gen.v1.urn
700                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
701                 .setNodeEdgePointUuid(cep2.getClientNodeEdgePoint()
702                     .values().stream().findFirst().get().getNodeEdgePointUuid())
703                 .setTopologyUuid(cep2.getClientNodeEdgePoint()
704                     .values().stream().findFirst().get().getTopologyUuid())
705                 .setNodeUuid(cep2.getClientNodeEdgePoint()
706                     .values().stream().findFirst().get().getNodeUuid())
707                 .setConnectionEndPointUuid(cep2.getUuid())
708                 .build();
709         Map<ConnectionEndPointKey, org.opendaylight.yang.gen.v1.urn
710             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint> ceps = new HashMap<>();
711         ceps.put(cepServ1.key(), cepServ1);
712         ceps.put(cepServ2.key(), cepServ2);
713         Name connName = new NameBuilder()
714             .setValueName("Connection name")
715             .setValue(String.join("+", "XC", tp1, tp2, qual))
716             .build();
717         // TODO: lower connection, supported link.......
718         return new org.opendaylight.yang.gen.v1.urn
719             .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
720             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "XC", tp1, tp2, qual))
721                 .getBytes(Charset.forName("UTF-8"))).toString()))
722             .setName(Map.of(connName.key(), connName))
723             .setConnectionEndPoint(ceps)
724             .setOperationalState(OperationalState.DISABLED)
725             .setLayerProtocolName(xcProtocol)
726             .setLifecycleState(LifecycleState.POTENTIALAVAILABLE)
727             .setDirection(ForwardingDirection.BIDIRECTIONAL)
728             .build();
729     }
730
731     private ConnectionEndPoint createCepRoadm(String id, String qualifier) {
732         LOG.info("NEP = {}", String.join("+", id.split("\\+")[0], qualifier, id.split("\\+")[1]));
733         Name cepName = new NameBuilder()
734             .setValueName("ConnectionEndPoint name")
735             .setValue(String.join("+", id.split("\\+")[0], qualifier,
736                 id.split("\\+")[1]))
737             .build();
738         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
739             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
740                 qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
741                 .toString()))
742             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
743                 qualifier)).getBytes(Charset.forName("UTF-8")))
744                 .toString()))
745             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
746                 .getBytes(Charset.forName("UTF-8"))).toString()))
747             .build();
748         // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...)
749         // TODO: add parent ONEP??
750         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
751             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
752                 qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
753                 .toString()))
754             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
755             .setName(Map.of(cepName.key(), cepName))
756             .setConnectionPortRole(PortRole.SYMMETRIC)
757             .setConnectionPortDirection(PortDirection.BIDIRECTIONAL)
758             .setOperationalState(OperationalState.ENABLED)
759             .setLifecycleState(LifecycleState.INSTALLED)
760             .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA);
761         return cepBldr.build();
762     }
763
764     private ConnectionEndPoint createCepXpdr(String id, String qualifier, String nodeLayer,
765                                              LayerProtocolName cepProtocol) {
766         Name cepName = new NameBuilder()
767             .setValueName("ConnectionEndPoint name")
768             .setValue(String.join("+", id.split("\\+")[0], qualifier,
769                 id.split("\\+")[1]))
770             .build();
771         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
772             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
773                 qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
774                 .toString()))
775             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
776                 nodeLayer)).getBytes(Charset.forName("UTF-8")))
777                 .toString()))
778             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
779                 .getBytes(Charset.forName("UTF-8"))).toString()))
780             .build();
781         // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...)
782         // TODO: add parent ONEP??
783         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
784             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
785                 qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
786                 .toString()))
787             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
788             .setName(Map.of(cepName.key(), cepName))
789             .setConnectionPortRole(PortRole.SYMMETRIC)
790             .setConnectionPortDirection(PortDirection.BIDIRECTIONAL)
791             .setOperationalState(OperationalState.ENABLED)
792             .setLifecycleState(LifecycleState.INSTALLED)
793             .setLayerProtocolName(cepProtocol);
794         return cepBldr.build();
795     }
796
797     private void putRdmCepInTopologyContext(String node, String spcRdmAD, String qual, ConnectionEndPoint cep) {
798         LOG.info("NEP id before Merge = {}", String.join("+", node, qual, spcRdmAD.split("\\+")[1]));
799         LOG.info("Node of NEP id before Merge = {}", String.join("+", node, TapiStringConstants.PHTNC_MEDIA));
800         // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep
801         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
802             .getBytes(Charset.forName("UTF-8"))).toString());
803         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, TapiStringConstants.PHTNC_MEDIA)
804             .getBytes(Charset.forName("UTF-8"))).toString());
805         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcRdmAD.split("\\+")[1])
806             .getBytes(Charset.forName("UTF-8"))).toString());
807         updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep);
808     }
809
810     private void putXpdrCepInTopologyContext(String node, String spcXpdrNet, String qual, String nodeLayer,
811                                              ConnectionEndPoint cep) {
812         // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep
813         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
814             .getBytes(Charset.forName("UTF-8"))).toString());
815         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, nodeLayer)
816             .getBytes(Charset.forName("UTF-8"))).toString());
817         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcXpdrNet.split("\\+")[1])
818             .getBytes(Charset.forName("UTF-8"))).toString());
819         updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep);
820     }
821
822     public void updateTopologyWithCep(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid, ConnectionEndPoint cep) {
823         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
824         InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
825             .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1.class)
826             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class)
827             .child(Topology.class, new TopologyKey(topoUuid))
828             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class,
829                 new NodeKey(nodeUuid))
830             .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid))
831             .build();
832         try {
833             Optional<OwnedNodeEdgePoint> optionalOnep = this.networkTransactionService.read(
834                 LogicalDatastoreType.OPERATIONAL, onepIID).get();
835             if (!optionalOnep.isPresent()) {
836                 LOG.error("ONEP is not present in datastore");
837                 return;
838             }
839             OwnedNodeEdgePoint onep = optionalOnep.get();
840             LOG.info("ONEP found = {}", onep.toString());
841             // TODO -> If cep exists -> skip merging to datasore
842             OwnedNodeEdgePoint1 onep1 = onep.augmentation(OwnedNodeEdgePoint1.class);
843             if (onep1 != null && onep1.getCepList() != null && onep1.getCepList().getConnectionEndPoint() != null) {
844                 if (onep1.getCepList().getConnectionEndPoint().containsKey(
845                     new org.opendaylight.yang.gen.v1
846                         .urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(cep.key()))) {
847                     LOG.info("CEP already in topology, skipping merge");
848                     return;
849                 }
850             }
851             // Updated ONEP
852             CepList cepList = new CepListBuilder().setConnectionEndPoint(Map.of(cep.key(), cep)).build();
853             OwnedNodeEdgePoint1 onep1Bldr = new OwnedNodeEdgePoint1Builder().setCepList(cepList).build();
854             OwnedNodeEdgePoint newOnep = new OwnedNodeEdgePointBuilder(onep)
855                 .addAugmentation(onep1Bldr)
856                 .build();
857             LOG.info("New ONEP is {}", newOnep.toString());
858             // merge in datastore
859             this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, onepIID,
860                 newOnep);
861             this.networkTransactionService.commit().get();
862             LOG.info("CEP added successfully.");
863         } catch (InterruptedException | ExecutionException e) {
864             LOG.error("Couldnt update cep in topology", e);
865         }
866     }
867
868     private void updateConnectionContextWithConn(
869             Map<org.opendaylight.yang.gen.v1.urn
870                 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
871                 org.opendaylight.yang.gen.v1.urn
872                     .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connFullMap,
873             Map<ConnectionKey, Connection> connMap, Uuid suuid) {
874         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
875         try {
876             ConnectivityService connServ = getConnectivityService(suuid);
877             ConnectivityService updtConnServ = new ConnectivityServiceBuilder(connServ)
878                     .setConnection(connMap)
879                     .build();
880
881             // Perform the merge operation with the new conn service and the connection context updated
882             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext
883                     connectivityContext = new ConnectivityContextBuilder()
884                     .setConnectivityService(Map.of(updtConnServ.key(), updtConnServ))
885                     .setConnection(connFullMap)
886                     .build();
887             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
888                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> connectivitycontextIID =
889                     InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
890                             .child(org.opendaylight.yang.gen.v1.urn
891                                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
892                             .build();
893             // merge in datastore
894             this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connectivitycontextIID,
895                     connectivityContext);
896             this.networkTransactionService.commit().get();
897             LOG.info("TAPI connectivity merged successfully.");
898         } catch (InterruptedException | ExecutionException e) {
899             LOG.error("Failed to merge TAPI connectivity", e);
900         }
901     }
902
903     private ConnectivityService getConnectivityService(Uuid suuid) {
904         try {
905         // First read connectivity service with service uuid and update info
906             InstanceIdentifier<ConnectivityService> connectivityServIID =
907                 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
908                         .child(org.opendaylight.yang.gen.v1.urn
909                                 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
910                         .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
911                         .build();
912
913             Optional<ConnectivityService> optConnServ =
914                 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityServIID).get();
915             if (!optConnServ.isPresent()) {
916                 LOG.error("Connectivity service not found in tapi context");
917                 return null;
918             }
919             return optConnServ.get();
920         } catch (InterruptedException | ExecutionException e) {
921             LOG.error("Connectivity service not found in tapi context. Error:", e);
922             return null;
923         }
924     }
925
926     private void deleteConnectivityService(Uuid suuid) {
927         // First read connectivity service with service uuid and update info
928         InstanceIdentifier<ConnectivityService> connectivityServIID =
929                 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
930                         .child(org.opendaylight.yang.gen.v1.urn
931                                 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
932                         .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
933                         .build();
934         try {
935             this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectivityServIID);
936             this.networkTransactionService.commit().get();
937         } catch (InterruptedException | ExecutionException e) {
938             LOG.error("Failed to delete TAPI connectivity service", e);
939         }
940     }
941
942     private void deleteConnection(Uuid connectionUuid) {
943         // First read connectivity service with service uuid and update info
944         InstanceIdentifier<org.opendaylight.yang.gen.v1
945                 .urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connectionIID =
946                 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
947                         .child(org.opendaylight.yang.gen.v1.urn
948                                 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
949                         .child(org.opendaylight.yang.gen.v1.urn
950                                 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class,
951                                 new org.opendaylight.yang.gen.v1.urn
952                                         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey(
953                                                 connectionUuid))
954                         .build();
955         try {
956             this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectionIID);
957             this.networkTransactionService.commit().get();
958         } catch (InterruptedException | ExecutionException e) {
959             LOG.error("Failed to delete TAPI connection", e);
960         }
961     }
962
963     private String getIdBasedOnModelVersion(String nodeid) {
964         return nodeid.matches("[A-Z]{5}-[A-Z0-9]{2}-.*")
965             ? String.join("-", nodeid.split("-")[0], nodeid.split("-")[1]) : nodeid.split("-")[0];
966     }
967
968     private ConnectionEndPoint getAssociatediODUCep(String spcXpdrNetwork) {
969         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
970             .getBytes(Charset.forName("UTF-8"))).toString());
971         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", spcXpdrNetwork.split("\\+")[0],
972             TapiStringConstants.DSR).getBytes(Charset.forName("UTF-8")))).toString());
973         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", spcXpdrNetwork.split("\\+")[0],
974                 TapiStringConstants.I_ODU, spcXpdrNetwork.split("\\+")[1]).getBytes(Charset.forName("UTF-8"))))
975             .toString());
976         Uuid cepUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP",
977             spcXpdrNetwork.split("\\+")[0], TapiStringConstants.I_ODU, spcXpdrNetwork.split("\\+")[1]))
978             .getBytes(Charset.forName("UTF-8"))).toString());
979         InstanceIdentifier<OwnedNodeEdgePoint> nepIID = InstanceIdentifier.builder(Context.class)
980             .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1.class)
981             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class)
982             .child(Topology.class, new TopologyKey(topoUuid))
983             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class,
984                 new NodeKey(nodeUuid)).child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid)).build();
985         try {
986             Optional<OwnedNodeEdgePoint> optNode = this.networkTransactionService
987                 .read(LogicalDatastoreType.OPERATIONAL, nepIID).get();
988             if (!optNode.isPresent()) {
989                 LOG.error("Node is not present in datastore");
990                 return null;
991             }
992             if (optNode.get().augmentation(OwnedNodeEdgePoint1.class) == null) {
993                 LOG.error("Node doesnt have ceps");
994                 return null;
995             }
996             return optNode.get().augmentation(OwnedNodeEdgePoint1.class).getCepList().getConnectionEndPoint()
997                 .get(new org.opendaylight.yang.gen.v1.urn
998                     .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(cepUuid));
999         } catch (InterruptedException | ExecutionException e) {
1000             LOG.error("Couldnt read node in topology", e);
1001             return null;
1002         }
1003     }
1004
1005     private String getAssociatedNetworkPort(String spcXpdrClient, List<String> xpdrNetworkTplist) {
1006         for (String networkPort:xpdrNetworkTplist) {
1007             if (networkPort.split("\\+")[0].equals(spcXpdrClient.split("\\+")[0])) {
1008                 return networkPort;
1009             }
1010         }
1011         return null;
1012     }
1013
1014     public void setInput(CreateConnectivityServiceInput input) {
1015         this.input = input;
1016     }
1017
1018     public void setServiceUuid(Uuid serviceUuid) {
1019         this.serviceUuid = serviceUuid;
1020     }
1021 }