Merge "Refactor TAPI utils TapiContext"
[transportpce.git] / tapi / src / main / java / org / opendaylight / transportpce / tapi / utils / TapiContext.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.utils;
9
10 import java.nio.charset.Charset;
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.Optional;
14 import java.util.UUID;
15 import java.util.concurrent.ExecutionException;
16 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
17 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
18 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Context;
19 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.ContextBuilder;
20 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LayerProtocolName;
21 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Uuid;
22 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.Name;
23 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameBuilder;
24 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePoint;
25 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePointKey;
26 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.Context1;
27 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.Context1Builder;
28 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.OwnedNodeEdgePoint1;
29 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.OwnedNodeEdgePoint1Builder;
30 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.cep.list.ConnectionEndPoint;
31 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.cep.list.ConnectionEndPointKey;
32 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connection.LowerConnection;
33 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connection.LowerConnectionKey;
34 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.Connection;
35 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectionKey;
36 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectivityService;
37 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectivityServiceKey;
38 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContextBuilder;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.context.topology.context.topology.node.owned.node.edge.point.CepListBuilder;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.context.NotificationContextBuilder;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.context.TopologyContext;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.context.TopologyContextBuilder;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePoint;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointBuilder;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointKey;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Link;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.LinkKey;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeBuilder;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeKey;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.NwTopologyServiceBuilder;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.Topology;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.TopologyKey;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 public class TapiContext {
59
60     private static final Logger LOG = LoggerFactory.getLogger(TapiContext.class);
61     public static final String TAPI_CONTEXT = "T-API context";
62     public static final String NODE_NOT_PRESENT = "Node is not present in datastore";
63     private final NetworkTransactionService networkTransactionService;
64
65     public TapiContext(NetworkTransactionService networkTransactionService) {
66         this.networkTransactionService = networkTransactionService;
67         createTapiContext();
68     }
69
70     private void createTapiContext() {
71         try {
72             // Augmenting tapi context to include topology and connectivity contexts
73             Name contextName = new NameBuilder().setValue(TAPI_CONTEXT).setValueName("TAPI Context Name").build();
74             Name nwTopoServiceName =
75                 new NameBuilder().setValue("Network Topo Service").setValueName("Network Topo Service Name").build();
76             this.networkTransactionService.put(
77                 LogicalDatastoreType.OPERATIONAL,
78                 InstanceIdentifier.builder(Context.class).build(),
79                 new ContextBuilder()
80                     .setName(Map.of(contextName.key(), contextName))
81                     .setUuid(
82                         new Uuid(UUID.nameUUIDFromBytes(TAPI_CONTEXT.getBytes(Charset.forName("UTF-8"))).toString()))
83                     .setServiceInterfacePoint(new HashMap<>())
84                     .addAugmentation(
85                     //connectivityContext
86                         new Context1Builder()
87                             .setConnectivityContext(
88                                 new ConnectivityContextBuilder()
89                                     .setConnection(new HashMap<>())
90                                     .setConnectivityService(new HashMap<>())
91                                     .build())
92                             .build())
93                     .addAugmentation(
94                     //topologyContext
95                         new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1Builder()
96                             .setTopologyContext(new TopologyContextBuilder()
97                                 .setNwTopologyService(new NwTopologyServiceBuilder()
98                                     .setTopology(new HashMap<>())
99                                     .setUuid(
100                                         new Uuid(
101                                             UUID.nameUUIDFromBytes(
102                                                     "Network Topo Service".getBytes(Charset.forName("UTF-8")))
103                                                 .toString()))
104                                     .setName(Map.of(nwTopoServiceName.key(), nwTopoServiceName))
105                                     .build())
106                                 .setTopology(new HashMap<>())
107                                 .build())
108                             .build())
109                     .addAugmentation(
110                     //notificationContext
111                         new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.Context1Builder()
112                             .setNotificationContext(new NotificationContextBuilder()
113                                 .setNotification(new HashMap<>())
114                                 .setNotifSubscription(new HashMap<>())
115                                 .build())
116                             .build())
117                     .build());
118             this.networkTransactionService.commit().get();
119             LOG.info("TAPI context created successfully.");
120         } catch (InterruptedException | ExecutionException e) {
121             LOG.error("Failed to create TAPI context", e);
122         }
123     }
124
125     public Context getTapiContext() {
126         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
127         //  There is no Identifiable in Context model
128         try {
129             Optional<Context> optionalContext = this.networkTransactionService.read(
130                     LogicalDatastoreType.OPERATIONAL,
131                     InstanceIdentifier.builder(Context.class).build())
132                 .get();
133             if (optionalContext.isEmpty()) {
134                 LOG.error("Tapi context is not present in datastore");
135                 return null;
136             }
137             return optionalContext.orElseThrow();
138         } catch (InterruptedException | ExecutionException e) {
139             LOG.error("Couldnt read tapi context from datastore", e);
140             return null;
141         }
142     }
143
144     public void deleteTapiContext() {
145
146     }
147
148     public void updateTopologyContext(Map<TopologyKey, Topology> topologyMap) {
149         // TODO: solve error when merging: Topology is not a valid child of topology context?
150         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
151         try {
152             // merge in datastore
153             this.networkTransactionService.merge(
154                 LogicalDatastoreType.OPERATIONAL,
155                 InstanceIdentifier.builder(Context.class)
156                     .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class)
157                     .child(TopologyContext.class)
158                     .build(),
159                 new TopologyContextBuilder()
160                     //.setNwTopologyService(new NwTopologyServiceBuilder().build())
161                     .setTopology(topologyMap)
162                     .build());
163             this.networkTransactionService.commit().get();
164             LOG.info("TAPI topology merged successfully.");
165         } catch (InterruptedException | ExecutionException e) {
166             LOG.error("Failed to merge TAPI topology", e);
167         }
168     }
169
170     public void updateSIPContext(Map<ServiceInterfacePointKey, ServiceInterfacePoint> sipMap) {
171         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
172         try {
173             // merge in datastore
174             this.networkTransactionService.merge(
175                 LogicalDatastoreType.OPERATIONAL,
176                 InstanceIdentifier.builder(Context.class).build(),
177                 new ContextBuilder().setServiceInterfacePoint(sipMap).build());
178             this.networkTransactionService.commit().get();
179             LOG.info("TAPI SIPs merged successfully.");
180         } catch (InterruptedException | ExecutionException e) {
181             LOG.error("Failed to merge TAPI SIPs", e);
182         }
183     }
184
185     public void updateConnectivityContext(Map<ConnectivityServiceKey, ConnectivityService> connServMap,
186                                           Map<ConnectionKey, Connection> connectionFullMap) {
187         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
188         try {
189             // merge in datastore
190             this.networkTransactionService.merge(
191                 LogicalDatastoreType.OPERATIONAL,
192                 InstanceIdentifier.builder(Context.class)
193                     .augmentation(Context1.class)
194                     .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
195                             .context.ConnectivityContext.class)
196                     .build(),
197                 new ConnectivityContextBuilder()
198                     .setConnectivityService(connServMap)
199                     .setConnection(connectionFullMap)
200                     .build());
201             this.networkTransactionService.commit().get();
202             LOG.info("TAPI connectivity merged successfully.");
203             LOG.debug("TAPI connectivity merged successfully for services {}",
204                 connServMap.entrySet().iterator().next().getKey());
205         } catch (InterruptedException | ExecutionException e) {
206             LOG.error("Failed to merge TAPI connectivity", e);
207         }
208     }
209
210     public void updateTopologyWithCep(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid, ConnectionEndPoint cep) {
211         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
212         InstanceIdentifier<OwnedNodeEdgePoint> onepIID =
213             InstanceIdentifier.builder(Context.class)
214                 .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class)
215                 .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121
216                         .context.TopologyContext.class)
217                 .child(Topology.class, new TopologyKey(topoUuid))
218                 .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node.class,
219                         new NodeKey(nodeUuid))
220                 .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid))
221                 .build();
222         try {
223             Optional<OwnedNodeEdgePoint> optionalOnep =
224                 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, onepIID).get();
225             if (optionalOnep.isEmpty()) {
226                 LOG.error("ONEP is not present in datastore for topoUuid {}, NodeUuid {}", topoUuid, nodeUuid);
227                 return;
228             }
229             OwnedNodeEdgePoint onep = optionalOnep.orElseThrow();
230             LOG.info("ONEP found = {}", onep);
231             // TODO -> If cep exists -> skip merging to datasore
232             OwnedNodeEdgePoint1 onep1 = onep.augmentation(OwnedNodeEdgePoint1.class);
233             if (onep1 != null && onep1.getCepList() != null && onep1.getCepList().getConnectionEndPoint() != null
234                     && onep1.getCepList().getConnectionEndPoint().containsKey(new ConnectionEndPointKey(cep.key()))) {
235                 LOG.info("CEP already in topology, skipping merge");
236                 return;
237             }
238             // Updated ONEP
239             OwnedNodeEdgePoint newOnep = new OwnedNodeEdgePointBuilder(onep)
240                 .addAugmentation(new OwnedNodeEdgePoint1Builder()
241                     .setCepList(new CepListBuilder().setConnectionEndPoint(Map.of(cep.key(), cep)).build())
242                     .build())
243                 .build();
244             LOG.info("New ONEP is {}", newOnep);
245             // merge in datastore
246             this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, onepIID, newOnep);
247             this.networkTransactionService.commit().get();
248             LOG.info("CEP added successfully.");
249         } catch (InterruptedException | ExecutionException e) {
250             LOG.error("Couldnt update cep in topology", e);
251         }
252     }
253
254     public Node getTapiNode(Uuid topoUuid, Uuid nodeUuid) {
255         try {
256             Optional<Node> optNode =
257                 this.networkTransactionService.read(
258                         LogicalDatastoreType.OPERATIONAL,
259                         InstanceIdentifier.builder(Context.class)
260                             .augmentation(
261                                 org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class)
262                             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121
263                                     .context.TopologyContext.class)
264                             .child(Topology.class, new TopologyKey(topoUuid))
265                             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121
266                                         .topology.Node.class,
267                                     new NodeKey(nodeUuid))
268                             .build())
269                     .get();
270             if (optNode.isEmpty()) {
271                 LOG.error(NODE_NOT_PRESENT);
272                 return null;
273             }
274             // TODO -> Need to remove CEPs from NEPs. If not error from get Topology details output
275             Node node = optNode.orElseThrow();
276             LOG.debug("NEPs of node before creating map to be returned to the getTapiNode function = {}",
277                 node.getOwnedNodeEdgePoint().size());
278             Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> onepMap = new HashMap<>();
279             for (OwnedNodeEdgePoint onep: node.getOwnedNodeEdgePoint().values()) {
280                 if (onep.augmentation(OwnedNodeEdgePoint1.class) == null) {
281                     onepMap.put(onep.key(), onep);
282                     continue;
283                 }
284                 OwnedNodeEdgePointBuilder newOnepBuilder = new OwnedNodeEdgePointBuilder()
285                     .setUuid(onep.getUuid())
286                     .setLayerProtocolName(onep.getLayerProtocolName())
287                     .setName(onep.getName())
288                     .setSupportedCepLayerProtocolQualifierInstances(
289                         onep.getSupportedCepLayerProtocolQualifierInstances())
290                     .setAdministrativeState(onep.getAdministrativeState())
291                     .setOperationalState(onep.getOperationalState())
292                     .setLifecycleState(onep.getLifecycleState())
293 //                    .setTerminationDirection(onep.getTerminationDirection())
294 //                    .setTerminationState(onep.getTerminationState())
295                     .setDirection(onep.getDirection())
296                     .setLinkPortRole(onep.getLinkPortRole());
297                 if (onep.getMappedServiceInterfacePoint() != null) {
298                     newOnepBuilder.setMappedServiceInterfacePoint(onep.getMappedServiceInterfacePoint());
299                 }
300                 OwnedNodeEdgePoint newOnep = newOnepBuilder.build();
301                 onepMap.put(newOnep.key(), newOnep);
302             }
303             LOG.debug("NEPs of node after creating map to be returned to the getTapiNode function = {}",
304                 onepMap.size());
305             return new NodeBuilder(node).setOwnedNodeEdgePoint(onepMap).build();
306         } catch (InterruptedException | ExecutionException e) {
307             LOG.error("Couldnt read node in topology", e);
308             return null;
309         }
310     }
311
312     public OwnedNodeEdgePoint getTapiNEP(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid) {
313         try {
314             Optional<OwnedNodeEdgePoint> optNode =
315                 this.networkTransactionService.read(
316                         LogicalDatastoreType.OPERATIONAL,
317                         InstanceIdentifier.builder(Context.class)
318                             .augmentation(
319                                 org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class)
320                             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121
321                                     .context.TopologyContext.class)
322                             .child(Topology.class, new TopologyKey(topoUuid))
323                             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121
324                                         .topology.Node.class,
325                                     new NodeKey(nodeUuid))
326                             .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid))
327                             .build())
328                     .get();
329             if (optNode.isEmpty()) {
330                 LOG.error(NODE_NOT_PRESENT);
331                 return null;
332             }
333             return optNode.orElseThrow();
334         } catch (InterruptedException | ExecutionException e) {
335             LOG.error("Couldnt read NEP in topology", e);
336             return null;
337         }
338     }
339
340     public Link getTapiLink(Uuid topoUuid, Uuid linkUuid) {
341         try {
342             Optional<Link> optLink = this.networkTransactionService.read(
343                     LogicalDatastoreType.OPERATIONAL,
344                     InstanceIdentifier.builder(Context.class)
345                         .augmentation(
346                             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class)
347                         .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121
348                                 .context.TopologyContext.class)
349                         .child(Topology.class, new TopologyKey(topoUuid))
350                         .child(Link.class, new LinkKey(linkUuid))
351                         .build())
352                 .get();
353             if (optLink.isEmpty()) {
354                 LOG.error(NODE_NOT_PRESENT);
355                 return null;
356             }
357             return optLink.orElseThrow();
358         } catch (InterruptedException | ExecutionException e) {
359             LOG.error("Couldnt read link in topology", e);
360             return null;
361         }
362     }
363
364     public Map<TopologyKey, Topology> getTopologyContext() {
365         try {
366             Optional<TopologyContext> optTopoContext = this.networkTransactionService.read(
367                     LogicalDatastoreType.OPERATIONAL,
368                     InstanceIdentifier.builder(Context.class)
369                         .augmentation(
370                             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class)
371                         .child(TopologyContext.class)
372                         .build())
373                 .get();
374             if (optTopoContext.isEmpty()) {
375                 LOG.error("Topology context is not present in datastore");
376                 return null;
377             }
378             return optTopoContext.orElseThrow().getTopology();
379         } catch (InterruptedException | ExecutionException e) {
380             LOG.error("Couldnt read topology context", e);
381             return null;
382         }
383     }
384
385     public ConnectivityService getConnectivityService(Uuid serviceUuid) {
386         try {
387             // First read connectivity service with service uuid and update info
388             Optional<ConnectivityService> optConnServ =
389                 this.networkTransactionService.read(
390                         LogicalDatastoreType.OPERATIONAL,
391                         InstanceIdentifier.builder(Context.class)
392                             .augmentation(Context1.class)
393                             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
394                                     .context.ConnectivityContext.class)
395                             .child(ConnectivityService.class, new ConnectivityServiceKey(serviceUuid))
396                             .build())
397                     .get();
398             if (optConnServ.isEmpty()) {
399                 LOG.error("Connectivity service not found in tapi context");
400                 return null;
401             }
402             return optConnServ.orElseThrow();
403         } catch (InterruptedException | ExecutionException e) {
404             LOG.error("Connectivity service not found in tapi context. Error:", e);
405             return null;
406         }
407     }
408
409     public void deleteConnectivityService(Uuid serviceUuid) {
410         // TODO: handle case where the infrastructure service is removed before the top level service?
411         ConnectivityService connectivityService = getConnectivityService(serviceUuid);
412         if (connectivityService == null) {
413             LOG.error("Service doesnt exist in tapi context");
414             return;
415         }
416         for (var connection : connectivityService.getConnection().values()) {
417             deleteConnection(connection.getConnectionUuid(), serviceUuid, connectivityService.getLayerProtocolName());
418         }
419         try {
420             this.networkTransactionService.delete(
421                 LogicalDatastoreType.OPERATIONAL,
422                 InstanceIdentifier.builder(Context.class)
423                     .augmentation(Context1.class)
424                     .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
425                             .context.ConnectivityContext.class)
426                     .child(ConnectivityService.class, new ConnectivityServiceKey(serviceUuid))
427                     .build());
428             this.networkTransactionService.commit().get();
429             LOG.info("Connectivity service deleted");
430         } catch (InterruptedException | ExecutionException e) {
431             LOG.error("Failed to delete Connectivity service", e);
432         }
433     }
434
435     private void deleteConnection(Uuid connectionUuid, Uuid serviceUuid, LayerProtocolName serviceLayer) {
436         // First read connectivity service with service uuid and update info
437         Connection connection = getConnection(connectionUuid);
438         if (connection == null || isUsedByOtherService(connection, serviceUuid)) {
439             rawDeleteConnection(connectionUuid);
440             return;
441         }
442         Map<LowerConnectionKey, LowerConnection> lowerConnectionMap = connection.getLowerConnection();
443         if (lowerConnectionMap == null) {
444             rawDeleteConnection(connectionUuid);
445             return;
446         }
447         for (LowerConnection lowerConnection : lowerConnectionMap.values()) {
448             // check layer of connection, for DSR service we only need to delete DSR layer
449             // connection and XC at ODU. For ODU, only need to delete ODU connections and for
450             // photonic media services all the photonic media. And when it is ETH we need to delete
451             // everything and also without checking the lower connection layer
452             Connection conn1 = getConnection(lowerConnection.getConnectionUuid());
453             if (conn1 == null) {
454                 // connection not found in tapi context
455                 continue;
456             }
457             LayerProtocolName lowerConnLayer = conn1.getLayerProtocolName();
458             switch (serviceLayer) {
459                 case PHOTONICMEDIA:
460                 case ODU:
461                     if (lowerConnLayer.equals(serviceLayer)) {
462                         deleteConnection(lowerConnection.getConnectionUuid(), serviceUuid, serviceLayer);
463                     }
464                     break;
465                 case ETH:
466                     deleteConnection(lowerConnection.getConnectionUuid(), serviceUuid, serviceLayer);
467                     break;
468                 case DSR:
469                     if (lowerConnLayer.equals(serviceLayer)
470                             || (lowerConnLayer.equals(LayerProtocolName.ODU)
471                                     && conn1.getName().values().stream()
472                                         .anyMatch(name -> name.getValue().contains("XC")))) {
473                         deleteConnection(lowerConnection.getConnectionUuid(), serviceUuid, serviceLayer);
474                     }
475                     break;
476                 //case DIGITAL_OTN:
477                 default:
478                     LOG.info("Unknown service Layer: {}", serviceLayer.getName());
479             }
480         }
481         rawDeleteConnection(connectionUuid);
482     }
483
484     private void rawDeleteConnection(Uuid connectionUuid) {
485         try {
486             this.networkTransactionService.delete(
487                 LogicalDatastoreType.OPERATIONAL,
488                 InstanceIdentifier.builder(Context.class)
489                     .augmentation(Context1.class)
490                     .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
491                             .context.ConnectivityContext.class)
492                     .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
493                             .connectivity.context.Connection.class,
494                         new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
495                             .connectivity.context.ConnectionKey(connectionUuid))
496                     .build());
497             this.networkTransactionService.commit().get();
498         } catch (InterruptedException | ExecutionException e) {
499             LOG.error("Failed to delete TAPI Connection", e);
500         }
501     }
502
503     private boolean isUsedByOtherService(Connection connection, Uuid serviceUuid) {
504         Map<ConnectivityServiceKey, ConnectivityService> connServicesMap = getConnectivityServices();
505         if (connServicesMap == null) {
506             LOG.info("isUsedByOtherService: No service in tapi context!");
507             return false;
508         }
509         Uuid connUuid = connection.getUuid();
510         for (ConnectivityService connService: connServicesMap.values()) {
511             var connServConn = connService.getConnection();
512             Uuid connServUuid = connService.getUuid();
513             if (connServConn == null || connServUuid.equals(serviceUuid)) {
514                 LOG.info("isUsedByOtherService: There are no connections in service {} or service in loop is the "
515                         + "service to be deleted", connServUuid.getValue());
516                 continue;
517             }
518             if (connServConn.containsKey(
519                     new org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
520                         .connectivity.service.ConnectionKey(connUuid))) {
521                 LOG.info(
522                     "isUsedByOtherService: Connection {} is in used by service {}. Cannot remove it from context",
523                     connUuid.getValue(), connServUuid.getValue());
524                 return true;
525             }
526             LOG.info("isUsedByOtherService: Going to check lower connections");
527             for (var conn1 : connServConn.values()) {
528                 Connection connection1 = getConnection(conn1.getConnectionUuid());
529                 if (connection1 == null) {
530                     continue;
531                 }
532                 var conn1Low = connection1.getLowerConnection();
533                 if (conn1Low == null) {
534                     continue;
535                 }
536                 if (conn1Low.containsKey(new LowerConnectionKey(connUuid))) {
537                     LOG.info("isUsedByOtherService: Lower Connection {} is in used by service {}. Cannot remove it "
538                             + "from context", connUuid.getValue(), connServUuid.getValue());
539                     return true;
540                 }
541             }
542         }
543         LOG.info("isUsedByOtherService: No other service uses connection {}, therefore it can be safely deleted",
544                 connUuid);
545         return false;
546     }
547
548     public Connection getConnection(Uuid connectionUuid) {
549         try {
550             // First read connectivity service with service uuid and update info
551             Optional<Connection> optConn =
552                 this.networkTransactionService.read(
553                         LogicalDatastoreType.OPERATIONAL,
554                         InstanceIdentifier.builder(Context.class)
555                             .augmentation(Context1.class)
556                             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
557                                     .context.ConnectivityContext.class)
558                             .child(Connection.class, new ConnectionKey(connectionUuid))
559                             .build())
560                 .get();
561             if (optConn.isEmpty()) {
562                 LOG.error("Connection not found in tapi context");
563                 return null;
564             }
565             return optConn.orElseThrow();
566         } catch (InterruptedException | ExecutionException e) {
567             LOG.error("Connection not found in tapi context. Error:", e);
568             return null;
569         }
570     }
571
572     public Map<ConnectivityServiceKey, ConnectivityService> getConnectivityServices() {
573         try {
574             // First read connectivity service with service uuid and update info
575             Optional<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
576                     .context.ConnectivityContext> optConnContext =
577                 this.networkTransactionService.read(
578                         LogicalDatastoreType.OPERATIONAL,
579                         InstanceIdentifier.builder(Context.class)
580                             .augmentation(Context1.class)
581                             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
582                                     .context.ConnectivityContext.class)
583                             .build())
584                     .get();
585             if (optConnContext.isEmpty()) {
586                 LOG.error("Connectivity context not found in tapi context");
587                 return null;
588             }
589             return optConnContext.orElseThrow().getConnectivityService();
590         } catch (InterruptedException | ExecutionException e) {
591             LOG.error("Connectivity context not found in tapi context. Error:", e);
592             return null;
593         }
594     }
595
596     public ConnectionEndPoint getTapiCEP(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid, Uuid cepUuid) {
597         try {
598             Optional<OwnedNodeEdgePoint> optNode = this.networkTransactionService.read(
599                     LogicalDatastoreType.OPERATIONAL,
600                     InstanceIdentifier.builder(Context.class)
601                         .augmentation(
602                             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1.class)
603                         .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121
604                                 .context.TopologyContext.class)
605                         .child(Topology.class, new TopologyKey(topoUuid))
606                         .child(
607                             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node.class,
608                             new NodeKey(nodeUuid))
609                         .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid))
610                         .build())
611                 .get();
612             if (optNode.isEmpty()) {
613                 LOG.error(NODE_NOT_PRESENT);
614                 return null;
615             }
616             if (optNode.orElseThrow().augmentation(OwnedNodeEdgePoint1.class) == null) {
617                 LOG.error("Node doesnt have ceps");
618                 return null;
619             }
620             return optNode.orElseThrow()
621                 .augmentation(OwnedNodeEdgePoint1.class)
622                 .getCepList()
623                 .getConnectionEndPoint()
624                 .get(new ConnectionEndPointKey(cepUuid));
625         } catch (InterruptedException | ExecutionException e) {
626             LOG.error("Couldnt read node in topology", e);
627             return null;
628         }
629     }
630 }