Add tests for autonomous service rerouting
[transportpce.git] / tapi / src / main / java / org / opendaylight / transportpce / tapi / listeners / TapiNetworkModelListenerImpl.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 java.nio.charset.StandardCharsets;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Objects;
18 import java.util.Optional;
19 import java.util.UUID;
20 import java.util.concurrent.ExecutionException;
21 import java.util.stream.Collectors;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
24 import org.opendaylight.transportpce.tapi.TapiStringConstants;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
26 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.AdministrativeState;
27 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Context;
28 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LayerProtocolName;
29 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState;
30 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1;
32 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnection;
33 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection;
34 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder;
35 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey;
36 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService;
37 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder;
38 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.NameAndValueChange;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.Notification;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.NotificationType;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.ObjectType;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.TapiNotificationListener;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.NodeEdgePointRef;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePoint;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointKey;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.NodeKey;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.TopologyKey;
54 import org.opendaylight.yangtools.yang.binding.Enumeration;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 public class TapiNetworkModelListenerImpl implements TapiNotificationListener {
60
61     private static final Logger LOG = LoggerFactory.getLogger(TapiNetworkModelListenerImpl.class);
62     private final NetworkTransactionService networkTransactionService;
63     private final List<ConnectivityService> connectivityServiceChanges = new ArrayList<>();
64     private final Uuid tapiTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
65             .getBytes(StandardCharsets.UTF_8)).toString());
66     private final List<LayerProtocolName> orderedServiceLayerList;
67
68
69     public TapiNetworkModelListenerImpl(NetworkTransactionService networkTransactionService) {
70         this.networkTransactionService = networkTransactionService;
71         this.orderedServiceLayerList = List.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU,
72             LayerProtocolName.DSR, LayerProtocolName.ETH);
73     }
74
75     @Override
76     public void onNotification(Notification notification) {
77         LOG.info("Received network model notification {}", notification);
78         if (notification.getNotificationType() == NotificationType.ATTRIBUTEVALUECHANGE
79                 && notification.getTargetObjectType() == ObjectType.NODEEDGEPOINT) {
80             if (notification.getChangedAttributes() == null) {
81                 return;
82             }
83             // TODO: need to re-think this to update first the connections from roadm to roadm and then the others
84             updateConnections(notification.getChangedAttributes().keySet().stream()
85                     .map(changedAttributesKey -> new Uuid(changedAttributesKey.getValueName()))
86                     .collect(Collectors.toList()),
87                 notification.getChangedAttributes().values().stream()
88                     .map(NameAndValueChange::getNewValue)
89                     .collect(Collectors.toList()));
90             updateConnectivityServices();
91             // todo  create NotificationPublishSerivce (Tapi) object + send Notification
92         }
93     }
94
95     private void updateConnectivityServices() {
96         try {
97             this.connectivityServiceChanges.clear();
98             InstanceIdentifier<ConnectivityContext> connectivityContextIID =
99                 InstanceIdentifier.builder(Context.class).augmentation(
100                         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
101                     .child(ConnectivityContext.class)
102                     .build();
103             Optional<ConnectivityContext> optConnContext =
104                 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityContextIID).get();
105             if (optConnContext.isEmpty()) {
106                 LOG.error("Could not update TAPI connectivity services");
107                 return;
108             }
109             ConnectivityContext connContext = optConnContext.get();
110             Map<Uuid, Enumeration[]> states = new HashMap<>();
111             if (connContext.getConnectivityService() == null) {
112                 return;
113             }
114             for (ConnectivityService connService : connContext.getConnectivityService().values()) {
115                 LOG.info("Connectivity service = {}", connService);
116                 // TODO: maybe we need to check lower connections if my new code doesnt work
117                 states.put(connService.getUuid(), getStates(connService));
118                 AdministrativeState adminState = (AdministrativeState) states.get(connService.getUuid())[0];
119                 OperationalState operState = (OperationalState) states.get(connService.getUuid())[1];
120
121                 InstanceIdentifier<ConnectivityService> connServIID = InstanceIdentifier
122                     .builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi
123                         .connectivity.rev181210.Context1.class)
124                     .child(ConnectivityContext.class)
125                     .child(ConnectivityService.class, new ConnectivityServiceKey(connService.getUuid()))
126                     .build();
127                 ConnectivityService changedConnServ = new ConnectivityServiceBuilder()
128                     .setUuid(connService.getUuid())
129                     .setAdministrativeState(adminState)
130                     .setOperationalState(operState)
131                     .build();
132                 this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connServIID,
133                     changedConnServ);
134                 this.networkTransactionService.commit().get();
135
136                 if (connService.getAdministrativeState() != adminState
137                     || connService.getOperationalState() != operState) {
138                     this.connectivityServiceChanges.add(changedConnServ);
139                 }
140             }
141             // TODO: this last function may need some refactoring... if the PHOT_MEDIA goes down,
142             //  then ODU goes down and then DSR should also go down
143             for (ConnectivityService connService : connContext.getConnectivityService().values()) {
144                 AdministrativeState adminState = (AdministrativeState) states.get(connService.getUuid())[0];
145                 OperationalState operState = (OperationalState) states.get(connService.getUuid())[1];
146                 this.connectivityServiceChanges.addAll(updateSupportedConnectivityServices(
147                     connContext.getConnectivityService().values(), connService.getUuid(), adminState, operState,
148                     LayerProtocolName.ODU));
149             }
150         } catch (InterruptedException | ExecutionException e) {
151             LOG.error("Could not update TAPI connectivity services");
152         }
153     }
154
155     private Enumeration[] getStates(ConnectivityService connService) throws InterruptedException, ExecutionException {
156         OperationalState operState = OperationalState.ENABLED;
157         AdministrativeState adminState = AdministrativeState.UNLOCKED;
158         if (connService.getConnection() == null) {
159             LOG.info("No connections on service = {}", connService);
160             return new Enumeration[]{null, null};
161         }
162         for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210
163                 .connectivity.service.Connection connection : connService.getConnection().values()) {
164             InstanceIdentifier<Connection> connIID =
165                 InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
166                         .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
167                     .child(ConnectivityContext.class)
168                     .child(Connection.class, new ConnectionKey(connection.getConnectionUuid()))
169                     .build();
170             Optional<Connection> optConn = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL,
171                 connIID).get();
172             if (optConn.isEmpty()) {
173                 LOG.error("Could not get state for a TAPI connection");
174                 continue;
175             }
176             LOG.info("State of connection {} of connectivity service {} = {}", optConn.get().getUuid().getValue(),
177                 connService.getUuid().getValue(), optConn.get().getOperationalState().getName());
178             if (optConn.get().getOperationalState() == OperationalState.DISABLED) {
179                 adminState = AdministrativeState.LOCKED;
180                 operState = OperationalState.DISABLED;
181             }
182         }
183         return new Enumeration[]{adminState, operState};
184     }
185
186     private void updateConnections(List<Uuid> changedOneps, List<String> onepStates) {
187         LOG.info("Updating TAPI connections");
188         LOG.info("Change in oneps = {}, new states = {}", changedOneps, onepStates);
189         try {
190             //should it return a list of connections?
191             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
192                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> connectivityContextIID =
193                 InstanceIdentifier.builder(Context.class).augmentation(
194                             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
195                         .child(org.opendaylight.yang.gen.v1.urn
196                                 .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
197                         .build();
198             Optional<org.opendaylight.yang.gen.v1.urn
199                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> optConnContext =
200                 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityContextIID).get();
201             if (optConnContext.isEmpty()) {
202                 LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
203                 return;
204             }
205             if (optConnContext.get().getConnectivityService() == null) {
206                 LOG.info("No TAPI connectivity service to update");
207                 return;
208             }
209             // TODO: order services from lower layer to upper layer
210             Map<ConnectivityServiceKey, ConnectivityService> connServMap
211                     = optConnContext.get().getConnectivityService();
212             if (connServMap == null) {
213                 LOG.info("No connections to update");
214                 return;
215             }
216             connServMap = orderConnServiceMap(connServMap);
217             for (ConnectivityService connService : connServMap.values()) {
218                 LOG.info("Looping through connectivity service = {}", connService.getUuid().getValue());
219                 if (connService.getConnection() == null) {
220                     continue;
221                 }
222                 for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210
223                         .connectivity.service.Connection connection : connService.getConnection().values()) {
224                     InstanceIdentifier<Connection> connIID =
225                         InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
226                             .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
227                                 .child(org.opendaylight.yang.gen.v1.urn
228                                         .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
229                                 .child(Connection.class, new ConnectionKey(connection.getConnectionUuid()))
230                                 .build();
231                     Optional<Connection> optConn =
232                         this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
233                     if (optConn.isEmpty()) {
234                         LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
235                         continue;
236                     }
237                     Connection newConn = optConn.get();
238                     // Check LowerConnection states and if any of the lower connection is disabled then we can put
239                     // the connection out of service. And based on the connection previous state we decide
240                     // the update necessary
241                     OperationalState newConnState = newConn.getOperationalState();
242                     if (newConn.getLowerConnection() != null) {
243                         newConnState = updateLowerConnections(changedOneps, onepStates,
244                                 newConn.getLowerConnection().values(), newConn.getOperationalState());
245                     }
246                     if (newConnState.equals(newConn.getOperationalState())) {
247                         // To check if the oneps are from the original Top connection
248                         newConnState = getConnectionState(changedOneps, onepStates, newConn);
249                     }
250
251                     LOG.info("Previous connection state = {} & New connection state = {}",
252                             newConn.getOperationalState().getName(), newConnState.getName());
253                     Connection changedConn = new ConnectionBuilder(newConn).setOperationalState(newConnState).build();
254                     // TODO: the changed NEP is a DEG port which is not in any connection,
255                     //  therefore we also need to change the cross connections,
256                     //  the lower connections uuid and check the states.
257                     //  If any of the lower connections of a connection is DISABLED then the top connection is DISABLED
258                     this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connIID, changedConn);
259                     this.networkTransactionService.commit().get();
260                 }
261             }
262         } catch (InterruptedException | ExecutionException e) {
263             LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
264         }
265     }
266
267     private Map<ConnectivityServiceKey, ConnectivityService> orderConnServiceMap(
268             Map<ConnectivityServiceKey, ConnectivityService> connServMap) {
269         Map<ConnectivityServiceKey, ConnectivityService> orderedServiceMap = new HashMap<>();
270         for (LayerProtocolName lpn:this.orderedServiceLayerList) {
271             for (ConnectivityService connServ:connServMap.values()) {
272                 if (connServ.getServiceLayer().equals(lpn)) {
273                     LOG.info("Layer of service is equal to entry of lpn = {}", lpn);
274                     orderedServiceMap.put(connServ.key(), connServ);
275                 }
276             }
277         }
278         LOG.info("Ordered map of services = {}", orderedServiceMap);
279         return orderedServiceMap;
280     }
281
282     private OperationalState updateLowerConnections(List<Uuid> changedOneps, List<String> onepStates,
283                                                     Collection<LowerConnection> lowerConnections,
284                                                     OperationalState uppConnState) {
285         LOG.info("Updating lower connections");
286         OperationalState topConnectionState = uppConnState;
287         Boolean allLowerConnEna = true;
288         try {
289             for (LowerConnection lowerConn:lowerConnections) {
290                 InstanceIdentifier<Connection> connIID =
291                     InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
292                         .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
293                             .child(org.opendaylight.yang.gen.v1.urn
294                                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
295                             .child(Connection.class, new ConnectionKey(lowerConn.getConnectionUuid()))
296                             .build();
297                 Optional<Connection> optConn =
298                         this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
299                 if (optConn.isEmpty()) {
300                     LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
301                     continue;
302                 }
303                 Connection newConn = optConn.get(); // Current state of connection
304                 if (newConn.getLowerConnection() != null) {
305                     // TODO: we can receive disable here because the lower connection haven been yet looped through and
306                     //  therefore it is disabled but it has to be changed to enable before returning disable.
307                     //  We need to recall the update Lower Connections with the lower connection we are checking now
308                     //  and all its lower connections, until no lower connections are found in the connection
309                     updateLowerConnections(changedOneps, onepStates, newConn.getLowerConnection().values(),
310                             newConn.getOperationalState());
311                 }
312                 OperationalState newConnState = getConnectionState(changedOneps, onepStates, newConn);
313                 // updated connection state if it contains a nep that has changed
314                 if (!newConn.getOperationalState().equals(newConnState)) {
315                     Connection changedConn = new ConnectionBuilder(newConn).setOperationalState(newConnState).build();
316                     this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connIID, changedConn);
317                     this.networkTransactionService.commit().get();
318                 }
319                 if (newConnState.equals(OperationalState.DISABLED)) {
320                     LOG.info("LowerConnection state is disable");
321                     allLowerConnEna = false;
322                     topConnectionState = OperationalState.DISABLED;
323                 }
324             }
325             if (allLowerConnEna) {
326                 return OperationalState.ENABLED;
327             }
328             return OperationalState.DISABLED;
329         } catch (InterruptedException | ExecutionException e) {
330             LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
331             return topConnectionState;
332         }
333     }
334
335     private OperationalState getConnectionState(List<Uuid> changedOneps, List<String> operState, Connection conn)
336             throws InterruptedException, ExecutionException {
337         LOG.info("Getting TAPI connectionState");
338         List<Uuid> connectionNeps = Objects.requireNonNull(conn.getConnectionEndPoint()).values().stream()
339             .map(NodeEdgePointRef::getNodeEdgePointUuid).collect(Collectors.toList());
340         LOG.info("Changed neps = {}", changedOneps);
341         LOG.info("Connection NEPs = {}", connectionNeps);
342         if (!Collections.disjoint(changedOneps, connectionNeps)) {
343             LOG.info("Connection neps {} are included in changed oneps {}", connectionNeps, changedOneps);
344             if ((changedOneps.contains(connectionNeps.get(0)) ? transformOperState(operState.get(
345                     changedOneps.indexOf(connectionNeps.get(0)))) : null) == OperationalState.DISABLED
346                         || (changedOneps.contains(connectionNeps.get(1)) ? transformOperState(operState.get(
347                                 changedOneps.indexOf(connectionNeps.get(1)))) : null) == OperationalState.DISABLED) {
348                 return OperationalState.DISABLED;
349             }
350             LOG.info("Didnt transform correctly the states");
351             for (Uuid connectionNep : connectionNeps) {
352                 Optional<org.opendaylight.yang.gen.v1.urn
353                         .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint> ocep
354                     = conn.getConnectionEndPoint().values().stream()
355                         .filter(connectionEndPoint -> connectionEndPoint.getNodeEdgePointUuid() == connectionNep)
356                         .findFirst();
357                 if (ocep.isEmpty()) {
358                     continue;
359                 }
360                 InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
361                     .augmentation(Context1.class).child(TopologyContext.class)
362                     .child(Topology.class, new TopologyKey(tapiTopoUuid))
363                     .child(Node.class, new NodeKey(ocep.get().getNodeUuid()))
364                     .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(connectionNep))
365                     .build();
366                 Optional<OwnedNodeEdgePoint> onep =
367                     this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, onepIID).get();
368                 if (onep.isEmpty() || onep.get().augmentation(OwnedNodeEdgePoint1.class) == null
369                         || onep.get().augmentation(OwnedNodeEdgePoint1.class).getCepList() == null) {
370                     continue;
371                 }
372                 if (onep.get().getOperationalState() == OperationalState.DISABLED
373                         && !changedOneps.contains(onep.get().getUuid())) {
374                     return OperationalState.DISABLED;
375                 }
376             }
377             return OperationalState.ENABLED;
378         }
379         LOG.info("Connection state = {}. Going to check lower connections", conn.getOperationalState());
380         // TODO --> check all lower connections state and if all of them are enabled we return enable, otherwise disable
381         if (conn.getLowerConnection() != null && allLowerConEnabled(conn.getLowerConnection().values())) {
382             return OperationalState.ENABLED;
383         }
384         return conn.getOperationalState();
385     }
386
387     private boolean allLowerConEnabled(Collection<LowerConnection> lowerConnections) {
388         try {
389             for (LowerConnection lowerConn:lowerConnections) {
390                 InstanceIdentifier<Connection> connIID =
391                     InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
392                             .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
393                         .child(org.opendaylight.yang.gen.v1.urn
394                             .onf.otcc.yang.tapi.connectivity.rev181210.context
395                             .ConnectivityContext.class)
396                         .child(Connection.class, new ConnectionKey(lowerConn.getConnectionUuid()))
397                         .build();
398                 Optional<Connection> optConn =
399                     this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
400                 if (optConn.isEmpty()) {
401                     LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
402                     continue;
403                 }
404                 Connection newConn = optConn.get(); // Current state of connection
405                 // updated connection state if it contains a nep that has changed
406                 if (newConn.getOperationalState().equals(OperationalState.DISABLED)) {
407                     LOG.info("LowerConnection state is disable");
408                     return false;
409                 }
410             }
411             return true;
412         } catch (InterruptedException | ExecutionException e) {
413             LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
414             return false;
415         }
416     }
417
418     private List<ConnectivityService> updateSupportedConnectivityServices(Collection<ConnectivityService> connServices,
419                                                                           Uuid supportingConnService,
420                                                                           AdministrativeState adminState,
421                                                                           OperationalState operState,
422                                                                           LayerProtocolName layer) {
423         // TODO we need to check this function
424         List<ConnectivityService> changedServices = new ArrayList<>();
425         if (adminState != AdministrativeState.LOCKED && operState != OperationalState.DISABLED) {
426             return changedServices;
427         }
428         try {
429             for (ConnectivityService supportedConnService : connServices) {
430                 // TODO currently supporting service uuid is saved in service layer, replace with name as soon
431                 // as name is implemented
432                 if (supportedConnService.getServiceLayer() != layer) {
433                     continue;
434                 }
435                 InstanceIdentifier<ConnectivityService> supportedConnServIID = InstanceIdentifier
436                     .builder(Context.class).augmentation(org.opendaylight.yang.gen.v1
437                         .urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
438                     .child(org.opendaylight.yang.gen.v1
439                         .urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
440                     .child(ConnectivityService.class, new ConnectivityServiceKey(supportedConnService.getUuid()))
441                     .build();
442                 Optional<ConnectivityService> optNewConnService = this.networkTransactionService.read(
443                     LogicalDatastoreType.OPERATIONAL, supportedConnServIID).get();
444                 if (optNewConnService.isEmpty()) {
445                     LOG.error("Could not update TAPI connectivity service");
446                     continue;
447                 }
448                 ConnectivityService newConnService = optNewConnService.get();
449                 if (supportedConnService.getServiceLevel() != null
450                         && supportedConnService.getServiceLevel().equals(supportingConnService.getValue())
451                         && newConnService.getAdministrativeState() != AdministrativeState.LOCKED
452                         && newConnService.getOperationalState() != OperationalState.DISABLED) {
453
454                     ConnectivityService changedSupportedConnServ = new ConnectivityServiceBuilder()
455                         .setUuid(supportedConnService.getUuid())
456                         .setAdministrativeState(adminState)
457                         .setOperationalState(operState)
458                         .build();
459                     // TODO: may need to update connections...
460                     this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, supportedConnServIID,
461                         changedSupportedConnServ);
462                     this.networkTransactionService.commit().get();
463                     changedServices.add(changedSupportedConnServ);
464                     if (layer == LayerProtocolName.ODU) {
465                         changedServices.addAll(updateSupportedConnectivityServices(connServices,
466                             supportedConnService.getUuid(), adminState, operState, LayerProtocolName.DSR));
467                     }
468                 }
469             }
470         } catch (InterruptedException | ExecutionException e) {
471             LOG.error("Could not update TAPI connectivity service");
472         }
473         return changedServices;
474     }
475
476     private OperationalState transformOperState(String operString) {
477         LOG.debug("Operstring to be converted = {}", operString);
478         State operState = org.opendaylight.transportpce.networkmodel.util.TopologyUtils.setNetworkOperState(operString);
479         LOG.debug("State received from topologyutils = {}", operState);
480         return operState.equals(State.InService) ? OperationalState.ENABLED : OperationalState.DISABLED;
481     }
482
483 }