2 * Copyright © 2021 Nokia, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.transportpce.tapi.listeners;
10 import java.nio.charset.StandardCharsets;
11 import java.time.OffsetDateTime;
12 import java.time.ZoneOffset;
13 import java.time.format.DateTimeFormatter;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
20 import java.util.Objects;
21 import java.util.Optional;
23 import java.util.UUID;
24 import java.util.concurrent.ExecutionException;
25 import java.util.stream.Collectors;
26 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
27 import org.opendaylight.mdsal.binding.api.NotificationService.CompositeListener;
28 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
29 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
30 import org.opendaylight.transportpce.tapi.TapiStringConstants;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
32 import org.opendaylight.yang.gen.v1.nbi.notifications.rev230728.PublishTapiNotificationService;
33 import org.opendaylight.yang.gen.v1.nbi.notifications.rev230728.PublishTapiNotificationServiceBuilder;
34 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.AdministrativeState;
35 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Context;
36 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.DateAndTime;
37 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LayerProtocolName;
38 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.OBJECTTYPETAPICONTEXT;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.OperationalState;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Uuid;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.Name;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameKey;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.OwnedNodeEdgePoint1;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connection.LowerConnection;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.Connection;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectionBuilder;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectionKey;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectivityService;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectivityServiceBuilder;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.connectivity.context.ConnectivityServiceKey;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContext;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.EventNotification;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.NOTIFICATIONTYPEATTRIBUTEVALUECHANGE;
54 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.NameAndValueChange;
55 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.Notification;
56 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.TapiNotificationListener;
57 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.ChangedAttributes;
58 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.ChangedAttributesBuilder;
59 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.ChangedAttributesKey;
60 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.TargetObjectName;
61 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.TargetObjectNameBuilder;
62 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev221121.notification.TargetObjectNameKey;
63 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.Context1;
64 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.NodeEdgePointRef;
65 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.context.TopologyContext;
66 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePoint;
67 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointKey;
68 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node;
69 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeKey;
70 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.Topology;
71 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.context.TopologyKey;
72 import org.opendaylight.yangtools.yang.binding.EnumTypeObject;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
74 import org.osgi.service.component.annotations.Activate;
75 import org.osgi.service.component.annotations.Component;
76 import org.osgi.service.component.annotations.Reference;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
80 @Component(service = TapiNetworkModelNotificationHandler.class)
81 public class TapiNetworkModelNotificationHandler {
83 private static final Logger LOG = LoggerFactory.getLogger(TapiNetworkModelNotificationHandler.class);
84 private final NetworkTransactionService networkTransactionService;
85 private final NotificationPublishService notificationPublishService;
86 private final List<ConnectivityService> connectivityServiceChanges = new ArrayList<>();
87 private final Uuid tapiTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
88 .getBytes(StandardCharsets.UTF_8)).toString());
89 private final List<LayerProtocolName> orderedServiceLayerList;
92 public TapiNetworkModelNotificationHandler(@Reference NetworkTransactionService networkTransactionService,
93 @Reference NotificationPublishService notificationPublishService) {
94 this.networkTransactionService = networkTransactionService;
95 this.notificationPublishService = notificationPublishService;
96 this.orderedServiceLayerList = List.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU,
97 LayerProtocolName.DSR, LayerProtocolName.ETH);
98 LOG.debug("TapiNetworkModelListenerImpl instantiated");
101 public CompositeListener getCompositeListener() {
102 return new CompositeListener(Set.of(
103 new CompositeListener.Component<>(Notification.class, this::onNotification)));
106 private void onNotification(Notification notification) {
107 LOG.info("Received network model notification {}", notification);
108 if (notification.getNotificationType().equals(NOTIFICATIONTYPEATTRIBUTEVALUECHANGE.VALUE)
109 && notification.getTargetObjectType().equals(OBJECTTYPETAPICONTEXT.VALUE)) {
110 if (notification.getChangedAttributes() == null) {
113 // TODO: need to re-think this to update first the connections from roadm to roadm and then the others
114 updateConnections(notification.getChangedAttributes().keySet().stream()
115 .map(changedAttributesKey -> new Uuid(changedAttributesKey.getValueName()))
116 .collect(Collectors.toList()), notification.getChangedAttributes().values().stream()
117 .map(NameAndValueChange::getNewValue)
118 .collect(Collectors.toList()));
119 updateConnectivityServices();
120 // todo set attributes
121 for (ConnectivityService connService : this.connectivityServiceChanges) {
122 sendNbiNotification(createNbiNotification(connService));
128 public void onEventNotification(EventNotification notification) {
129 LOG.info("Received network model notification {}", notification);
130 //TODO: see if implementation needed as this is declared as obsolete
133 private PublishTapiNotificationService createNbiNotification(ConnectivityService connService) {
134 if (connService == null) {
135 LOG.error("ConnService is null");
138 Map<ChangedAttributesKey, ChangedAttributes> changedStates = new HashMap<>();
139 changedStates.put(new ChangedAttributesKey("administrativeState"),
140 new ChangedAttributesBuilder()
141 .setNewValue(connService.getAdministrativeState().getName())
142 .setOldValue(connService.getAdministrativeState().equals(AdministrativeState.UNLOCKED)
143 ? AdministrativeState.LOCKED.getName() : AdministrativeState.UNLOCKED.getName())
144 .setValueName("administrativeState").build());
145 changedStates.put(new ChangedAttributesKey("operationalState"),
146 new ChangedAttributesBuilder()
147 .setNewValue(connService.getOperationalState().getName())
148 .setOldValue(connService.getOperationalState().equals(OperationalState.ENABLED)
149 ? OperationalState.DISABLED.getName() : OperationalState.ENABLED.getName())
150 .setValueName("operationalState").build());
151 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx");
152 OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneOffset.UTC);
153 DateAndTime datetime = new DateAndTime(dtf.format(offsetDateTime));
154 Map<TargetObjectNameKey, TargetObjectName> targetObjectNames = new HashMap<>();
155 if (connService.getName() != null) {
156 for (Map.Entry<NameKey, Name> entry : connService.getName().entrySet()) {
157 targetObjectNames.put(new TargetObjectNameKey(entry.getKey().getValueName()),
158 new TargetObjectNameBuilder()
159 .setValueName(entry.getValue().getValueName())
160 .setValue(entry.getValue().getValue())
165 return new PublishTapiNotificationServiceBuilder()
166 .setUuid(new Uuid(UUID.randomUUID().toString()))
167 .setTopic(connService.getUuid().getValue())
168 .setTargetObjectIdentifier(connService.getUuid())
169 .setNotificationType(NOTIFICATIONTYPEATTRIBUTEVALUECHANGE.VALUE)
170 .setChangedAttributes(changedStates)
171 .setEventTimeStamp(datetime)
172 .setTargetObjectName(targetObjectNames)
173 .setTargetObjectType(OBJECTTYPETAPICONTEXT.VALUE)
174 .setLayerProtocolName(connService.getLayerProtocolName())
178 private void sendNbiNotification(PublishTapiNotificationService service) {
180 this.notificationPublishService.putNotification(service);
181 } catch (InterruptedException e) {
182 LOG.warn("Cannot send notification to nbi", e);
183 Thread.currentThread().interrupt();
187 private void updateConnectivityServices() {
189 this.connectivityServiceChanges.clear();
190 InstanceIdentifier<ConnectivityContext> connectivityContextIID =
191 InstanceIdentifier.builder(Context.class).augmentation(
192 org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
193 .child(ConnectivityContext.class)
195 Optional<ConnectivityContext> optConnContext =
196 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityContextIID).get();
197 if (optConnContext.isEmpty()) {
198 LOG.error("Could not update TAPI connectivity services");
201 ConnectivityContext connContext = optConnContext.orElseThrow();
202 Map<Uuid, EnumTypeObject[]> states = new HashMap<>();
203 if (connContext.getConnectivityService() == null) {
206 for (ConnectivityService connService : connContext.getConnectivityService().values()) {
207 LOG.info("Connectivity service = {}", connService);
208 // TODO: maybe we need to check lower connections if my new code doesnt work
209 states.put(connService.getUuid(), getStates(connService));
210 AdministrativeState adminState = (AdministrativeState) states.get(connService.getUuid())[0];
211 OperationalState operState = (OperationalState) states.get(connService.getUuid())[1];
213 InstanceIdentifier<ConnectivityService> connServIID = InstanceIdentifier
214 .builder(Context.class).augmentation(org.opendaylight.yang.gen.v1
215 .urn.onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
216 .child(ConnectivityContext.class)
217 .child(ConnectivityService.class, new ConnectivityServiceKey(connService.getUuid()))
219 ConnectivityService changedConnServ = new ConnectivityServiceBuilder()
220 .setUuid(connService.getUuid())
221 .setAdministrativeState(adminState)
222 .setOperationalState(operState)
224 this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connServIID,
226 this.networkTransactionService.commit().get();
228 if (connService.getAdministrativeState() != adminState
229 || connService.getOperationalState() != operState) {
230 this.connectivityServiceChanges.add(changedConnServ);
233 // TODO: this last function may need some refactoring... if the PHOT_MEDIA goes down,
234 // then ODU goes down and then DSR should also go down
235 for (ConnectivityService connService : connContext.getConnectivityService().values()) {
236 AdministrativeState adminState = (AdministrativeState) states.get(connService.getUuid())[0];
237 OperationalState operState = (OperationalState) states.get(connService.getUuid())[1];
238 this.connectivityServiceChanges.addAll(updateSupportedConnectivityServices(
239 connContext.getConnectivityService().values(), connService.getUuid(), adminState, operState,
240 LayerProtocolName.ODU));
242 } catch (InterruptedException | ExecutionException e) {
243 LOG.error("Could not update TAPI connectivity services");
247 private EnumTypeObject[] getStates(ConnectivityService connService)
248 throws InterruptedException, ExecutionException {
249 OperationalState operState = OperationalState.ENABLED;
250 AdministrativeState adminState = AdministrativeState.UNLOCKED;
251 if (connService.getConnection() == null) {
252 LOG.info("No connections on service = {}", connService);
253 return new EnumTypeObject[]{null, null};
255 for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
256 .connectivity.service.Connection connection : connService.getConnection().values()) {
257 InstanceIdentifier<Connection> connIID =
258 InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
259 .onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
260 .child(ConnectivityContext.class)
261 .child(Connection.class, new ConnectionKey(connection.getConnectionUuid()))
263 Optional<Connection> optConn = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL,
265 if (optConn.isEmpty()) {
266 LOG.error("Could not get state for a TAPI connection");
269 LOG.info("State of connection {} of connectivity service {} = {}", optConn.orElseThrow().getUuid()
270 .getValue(), connService.getUuid().getValue(), optConn.orElseThrow().getOperationalState().getName());
271 if (optConn.orElseThrow().getOperationalState() == OperationalState.DISABLED) {
272 adminState = AdministrativeState.LOCKED;
273 operState = OperationalState.DISABLED;
276 return new EnumTypeObject[]{adminState, operState};
279 private void updateConnections(List<Uuid> changedOneps, List<String> onepStates) {
280 LOG.info("Updating TAPI connections");
281 LOG.info("Change in oneps = {}, new states = {}", changedOneps, onepStates);
283 //should it return a list of connections?
284 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
285 .onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContext> connectivityContextIID =
286 InstanceIdentifier.builder(Context.class).augmentation(
287 org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
288 .child(org.opendaylight.yang.gen.v1.urn
289 .onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContext.class)
291 Optional<org.opendaylight.yang.gen.v1.urn
292 .onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContext> optConnContext =
293 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityContextIID).get();
294 if (optConnContext.isEmpty()) {
295 LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
298 if (optConnContext.orElseThrow().getConnectivityService() == null) {
299 LOG.info("No TAPI connectivity service to update");
302 // TODO: order services from lower layer to upper layer
303 Map<ConnectivityServiceKey, ConnectivityService> connServMap
304 = optConnContext.orElseThrow().getConnectivityService();
305 if (connServMap == null) {
306 LOG.info("No connections to update");
309 connServMap = orderConnServiceMap(connServMap);
310 for (ConnectivityService connService : connServMap.values()) {
311 LOG.info("Looping through connectivity service = {}", connService.getUuid().getValue());
312 if (connService.getConnection() == null) {
315 for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121
316 .connectivity.service.Connection connection : connService.getConnection().values()) {
317 InstanceIdentifier<Connection> connIID =
318 InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
319 .onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
320 .child(org.opendaylight.yang.gen.v1.urn
321 .onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContext.class)
322 .child(Connection.class, new ConnectionKey(connection.getConnectionUuid()))
324 Optional<Connection> optConn =
325 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
326 if (optConn.isEmpty()) {
327 LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
330 Connection newConn = optConn.orElseThrow();
331 // Check LowerConnection states and if any of the lower connection is disabled then we can put
332 // the connection out of service. And based on the connection previous state we decide
333 // the update necessary
334 OperationalState newConnState = newConn.getOperationalState();
335 if (newConn.getLowerConnection() != null) {
336 newConnState = updateLowerConnections(changedOneps, onepStates,
337 newConn.getLowerConnection().values(), newConn.getOperationalState());
339 if (newConnState.equals(newConn.getOperationalState())) {
340 // To check if the oneps are from the original Top connection
341 newConnState = getConnectionState(changedOneps, onepStates, newConn);
344 LOG.info("Previous connection state = {} & New connection state = {}",
345 newConn.getOperationalState().getName(), newConnState.getName());
346 Connection changedConn = new ConnectionBuilder(newConn).setOperationalState(newConnState).build();
347 // TODO: the changed NEP is a DEG port which is not in any connection,
348 // therefore we also need to change the cross connections,
349 // the lower connections uuid and check the states.
350 // If any of the lower connections of a connection is DISABLED then the top connection is DISABLED
351 this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connIID, changedConn);
352 this.networkTransactionService.commit().get();
355 } catch (InterruptedException | ExecutionException e) {
356 LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
360 private Map<ConnectivityServiceKey, ConnectivityService> orderConnServiceMap(
361 Map<ConnectivityServiceKey, ConnectivityService> connServMap) {
362 Map<ConnectivityServiceKey, ConnectivityService> orderedServiceMap = new HashMap<>();
363 for (LayerProtocolName lpn:this.orderedServiceLayerList) {
364 for (ConnectivityService connServ:connServMap.values()) {
365 if (connServ.getLayerProtocolName().equals(lpn)) {
366 LOG.info("Layer of service is equal to entry of lpn = {}", lpn);
367 orderedServiceMap.put(connServ.key(), connServ);
371 LOG.info("Ordered map of services = {}", orderedServiceMap);
372 return orderedServiceMap;
375 private OperationalState updateLowerConnections(List<Uuid> changedOneps, List<String> onepStates,
376 Collection<LowerConnection> lowerConnections,
377 OperationalState uppConnState) {
378 LOG.info("Updating lower connections");
379 OperationalState topConnectionState = uppConnState;
380 Boolean allLowerConnEna = true;
382 for (LowerConnection lowerConn:lowerConnections) {
383 InstanceIdentifier<Connection> connIID =
384 InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
385 .onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
386 .child(org.opendaylight.yang.gen.v1.urn
387 .onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContext.class)
388 .child(Connection.class, new ConnectionKey(lowerConn.getConnectionUuid()))
390 Optional<Connection> optConn =
391 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
392 if (optConn.isEmpty()) {
393 LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
396 Connection newConn = optConn.orElseThrow(); // Current state of connection
397 if (newConn.getLowerConnection() != null) {
398 // TODO: we can receive disable here because the lower connection haven been yet looped through and
399 // therefore it is disabled but it has to be changed to enable before returning disable.
400 // We need to recall the update Lower Connections with the lower connection we are checking now
401 // and all its lower connections, until no lower connections are found in the connection
402 updateLowerConnections(changedOneps, onepStates, newConn.getLowerConnection().values(),
403 newConn.getOperationalState());
405 OperationalState newConnState = getConnectionState(changedOneps, onepStates, newConn);
406 // updated connection state if it contains a nep that has changed
407 if (!newConn.getOperationalState().equals(newConnState)) {
408 Connection changedConn = new ConnectionBuilder(newConn).setOperationalState(newConnState).build();
409 this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connIID, changedConn);
410 this.networkTransactionService.commit().get();
412 if (newConnState.equals(OperationalState.DISABLED)) {
413 LOG.info("LowerConnection state is disable");
414 allLowerConnEna = false;
415 topConnectionState = OperationalState.DISABLED;
418 if (allLowerConnEna) {
419 return OperationalState.ENABLED;
421 return OperationalState.DISABLED;
422 } catch (InterruptedException | ExecutionException e) {
423 LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
424 return topConnectionState;
428 private OperationalState getConnectionState(List<Uuid> changedOneps, List<String> operState, Connection conn)
429 throws InterruptedException, ExecutionException {
430 LOG.info("Getting TAPI connectionState");
431 List<Uuid> connectionNeps = Objects.requireNonNull(conn.getConnectionEndPoint()).values().stream()
432 .map(NodeEdgePointRef::getNodeEdgePointUuid).collect(Collectors.toList());
433 LOG.info("Changed neps = {}", changedOneps);
434 LOG.info("Connection NEPs = {}", connectionNeps);
435 if (!Collections.disjoint(changedOneps, connectionNeps)) {
436 LOG.info("Connection neps {} are included in changed oneps {}", connectionNeps, changedOneps);
437 if ((changedOneps.contains(connectionNeps.get(0)) ? transformOperState(operState.get(
438 changedOneps.indexOf(connectionNeps.get(0)))) : null) == OperationalState.DISABLED
439 || (changedOneps.contains(connectionNeps.get(1)) ? transformOperState(operState.get(
440 changedOneps.indexOf(connectionNeps.get(1)))) : null) == OperationalState.DISABLED) {
441 return OperationalState.DISABLED;
443 LOG.info("Didnt transform correctly the states");
444 for (Uuid connectionNep : connectionNeps) {
445 Optional<org.opendaylight.yang.gen.v1.urn
446 .onf.otcc.yang.tapi.connectivity.rev221121.connection.ConnectionEndPoint> ocep
447 = conn.getConnectionEndPoint().values().stream()
448 .filter(connectionEndPoint -> connectionEndPoint.getNodeEdgePointUuid() == connectionNep)
450 if (ocep.isEmpty()) {
453 InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
454 .augmentation(Context1.class).child(TopologyContext.class)
455 .child(Topology.class, new TopologyKey(tapiTopoUuid))
456 .child(Node.class, new NodeKey(ocep.orElseThrow().getNodeUuid()))
457 .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(connectionNep))
459 Optional<OwnedNodeEdgePoint> onep =
460 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, onepIID).get();
461 if (onep.isEmpty() || onep.orElseThrow().augmentation(OwnedNodeEdgePoint1.class) == null
462 || onep.orElseThrow().augmentation(OwnedNodeEdgePoint1.class).getCepList() == null) {
465 if (onep.orElseThrow().getOperationalState() == OperationalState.DISABLED
466 && !changedOneps.contains(onep.orElseThrow().getUuid())) {
467 return OperationalState.DISABLED;
470 return OperationalState.ENABLED;
472 LOG.info("Connection state = {}. Going to check lower connections", conn.getOperationalState());
473 // TODO --> check all lower connections state and if all of them are enabled we return enable, otherwise disable
474 if (conn.getLowerConnection() != null && allLowerConEnabled(conn.getLowerConnection().values())) {
475 return OperationalState.ENABLED;
477 return conn.getOperationalState();
480 private boolean allLowerConEnabled(Collection<LowerConnection> lowerConnections) {
482 for (LowerConnection lowerConn:lowerConnections) {
483 InstanceIdentifier<Connection> connIID =
484 InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
485 .onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
486 .child(org.opendaylight.yang.gen.v1.urn
487 .onf.otcc.yang.tapi.connectivity.rev221121.context
488 .ConnectivityContext.class)
489 .child(Connection.class, new ConnectionKey(lowerConn.getConnectionUuid()))
491 Optional<Connection> optConn =
492 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
493 if (optConn.isEmpty()) {
494 LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
497 Connection newConn = optConn.orElseThrow(); // Current state of connection
498 // updated connection state if it contains a nep that has changed
499 if (newConn.getOperationalState().equals(OperationalState.DISABLED)) {
500 LOG.info("LowerConnection state is disable");
505 } catch (InterruptedException | ExecutionException e) {
506 LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
511 private List<ConnectivityService> updateSupportedConnectivityServices(Collection<ConnectivityService> connServices,
512 Uuid supportingConnService,
513 AdministrativeState adminState,
514 OperationalState operState,
515 LayerProtocolName layer) {
516 // TODO we need to check this function
517 List<ConnectivityService> changedServices = new ArrayList<>();
518 if (adminState != AdministrativeState.LOCKED && operState != OperationalState.DISABLED) {
519 return changedServices;
522 for (ConnectivityService supportedConnService : connServices) {
523 // TODO currently supporting service uuid is saved in service layer, replace with name as soon
524 // as name is implemented
525 if (supportedConnService.getLayerProtocolName() != layer) {
528 InstanceIdentifier<ConnectivityService> supportedConnServIID = InstanceIdentifier
529 .builder(Context.class).augmentation(org.opendaylight.yang.gen.v1
530 .urn.onf.otcc.yang.tapi.connectivity.rev221121.Context1.class)
531 .child(org.opendaylight.yang.gen.v1
532 .urn.onf.otcc.yang.tapi.connectivity.rev221121.context.ConnectivityContext.class)
533 .child(ConnectivityService.class, new ConnectivityServiceKey(supportedConnService.getUuid()))
535 Optional<ConnectivityService> optNewConnService = this.networkTransactionService.read(
536 LogicalDatastoreType.OPERATIONAL, supportedConnServIID).get();
537 if (optNewConnService.isEmpty()) {
538 LOG.error("Could not update TAPI connectivity service");
541 ConnectivityService newConnService = optNewConnService.orElseThrow();
542 if (supportedConnService.getConnectivityConstraint().getServiceLevel() != null
543 && supportedConnService.getConnectivityConstraint().getServiceLevel()
544 .equals(supportingConnService.getValue())
545 && newConnService.getAdministrativeState() != AdministrativeState.LOCKED
546 && newConnService.getOperationalState() != OperationalState.DISABLED) {
548 ConnectivityService changedSupportedConnServ = new ConnectivityServiceBuilder()
549 .setUuid(supportedConnService.getUuid())
550 .setAdministrativeState(adminState)
551 .setOperationalState(operState)
553 // TODO: may need to update connections...
554 this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, supportedConnServIID,
555 changedSupportedConnServ);
556 this.networkTransactionService.commit().get();
557 changedServices.add(changedSupportedConnServ);
558 if (layer == LayerProtocolName.ODU) {
559 changedServices.addAll(updateSupportedConnectivityServices(connServices,
560 supportedConnService.getUuid(), adminState, operState, LayerProtocolName.DSR));
564 } catch (InterruptedException | ExecutionException e) {
565 LOG.error("Could not update TAPI connectivity service");
567 return changedServices;
570 private OperationalState transformOperState(String operString) {
571 LOG.debug("Operstring to be converted = {}", operString);
572 State operState = org.opendaylight.transportpce.networkmodel.util.TopologyUtils.setNetworkOperState(operString);
573 LOG.debug("State received from topologyutils = {}", operState);
574 return operState.equals(State.InService) ? OperationalState.ENABLED : OperationalState.DISABLED;