From: Gilles Thouenon Date: Sat, 6 Mar 2021 14:32:34 +0000 (+0100) Subject: Handle notification reception on port state change X-Git-Tag: 4.0.0~130 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=transportpce.git;a=commitdiff_plain;h=bb4b275b90fad3b9c03d6eda2c657ff7eefdeaca Handle notification reception on port state change - implement reception of a changeNotification on DeviceListener221 when a device port state change - rename DeviceListener to DeviceListener121 and align its implementation on the DeviceListener221 one - add a new DeviceListener710 with the same implementation of other device listeners - refactor all the NetconfTopologyListener class to remove technical debts after extension to DeviceListener221 and DeviceListener710 - refactor NetconfTopologyListenerTest UT to be aligned with the new implementation JIRA: TRNSPRTPCE-422 Signed-off-by: Gilles Thouenon Change-Id: I7af3073071e47383dbf8629d261c7d07a8113e91 --- diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java index b2c5001d4..34d2a1ea8 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListener.java @@ -7,18 +7,15 @@ */ package org.opendaylight.transportpce.networkmodel; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import com.google.common.util.concurrent.ListenableFuture; import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; +import java.util.concurrent.ExecutionException; import javax.annotation.Nonnull; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.DataObjectModification; -import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType; import org.opendaylight.mdsal.binding.api.DataTreeChangeListener; import org.opendaylight.mdsal.binding.api.DataTreeModification; import org.opendaylight.mdsal.binding.api.MountPoint; @@ -26,13 +23,14 @@ import org.opendaylight.mdsal.binding.api.NotificationService; import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry; import org.opendaylight.transportpce.common.StringConstants; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.mapping.PortMapping; import org.opendaylight.transportpce.networkmodel.dto.NodeRegistration; import org.opendaylight.transportpce.networkmodel.dto.NodeRegistration22; import org.opendaylight.transportpce.networkmodel.listeners.AlarmNotificationListener; import org.opendaylight.transportpce.networkmodel.listeners.AlarmNotificationListener221; import org.opendaylight.transportpce.networkmodel.listeners.DeOperationsListener; import org.opendaylight.transportpce.networkmodel.listeners.DeOperationsListener221; -import org.opendaylight.transportpce.networkmodel.listeners.DeviceListener; +import org.opendaylight.transportpce.networkmodel.listeners.DeviceListener121; import org.opendaylight.transportpce.networkmodel.listeners.DeviceListener221; import org.opendaylight.transportpce.networkmodel.listeners.TcaListener; import org.opendaylight.transportpce.networkmodel.listeners.TcaListener221; @@ -42,38 +40,91 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.de.operations.rev161014.O import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceListener; import org.opendaylight.yang.gen.v1.http.org.openroadm.tca.rev161014.OrgOpenroadmTcaListener; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInputBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionOutput; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class NetConfTopologyListener implements DataTreeChangeListener { private static final Logger LOG = LoggerFactory.getLogger(NetConfTopologyListener.class); - + private static final String RPC_SERVICE_FAILED = "Failed to get RpcService for node {}"; private final NetworkModelService networkModelService; private final DataBroker dataBroker; private final DeviceTransactionManager deviceTransactionManager; private final Map registrations; private final Map registrations22; + private final PortMapping portMapping; public NetConfTopologyListener(final NetworkModelService networkModelService, final DataBroker dataBroker, - DeviceTransactionManager deviceTransactionManager) { + DeviceTransactionManager deviceTransactionManager, PortMapping portMapping) { this.networkModelService = networkModelService; this.dataBroker = dataBroker; this.deviceTransactionManager = deviceTransactionManager; this.registrations = new ConcurrentHashMap<>(); this.registrations22 = new ConcurrentHashMap<>(); + this.portMapping = portMapping; + } + + public void onDataTreeChanged(@Nonnull Collection> changes) { + LOG.info("onDataTreeChanged - {}", this.getClass().getSimpleName()); + for (DataTreeModification change : changes) { + DataObjectModification rootNode = change.getRootNode(); + if (rootNode.getDataBefore() == null) { + continue; + } + String nodeId = rootNode.getDataBefore().key().getNodeId().getValue(); + NetconfNode netconfNodeBefore = rootNode.getDataBefore().augmentation(NetconfNode.class); + switch (rootNode.getModificationType()) { + case DELETE: + this.networkModelService.deleteOpenRoadmnode(nodeId); + String deviceVersion = netconfNodeBefore + .getAvailableCapabilities().getAvailableCapability().stream() + .filter(cp -> cp.getCapability().contains(StringConstants.OPENROADM_DEVICE_MODEL_NAME)) + .sorted((c1, c2) -> c1.getCapability().compareTo(c2.getCapability())) + .findFirst() + .get().getCapability(); + onDeviceDisConnected(nodeId, deviceVersion); + LOG.info("Device {} correctly disconnected from controller", nodeId); + break; + case WRITE: + NetconfNode netconfNodeAfter = rootNode.getDataAfter().augmentation(NetconfNode.class); + if (ConnectionStatus.Connecting.equals(netconfNodeBefore.getConnectionStatus()) + && ConnectionStatus.Connected.equals(netconfNodeAfter.getConnectionStatus())) { + LOG.info("Connecting Node: {}", nodeId); + Optional deviceCapabilityOpt = netconfNodeAfter + .getAvailableCapabilities().getAvailableCapability().stream() + .filter(cp -> cp.getCapability().contains(StringConstants.OPENROADM_DEVICE_MODEL_NAME)) + .sorted((c1, c2) -> c1.getCapability().compareTo(c2.getCapability())) + .findFirst(); + if (deviceCapabilityOpt.isEmpty()) { + LOG.error("Unable to get openroadm-device-capability"); + return; + } + this.networkModelService + .createOpenRoadmNode(nodeId, deviceCapabilityOpt.get().getCapability()); + onDeviceConnected(nodeId,deviceCapabilityOpt.get().getCapability()); + LOG.info("Device {} correctly connected to controller", nodeId); + } + if (ConnectionStatus.Connected.equals(netconfNodeBefore.getConnectionStatus()) + && ConnectionStatus.Connecting.equals(netconfNodeAfter.getConnectionStatus())) { + LOG.warn("Node: {} is being disconnected", nodeId); + } + break; + default: + LOG.debug("Unknown modification type {}", rootNode.getModificationType().name()); + break; + } + } } - @SuppressFBWarnings( - value = "RV_RETURN_VALUE_IGNORED", - justification = "nothing to verify once rpc has been sent") private void onDeviceConnected(final String nodeId, String openRoadmVersion) { LOG.info("onDeviceConnected: {}", nodeId); Optional mountPointOpt = this.deviceTransactionManager.getDeviceMountPoint(nodeId); @@ -84,228 +135,132 @@ public class NetConfTopologyListener implements DataTreeChangeListener { LOG.error("Failed to get mount point for node {}", nodeId); return; } - - final Optional notificationService = - mountPoint.getService(NotificationService.class); + final Optional notificationService = mountPoint.getService(NotificationService.class); if (!notificationService.isPresent()) { - LOG.error("Failed to get RpcService for node {}", nodeId); + LOG.error(RPC_SERVICE_FAILED, nodeId); return; } + switch (openRoadmVersion) { + case StringConstants.OPENROADM_DEVICE_VERSION_1_2_1: + NodeRegistration node121Registration = registrateNode121Listeners(nodeId, notificationService.get()); + registrations.put(nodeId, node121Registration); + break; + case StringConstants.OPENROADM_DEVICE_VERSION_2_2_1: + NodeRegistration22 node221Registration = registrateNode221Listeners(nodeId, notificationService.get()); + registrations22.put(nodeId, node221Registration); + break; + default: + break; + } + String streamName = "NETCONF"; + subscribeStream(mountPoint, streamName, nodeId); + } - if (openRoadmVersion.equals(StringConstants.OPENROADM_DEVICE_VERSION_1_2_1)) { - - final OrgOpenroadmAlarmListener alarmListener = new AlarmNotificationListener(this.dataBroker); - LOG.info("Registering notification listener on OrgOpenroadmAlarmListener for node: {}", nodeId); - final ListenerRegistration accessAlarmNotificationListenerRegistration = - notificationService.get().registerNotificationListener(alarmListener); - - final OrgOpenroadmDeOperationsListener deOperationsListener = new DeOperationsListener(); - LOG.info("Registering notification listener on OrgOpenroadmDeOperationsListener for node: {}", nodeId); - final ListenerRegistration - accessDeOperationasNotificationListenerRegistration = - notificationService.get().registerNotificationListener(deOperationsListener); - - final OrgOpenroadmDeviceListener deviceListener = new DeviceListener(this.deviceTransactionManager, - nodeId, this.networkModelService); - LOG.info("Registering notification listener on OrgOpenroadmDeviceListener for node: {}", nodeId); - final ListenerRegistration accessDeviceNotificationListenerRegistration = - notificationService.get().registerNotificationListener(deviceListener); - - TcaListener tcaListener = new TcaListener(); - LOG.info("Registering notification listener on OrgOpenroadmTcaListener for node: {}", nodeId); - final ListenerRegistration accessTcaNotificationListenerRegistration = - notificationService.get().registerNotificationListener(tcaListener); - - String streamName = "NETCONF"; - - if (streamName == null) { - streamName = "OPENROADM"; - } - - final Optional service = mountPoint.getService(RpcConsumerRegistry.class); - if (service.isPresent()) { - final NotificationsService rpcService = service.get().getRpcService(NotificationsService.class); - if (rpcService == null) { - LOG.error("Failed to get RpcService for node {}", nodeId); - } else { - final CreateSubscriptionInputBuilder createSubscriptionInputBuilder = - new CreateSubscriptionInputBuilder(); - createSubscriptionInputBuilder.setStream(new StreamNameType(streamName)); - LOG.info("Triggering notification stream {} for node {}", streamName, nodeId); - rpcService.createSubscription(createSubscriptionInputBuilder.build()); + private void onDeviceDisConnected(final String nodeId, String openRoadmVersion) { + LOG.info("onDeviceDisConnected: {}", nodeId); + switch (openRoadmVersion) { + case StringConstants.OPENROADM_DEVICE_VERSION_1_2_1: + NodeRegistration nodeRegistration = this.registrations.remove(nodeId); + if (nodeRegistration != null) { + nodeRegistration.getAccessAlarmNotificationListenerRegistration().close(); + nodeRegistration.getAccessDeOperationasNotificationListenerRegistration().close(); + nodeRegistration.getAccessDeviceNotificationListenerRegistration().close(); + nodeRegistration.getAccessTcaNotificationListenerRegistration().close(); } - } else { - LOG.error("Failed to get RpcService for node {}", nodeId); - } - NodeRegistration nodeRegistration = new NodeRegistration(nodeId, - accessAlarmNotificationListenerRegistration, - accessDeOperationasNotificationListenerRegistration, accessDeviceNotificationListenerRegistration, - null, accessTcaNotificationListenerRegistration); - registrations.put(nodeId, nodeRegistration); + break; + case StringConstants.OPENROADM_DEVICE_VERSION_2_2_1: + NodeRegistration22 nodeRegistration221 = this.registrations22.remove(nodeId); + if (nodeRegistration221 != null) { + nodeRegistration221.getAccessAlarmNotificationListenerRegistration().close(); + nodeRegistration221.getAccessDeOperationasNotificationListenerRegistration().close(); + nodeRegistration221.getAccessDeviceNotificationListenerRegistration().close(); + nodeRegistration221.getAccessTcaNotificationListenerRegistration().close(); + } + break; + default: + break; + } + } - } else if (openRoadmVersion.equals(StringConstants.OPENROADM_DEVICE_VERSION_2_2_1)) { - final org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev181019.OrgOpenroadmAlarmListener - alarmListener = new AlarmNotificationListener221(dataBroker); - LOG.info("Registering notification listener on OrgOpenroadmAlarmListener for node: {}", nodeId); - final ListenerRegistration accessAlarmNotificationListenerRegistration = - notificationService.get().registerNotificationListener(alarmListener); + private NodeRegistration registrateNode121Listeners(String nodeId, NotificationService notificationService) { + final OrgOpenroadmAlarmListener alarmListener = new AlarmNotificationListener(this.dataBroker); + LOG.info("Registering notification listener on OrgOpenroadmAlarmListener for node: {}", nodeId); + final ListenerRegistration accessAlarmNotificationListenerRegistration = + notificationService.registerNotificationListener(alarmListener); - final org.opendaylight.yang.gen.v1.http.org.openroadm.de.operations.rev181019 - .OrgOpenroadmDeOperationsListener deOperationsListener = new DeOperationsListener221(); - LOG.info("Registering notification listener on OrgOpenroadmDeOperationsListener for node: {}", nodeId); - final ListenerRegistration accessDeOperationasNotificationListenerRegistration = - notificationService.get().registerNotificationListener(deOperationsListener); + final OrgOpenroadmDeOperationsListener deOperationsListener = new DeOperationsListener(); + LOG.info("Registering notification listener on OrgOpenroadmDeOperationsListener for node: {}", nodeId); + final ListenerRegistration + accessDeOperationasNotificationListenerRegistration = + notificationService.registerNotificationListener(deOperationsListener); - final org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.OrgOpenroadmDeviceListener - deviceListener = new DeviceListener221(); - LOG.info("Registering notification listener on OrgOpenroadmDeviceListener for node: {}", nodeId); - final ListenerRegistration accessDeviceNotificationListenerRegistration = - notificationService.get().registerNotificationListener(deviceListener); + final OrgOpenroadmDeviceListener deviceListener = new DeviceListener121(nodeId, this.portMapping); + LOG.info("Registering notification listener on OrgOpenroadmDeviceListener for node: {}", nodeId); + final ListenerRegistration accessDeviceNotificationListenerRegistration = + notificationService.registerNotificationListener(deviceListener); - final org.opendaylight.yang.gen.v1.http.org.openroadm.tca.rev181019.OrgOpenroadmTcaListener - tcaListener = new TcaListener221(); - LOG.info("Registering notification listener on OrgOpenroadmTcaListener for node: {}", nodeId); - final ListenerRegistration accessTcaNotificationListenerRegistration = - notificationService.get().registerNotificationListener(tcaListener); + TcaListener tcaListener = new TcaListener(); + LOG.info("Registering notification listener on OrgOpenroadmTcaListener for node: {}", nodeId); + final ListenerRegistration accessTcaNotificationListenerRegistration = + notificationService.registerNotificationListener(tcaListener); + return new NodeRegistration(nodeId, accessAlarmNotificationListenerRegistration, + accessDeOperationasNotificationListenerRegistration, accessDeviceNotificationListenerRegistration, + null, accessTcaNotificationListenerRegistration); + } + private NodeRegistration22 registrateNode221Listeners(String nodeId, NotificationService notificationService) { + final org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev181019.OrgOpenroadmAlarmListener + alarmListener = new AlarmNotificationListener221(dataBroker); + LOG.info("Registering notification listener on OrgOpenroadmAlarmListener for node: {}", nodeId); + final ListenerRegistration accessAlarmNotificationListenerRegistration = + notificationService.registerNotificationListener(alarmListener); - String streamName = "NETCONF"; - if (streamName == null) { - streamName = "OPENROADM"; - } - final Optional service = mountPoint.getService(RpcConsumerRegistry.class); - if (service.isPresent()) { - final NotificationsService rpcService = service.get().getRpcService(NotificationsService.class); - if (rpcService == null) { - LOG.error("Failed to get RpcService for node {}", nodeId); - } else { - final CreateSubscriptionInputBuilder createSubscriptionInputBuilder = - new CreateSubscriptionInputBuilder(); - createSubscriptionInputBuilder.setStream(new StreamNameType(streamName)); - LOG.info("Triggering notification stream {} for node {}", streamName, nodeId); - rpcService.createSubscription(createSubscriptionInputBuilder.build()); - } - } else { - LOG.error("Failed to get RpcService for node {}", nodeId); - } - NodeRegistration22 nodeRegistration22 = new NodeRegistration22(nodeId, - accessAlarmNotificationListenerRegistration, - accessDeOperationasNotificationListenerRegistration, accessDeviceNotificationListenerRegistration, - null, accessTcaNotificationListenerRegistration); - registrations22.put(nodeId, nodeRegistration22); + final org.opendaylight.yang.gen.v1.http.org.openroadm.de.operations.rev181019 + .OrgOpenroadmDeOperationsListener deOperationsListener = new DeOperationsListener221(); + LOG.info("Registering notification listener on OrgOpenroadmDeOperationsListener for node: {}", nodeId); + final ListenerRegistration accessDeOperationasNotificationListenerRegistration = + notificationService.registerNotificationListener(deOperationsListener); - } + final org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.OrgOpenroadmDeviceListener + deviceListener = new DeviceListener221(nodeId, this.portMapping); + LOG.info("Registering notification listener on OrgOpenroadmDeviceListener for node: {}", nodeId); + final ListenerRegistration accessDeviceNotificationListenerRegistration = + notificationService.registerNotificationListener(deviceListener); + final org.opendaylight.yang.gen.v1.http.org.openroadm.tca.rev181019.OrgOpenroadmTcaListener + tcaListener = new TcaListener221(); + LOG.info("Registering notification listener on OrgOpenroadmTcaListener for node: {}", nodeId); + final ListenerRegistration accessTcaNotificationListenerRegistration = + notificationService.registerNotificationListener(tcaListener); + return new NodeRegistration22(nodeId, accessAlarmNotificationListenerRegistration, + accessDeOperationasNotificationListenerRegistration, accessDeviceNotificationListenerRegistration, + null, accessTcaNotificationListenerRegistration); } - private void onDeviceDisConnected(final String nodeId) { - LOG.info("onDeviceDisConnected: {}", nodeId); - NodeRegistration nodeRegistration = this.registrations.remove(nodeId); - if (nodeRegistration != null) { - nodeRegistration.getAccessAlarmNotificationListenerRegistration().close(); - nodeRegistration.getAccessDeOperationasNotificationListenerRegistration().close(); - nodeRegistration.getAccessDeviceNotificationListenerRegistration().close(); - nodeRegistration.getAccessTcaNotificationListenerRegistration().close(); + private boolean subscribeStream(MountPoint mountPoint, String streamName, String nodeId) { + final Optional service = mountPoint.getService(RpcConsumerRegistry.class); + if (!service.isPresent()) { + return false; } - } - - @Override - @SuppressFBWarnings( - value = "SF_SWITCH_FALLTHROUGH", - justification = "intentional fallthrough") - public void onDataTreeChanged(@Nonnull Collection> changes) { - LOG.info("onDataTreeChanged"); - for (DataTreeModification change : changes) { - DataObjectModification rootNode = change.getRootNode(); - if ((rootNode.getDataAfter() == null) && (rootNode.getModificationType() != ModificationType.DELETE)) { - LOG.error("rootNode.getDataAfter is null : Node not connected via Netconf protocol"); - continue; - } - if (rootNode.getModificationType() == ModificationType.DELETE) { - if (rootNode.getDataBefore() != null) { - String nodeId = rootNode.getDataBefore().key().getNodeId().getValue(); - LOG.info("Node {} deleted", nodeId); - this.networkModelService.deleteOpenRoadmnode(nodeId); - onDeviceDisConnected(nodeId); - } else { - LOG.error("rootNode.getDataBefore is null !"); - } - continue; - } - String nodeId = rootNode.getDataAfter().key().getNodeId().getValue(); - NetconfNode netconfNode = rootNode.getDataAfter().augmentation(NetconfNode.class); - - if ((netconfNode != null) && !StringConstants.DEFAULT_NETCONF_NODEID.equals(nodeId)) { - switch (rootNode.getModificationType()) { - case WRITE: - LOG.info("Node added: {}", nodeId); - //fallthrough - case SUBTREE_MODIFIED: - NetconfNodeConnectionStatus.ConnectionStatus connectionStatus = - netconfNode.getConnectionStatus(); - try { - List deviceCapabilities = netconfNode.getAvailableCapabilities() - .getAvailableCapability().stream().filter(cp -> cp.getCapability() - .contains(StringConstants.OPENROADM_DEVICE_MODEL_NAME)).collect(Collectors.toList()); - if (!deviceCapabilities.isEmpty()) { - Collections.sort(deviceCapabilities, (cp0, cp1) -> cp1.getCapability() - .compareTo(cp0.getCapability())); - LOG.info("OpenROADM node detected: {} {}", nodeId, connectionStatus.name()); - switch (connectionStatus) { - case Connected: - this.networkModelService.createOpenRoadmNode(nodeId, deviceCapabilities.get(0) - .getCapability()); - onDeviceConnected(nodeId,deviceCapabilities.get(0).getCapability()); - break; - case Connecting: - case UnableToConnect: - this.networkModelService.setOpenRoadmNodeStatus(nodeId, connectionStatus); - onDeviceDisConnected(nodeId); - break; - default: - LOG.warn("Unsupported device state {}", connectionStatus.getName()); - break; - } - } - - } catch (NullPointerException e) { - LOG.error("Cannot get available Capabilities"); - } - break; - default: - LOG.warn("Unexpected connection status : {}", rootNode.getModificationType()); - break; - } - } + final NotificationsService rpcService = service.get().getRpcService(NotificationsService.class); + if (rpcService == null) { + LOG.error(RPC_SERVICE_FAILED, nodeId); + return false; } - } - - - /*private String getSupportedStream(String nodeId) { - InstanceIdentifier streamsIID = InstanceIdentifier.create(Netconf.class).child(Streams.class); + final CreateSubscriptionInputBuilder createSubscriptionInputBuilder = new CreateSubscriptionInputBuilder() + .setStream(new StreamNameType(streamName)); + LOG.info("Triggering notification stream {} for node {}", streamName, nodeId); + ListenableFuture> subscription = rpcService + .createSubscription(createSubscriptionInputBuilder.build()); try { - Optional ordmInfoObject = - this.deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, - streamsIID, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); - if (!ordmInfoObject.isPresent()) { - LOG.error("Get Stream RPC is not supported"); - return "NETCONF"; - } - for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.netconf - .streams.Stream strm : ordmInfoObject.get().getStream()) { - - if ("OPENROADM".equalsIgnoreCase(strm.getName().getValue())) { - return strm.getName().getValue().toUpperCase(); - } - } - return "NETCONF"; - } catch (NullPointerException ex) { - LOG.error("NullPointerException thrown while getting Info from a non Open ROADM device {}", nodeId); - return "NETCONF"; + subscription.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Error during subscription to stream {}", streamName, e); } - }*/ + return true; + } } diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener.java deleted file mode 100644 index d7eaeeb83..000000000 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.networkmodel.listeners; - -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.opendaylight.mdsal.common.api.LogicalDatastoreType; -import org.opendaylight.transportpce.common.device.DeviceTransactionManager; -import org.opendaylight.transportpce.networkmodel.service.NetworkModelService; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.ChangeNotification; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceListener; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OtdrScanResult; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.change.notification.Edit; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DeviceListener implements OrgOpenroadmDeviceListener { - - private static final Logger LOG = LoggerFactory.getLogger(DeviceListener.class); - /* TODO: value obtained from DeviceTransactionManagerImpl and increased due to the timeout error described in - JIRA TRNSPRTPCE-249. The increase had no effect. - */ - private static final long GET_DATA_SUBMIT_TIMEOUT = 5000; - private static final TimeUnit MAX_DURATION_TO_SUBMIT_TIMEUNIT = TimeUnit.MILLISECONDS; - private final DeviceTransactionManager deviceTransactionManager; - private final String nodeId; - private final NetworkModelService networkModelService; - - public DeviceListener(DeviceTransactionManager deviceTransactionManager, String nodeId, - NetworkModelService networkModelService) { - this.deviceTransactionManager = deviceTransactionManager; - this.nodeId = nodeId; - this.networkModelService = networkModelService; - } - - /** - * Callback for change-notification. - * - * @param notification ChangeNotification object - */ - @Override - public void onChangeNotification(ChangeNotification notification) { - - LOG.info("Notification {} received {}", ChangeNotification.QNAME, notification); - // NETCONF event notification handling - String deviceComponentChanged = null; - // Seems like there is only one edit in the NETCONF notification (from honeynode experience) - Edit edit = Objects.requireNonNull(notification.getEdit()).get(0); - deviceComponentChanged = Objects.requireNonNull(edit.getTarget()).getTargetType().getSimpleName(); - // Only circuitPack type handled - switch (deviceComponentChanged) { - case "Interface": - // do changes - LOG.info("Interface modified on device {}", this.nodeId); - break; - case "CircuitPacks": - LOG.info("Circuit Pack modified on device {}", this.nodeId); - // 1. Get the name of the component modified - Iterable pathArguments = edit.getTarget().getPathArguments(); - String cpackId = null; - for (InstanceIdentifier.PathArgument pathArgument : pathArguments) { - if (!pathArgument.toString().contains("CircuitPacks")) { - LOG.warn("Path argument element doesnt reference a Circuit Pack"); - continue; - } - Pattern pattern = Pattern.compile("\\{(.*?)}", Pattern.DOTALL); - Matcher matcher = pattern.matcher(pathArgument.toString()); - while (matcher.find()) { - String cpackKey = matcher.group(1); - Pattern pattern1 = Pattern.compile("=(.*)", Pattern.DOTALL); - Matcher matcher1 = pattern1.matcher(cpackKey); - while (matcher1.find()) { - cpackId = matcher1.group(1); - } - } - } - // 2. Get new configuration of component from device - if (cpackId == null) { - LOG.warn("No Circuit pack id retrieved from NETCONF notification... aborting"); - break; - } - LOG.info("Circuit Pack {} modified on device {}", cpackId, this.nodeId); - if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) { - LOG.error("Device {} not mounted yet", nodeId); - break; - } - InstanceIdentifier cpIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(CircuitPacks.class, new CircuitPacksKey(cpackId)); - /* Creating runnable to perform configuration retrieval and topology update in a new thread - to avoid JIRA TRNSPRTCE-251 */ - Runnable handlenetconfEvent = new Runnable() { - private CircuitPacks circuitPacks; - - public CircuitPacks getCircuitPacks() { - return circuitPacks; - } - - public void setCircuitPacks(CircuitPacks circuitPacks) { - this.circuitPacks = circuitPacks; - } - - @Override - public void run() { - Optional cpacksOptional = deviceTransactionManager - .getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, cpIID, - GET_DATA_SUBMIT_TIMEOUT, MAX_DURATION_TO_SUBMIT_TIMEUNIT); - if (!cpacksOptional.isPresent()) { - LOG.error("Couldnt read from device datastore"); - return; - } - setCircuitPacks(cpacksOptional.get()); - LOG.info("Component {} configuration: {}", getCircuitPacks().getCircuitPackName(), - getCircuitPacks()); - // 3. Update openroadm-topology - networkModelService.updateOpenRoadmNetworkTopology(nodeId, getCircuitPacks()); - } - }; - Thread thread = new Thread(handlenetconfEvent); - thread.start(); - break; - default: - // TODO: handle more component types --> it implies development on honeynode simulator - LOG.warn("Component {} change not supported", deviceComponentChanged); - } - - } - - /** - * Callback for otdr-scan-result. - * - * @param notification OtdrScanResult object - */ - @Override - public void onOtdrScanResult(OtdrScanResult notification) { - - LOG.info("Notification {} received {}", OtdrScanResult.QNAME, notification); - } - -} \ No newline at end of file diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener121.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener121.java new file mode 100644 index 000000000..74ad22696 --- /dev/null +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener121.java @@ -0,0 +1,94 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.networkmodel.listeners; + +import java.util.Collection; +import java.util.LinkedList; +import org.opendaylight.transportpce.common.mapping.PortMapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210310.network.nodes.Mapping; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.ChangeNotification; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceListener; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OtdrScanResult; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.change.notification.Edit; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.Ports; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeviceListener121 implements OrgOpenroadmDeviceListener { + + private static final Logger LOG = LoggerFactory.getLogger(DeviceListener121.class); + private final String nodeId; + private final PortMapping portMapping; + + public DeviceListener121(String nodeId, PortMapping portMapping) { + this.nodeId = nodeId; + this.portMapping = portMapping; + } + + /** + * Callback for change-notification. + * + * @param notification ChangeNotification object + */ + @Override + public void onChangeNotification(ChangeNotification notification) { + if (notification.getEdit() == null) { + LOG.warn("unable to handle {} notificatin received - list of edit is null", ChangeNotification.QNAME); + return; + } + for (Edit edit : notification.getEdit()) { + // 1. Detect the org-openroadm-device object modified + switch (edit.getTarget().getTargetType().getSimpleName()) { + case "Ports": + LinkedList path = new LinkedList<>(); + path.addAll((Collection) edit.getTarget().getPathArguments()); + InstanceIdentifier portIID = (InstanceIdentifier) InstanceIdentifier + .create(path); + String portName = InstanceIdentifier.keyOf(portIID).getPortName(); + path.removeLast(); + InstanceIdentifier cpIID = (InstanceIdentifier) InstanceIdentifier + .create(path); + String cpName = InstanceIdentifier.keyOf(cpIID).getCircuitPackName(); + LOG.info("port {} of circruit-pack {} modified on device {}", portName, cpName, this.nodeId); + Mapping oldMapping = portMapping.getMapping(nodeId, cpName, portName); + if (oldMapping == null) { + return; + } + Runnable handleNetconfEvent = new Runnable() { + @Override + public void run() { + portMapping.updateMapping(nodeId, oldMapping); + LOG.info("{} : mapping data for {} updated", nodeId, + oldMapping.getLogicalConnectionPoint()); + } + }; + Thread thread = new Thread(handleNetconfEvent); + thread.start(); + break; + default: + LOG.debug("modification of type {} not managed yet", edit.getTarget().getTargetType()); + break; + } + } + } + + /** + * Callback for otdr-scan-result. + * + * @param notification OtdrScanResult object + */ + @Override + public void onOtdrScanResult(OtdrScanResult notification) { + LOG.info("Notification {} received {}", OtdrScanResult.QNAME, notification); + } + +} \ No newline at end of file diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener221.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener221.java index 87b19e2e0..9af7cfe3d 100644 --- a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener221.java +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener221.java @@ -8,41 +8,93 @@ package org.opendaylight.transportpce.networkmodel.listeners; +import java.util.Collection; +import java.util.LinkedList; +import org.opendaylight.transportpce.common.mapping.PortMapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210310.network.nodes.Mapping; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.ChangeNotification; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.CreateTechInfoNotification; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.OrgOpenroadmDeviceListener; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.OtdrScanResult; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.change.notification.Edit; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.pack.Ports; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev181019.circuit.packs.CircuitPacks; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DeviceListener221 implements OrgOpenroadmDeviceListener { private static final Logger LOG = LoggerFactory.getLogger(DeviceListener221.class); + private final String nodeId; + private final PortMapping portMapping; + + public DeviceListener221(String nodeId, PortMapping portMapping) { + this.nodeId = nodeId; + this.portMapping = portMapping; + } /** * Callback for change-notification. * - * @param notification ChangeNotification object + * @param notification + * ChangeNotification object */ @Override public void onChangeNotification(ChangeNotification notification) { - - LOG.info("Notification {} received {}", ChangeNotification.QNAME, notification); + if (notification.getEdit() == null) { + LOG.warn("unable to handle {} notificatin received - list of edit is null", ChangeNotification.QNAME); + return; + } + for (Edit edit : notification.getEdit()) { + // 1. Detect the org-openroadm-device object modified + switch (edit.getTarget().getTargetType().getSimpleName()) { + case "Ports": + LinkedList path = new LinkedList<>(); + path.addAll((Collection) edit.getTarget().getPathArguments()); + InstanceIdentifier portIID = (InstanceIdentifier) InstanceIdentifier + .create(path); + String portName = InstanceIdentifier.keyOf(portIID).getPortName(); + path.removeLast(); + InstanceIdentifier cpIID = (InstanceIdentifier) InstanceIdentifier + .create(path); + String cpName = InstanceIdentifier.keyOf(cpIID).getCircuitPackName(); + LOG.info("port {} of circruit-pack {} modified on device {}", portName, cpName, this.nodeId); + Mapping oldMapping = portMapping.getMapping(nodeId, cpName, portName); + if (oldMapping == null) { + return; + } + Runnable handleNetconfEvent = new Runnable() { + @Override + public void run() { + portMapping.updateMapping(nodeId, oldMapping); + LOG.info("{} : mapping data for {} updated", nodeId, + oldMapping.getLogicalConnectionPoint()); + } + }; + Thread thread = new Thread(handleNetconfEvent); + thread.start(); + break; + default: + LOG.debug("modification of type {} not managed yet", edit.getTarget().getTargetType()); + break; + } + } } @Override public void onCreateTechInfoNotification(CreateTechInfoNotification notification) { - } /** * Callback for otdr-scan-result. * - * @param notification OtdrScanResult object + * @param notification + * OtdrScanResult object */ @Override public void onOtdrScanResult(OtdrScanResult notification) { - LOG.info("Notification {} received {}", OtdrScanResult.QNAME, notification); } diff --git a/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener710.java b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener710.java new file mode 100644 index 000000000..27524d0d8 --- /dev/null +++ b/networkmodel/src/main/java/org/opendaylight/transportpce/networkmodel/listeners/DeviceListener710.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2021 Orange and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.networkmodel.listeners; + +import java.util.Collection; +import java.util.LinkedList; +import org.opendaylight.transportpce.common.mapping.PortMapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210310.network.nodes.Mapping; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.ChangeNotification; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.CreateTechInfoNotification; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.OrgOpenroadmDeviceListener; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.OtdrScanResult; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.change.notification.Edit; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.circuit.pack.Ports; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.circuit.packs.CircuitPacks; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeviceListener710 implements OrgOpenroadmDeviceListener { + + private static final Logger LOG = LoggerFactory.getLogger(DeviceListener710.class); + private final String nodeId; + private final PortMapping portMapping; + + public DeviceListener710(String nodeId, PortMapping portMapping) { + this.nodeId = nodeId; + this.portMapping = portMapping; + } + + /** + * Callback for change-notification. + * + * @param notification + * ChangeNotification object + */ + @Override + public void onChangeNotification(ChangeNotification notification) { + if (notification.getEdit() == null) { + LOG.warn("unable to handle {} notificatin received - list of edit is null", ChangeNotification.QNAME); + return; + } + for (Edit edit : notification.getEdit()) { + // 1. Detect the org-openroadm-device object modified + switch (edit.getTarget().getTargetType().getSimpleName()) { + case "Ports": + LinkedList path = new LinkedList<>(); + path.addAll((Collection) edit.getTarget().getPathArguments()); + InstanceIdentifier portIID = (InstanceIdentifier) InstanceIdentifier + .create(path); + String portName = InstanceIdentifier.keyOf(portIID).getPortName(); + path.removeLast(); + InstanceIdentifier cpIID = (InstanceIdentifier) InstanceIdentifier + .create(path); + String cpName = InstanceIdentifier.keyOf(cpIID).getCircuitPackName(); + LOG.info("port {} of circruit-pack {} modified on device {}", portName, cpName, this.nodeId); + Mapping oldMapping = portMapping.getMapping(nodeId, cpName, portName); + if (oldMapping == null) { + return; + } + Runnable handleNetconfEvent = new Runnable() { + @Override + public void run() { + portMapping.updateMapping(nodeId, oldMapping); + LOG.info("{} : mapping data for {} updated", nodeId, + oldMapping.getLogicalConnectionPoint()); + } + }; + Thread thread = new Thread(handleNetconfEvent); + thread.start(); + break; + default: + LOG.debug("modification of type {} not managed yet", edit.getTarget().getTargetType()); + break; + } + } + } + + @Override + public void onCreateTechInfoNotification(CreateTechInfoNotification notification) { + } + + /** + * Callback for otdr-scan-result. + * + * @param notification + * OtdrScanResult object + */ + @Override + public void onOtdrScanResult(OtdrScanResult notification) { + LOG.info("Notification {} received {}", OtdrScanResult.QNAME, notification); + } + +} diff --git a/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml b/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml index 40a5b9ec7..e4e772c10 100644 --- a/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml +++ b/networkmodel/src/main/resources/OSGI-INF/blueprint/networkmodel-blueprint.xml @@ -37,6 +37,7 @@ + diff --git a/networkmodel/src/test/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListenerTest.java b/networkmodel/src/test/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListenerTest.java index 4dd5446fe..7085174b8 100644 --- a/networkmodel/src/test/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListenerTest.java +++ b/networkmodel/src/test/java/org/opendaylight/transportpce/networkmodel/NetConfTopologyListenerTest.java @@ -8,44 +8,28 @@ package org.opendaylight.transportpce.networkmodel; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.opendaylight.transportpce.common.StringConstants.OPENROADM_DEVICE_VERSION_1_2_1; import static org.opendaylight.transportpce.common.StringConstants.OPENROADM_DEVICE_VERSION_2_2_1; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; -import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.DataObjectModification; import org.opendaylight.mdsal.binding.api.DataTreeModification; -import org.opendaylight.mdsal.binding.api.MountPoint; -import org.opendaylight.mdsal.binding.api.MountPointService; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; -import org.opendaylight.transportpce.common.device.DeviceTransactionManagerImpl; -import org.opendaylight.transportpce.common.mapping.MappingUtils; -import org.opendaylight.transportpce.common.mapping.MappingUtilsImpl; import org.opendaylight.transportpce.common.mapping.PortMapping; -import org.opendaylight.transportpce.common.mapping.PortMappingImpl; -import org.opendaylight.transportpce.common.mapping.PortMappingVersion121; -import org.opendaylight.transportpce.common.mapping.PortMappingVersion221; -import org.opendaylight.transportpce.common.mapping.PortMappingVersion710; -import org.opendaylight.transportpce.common.network.NetworkTransactionImpl; -import org.opendaylight.transportpce.common.network.NetworkTransactionService; -import org.opendaylight.transportpce.common.network.RequestProcessor; -import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfacesImpl; -import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfacesImpl121; -import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfacesImpl221; -import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfacesImpl710; import org.opendaylight.transportpce.networkmodel.service.NetworkModelService; -import org.opendaylight.transportpce.test.DataStoreContextImpl; -import org.opendaylight.transportpce.test.stub.MountPointServiceStub; -import org.opendaylight.transportpce.test.stub.MountPointStub; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; @@ -61,120 +45,148 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev15 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.yang.common.Uint16; import org.opendaylight.yangtools.yang.common.Uint32; +@RunWith(MockitoJUnitRunner.StrictStubs.class) public class NetConfTopologyListenerTest { - @Before - public void setUp() { + @Mock + private NetworkModelService networkModelService; + @Mock + private DataBroker dataBroker; + @Mock + private DeviceTransactionManager deviceTransactionManager; + @Mock + private PortMapping portMapping; + @Test + public void testOnDataTreeChangedWhenDeleteNode() { + final DataObjectModification node = mock(DataObjectModification.class); + final Collection> changes = new HashSet<>(); + final DataTreeModification ch = mock(DataTreeModification.class); + changes.add(ch); + when(ch.getRootNode()).thenReturn(node); + + final Node netconfNode = getNetconfNode("netconfNode1", NetconfNodeConnectionStatus.ConnectionStatus.Connecting, + OPENROADM_DEVICE_VERSION_2_2_1); + when(node.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE); + when(node.getDataBefore()).thenReturn(netconfNode); + NetConfTopologyListener listener = new NetConfTopologyListener(networkModelService, dataBroker, + deviceTransactionManager, portMapping); + listener.onDataTreeChanged(changes); + verify(ch, times(1)).getRootNode(); + verify(node, times(1)).getModificationType(); + verify(node, times(3)).getDataBefore(); + verify(networkModelService, times(1)).deleteOpenRoadmnode(anyString()); } @Test - public void testOnDataTreeChanged() { - - @SuppressWarnings("unchecked") final DataObjectModification newNode = mock(DataObjectModification.class); - when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE); + public void testOnDataTreeChangedWhenAddNode() { + final DataObjectModification node = mock(DataObjectModification.class); final Collection> changes = new HashSet<>(); @SuppressWarnings("unchecked") final DataTreeModification ch = mock(DataTreeModification.class); changes.add(ch); - when(ch.getRootNode()).thenReturn(newNode); - - DataStoreContextImpl dataStoreContext = new DataStoreContextImpl(); - DataBroker dataBroker = dataStoreContext.getDataBroker(); - RequestProcessor requestProcessor = new RequestProcessor(dataBroker); - NetworkTransactionService networkTransactionService = new NetworkTransactionImpl(requestProcessor); - MountPoint mountPoint = new MountPointStub(dataBroker); - MountPointService mountPointService = new MountPointServiceStub(mountPoint); - DeviceTransactionManager deviceTransactionManager = - new DeviceTransactionManagerImpl(mountPointService, 3000); - R2RLinkDiscovery linkDiskovery = new R2RLinkDiscovery( - dataBroker, deviceTransactionManager, networkTransactionService); - OpenRoadmInterfacesImpl121 openRoadmInterfacesImpl121 = - new OpenRoadmInterfacesImpl121(deviceTransactionManager); - OpenRoadmInterfacesImpl221 openRoadmInterfacesImpl221 = - new OpenRoadmInterfacesImpl221(deviceTransactionManager); - OpenRoadmInterfacesImpl710 openRoadmInterfacesImpl710 = - new OpenRoadmInterfacesImpl710(deviceTransactionManager); - MappingUtils mappingUtils = new MappingUtilsImpl(dataBroker); - OpenRoadmInterfacesImpl openRoadmInterfaces = - new OpenRoadmInterfacesImpl(deviceTransactionManager, mappingUtils, - openRoadmInterfacesImpl121, openRoadmInterfacesImpl221, openRoadmInterfacesImpl710); - PortMappingVersion121 p1 = new PortMappingVersion121(dataBroker, deviceTransactionManager, openRoadmInterfaces); - PortMappingVersion221 p2 = new PortMappingVersion221(dataBroker, deviceTransactionManager, openRoadmInterfaces); - PortMappingVersion710 p3 = new PortMappingVersion710(dataBroker, deviceTransactionManager, openRoadmInterfaces); - PortMapping portMapping = new PortMappingImpl(dataBroker,p3, p2, p1); - NetworkModelService networkModelService = mock(NetworkModelService.class); - - //Start Netconf Topology listener and start adding nodes to the Netconf Topology to verify behaviour - NetConfTopologyListener listener = new NetConfTopologyListener(networkModelService, dataBroker, - deviceTransactionManager); + when(ch.getRootNode()).thenReturn(node); - //A new node appears in Netconf Topology, status is Connecting - final Node netconfNode = getNetconfNode("test1", - NetconfNodeConnectionStatus.ConnectionStatus.Connecting, OPENROADM_DEVICE_VERSION_2_2_1); - when(newNode.getDataAfter()).thenReturn(netconfNode); - listener.onDataTreeChanged(changes); - verify(ch).getRootNode(); - verify(newNode, times(3)).getDataAfter(); - verify(newNode, times(2)).getModificationType(); - - //A new node appears in Netconf Topology, status is Connected, version is 121 - final Node netconfNode2 = getNetconfNode("test2", NetconfNodeConnectionStatus.ConnectionStatus.Connected, - OPENROADM_DEVICE_VERSION_1_2_1); - when(newNode.getDataAfter()).thenReturn(netconfNode2); - listener.onDataTreeChanged(changes); - verify(ch, times(2)).getRootNode(); - verify(newNode, times(6)).getDataAfter(); - verify(newNode, times(4)).getModificationType(); - - //A new node appears in Netconf Topology, status is Connected, version is 221 - final Node netconfNode3 = getNetconfNode("test3", NetconfNodeConnectionStatus.ConnectionStatus.Connected, - OPENROADM_DEVICE_VERSION_2_2_1); - when(newNode.getDataAfter()).thenReturn(netconfNode3); + final Node netconfNodeBefore = getNetconfNode("netconfNode1", + NetconfNodeConnectionStatus.ConnectionStatus.Connecting, OPENROADM_DEVICE_VERSION_2_2_1); + final Node netconfNodeAfter = getNetconfNode("netconfNode1", + NetconfNodeConnectionStatus.ConnectionStatus.Connected, OPENROADM_DEVICE_VERSION_2_2_1); + when(node.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE); + when(node.getDataBefore()).thenReturn(netconfNodeBefore); + when(node.getDataAfter()).thenReturn(netconfNodeAfter); + + NetConfTopologyListener listener = new NetConfTopologyListener(networkModelService, dataBroker, + deviceTransactionManager, portMapping); listener.onDataTreeChanged(changes); - verify(ch, times(3)).getRootNode(); - verify(newNode, times(9)).getDataAfter(); - verify(newNode, times(6)).getModificationType(); + verify(ch, times(1)).getRootNode(); + verify(node, times(1)).getModificationType(); + verify(node, times(3)).getDataBefore(); + verify(node, times(1)).getDataAfter(); + verify(networkModelService, times(1)).createOpenRoadmNode(anyString(), anyString()); + } + + @Test + public void testOnDataTreeChangedWhenDisconnectingNode() { + final DataObjectModification node = mock(DataObjectModification.class); + final Collection> changes = new HashSet<>(); + final DataTreeModification ch = mock(DataTreeModification.class); + changes.add(ch); + when(ch.getRootNode()).thenReturn(node); + + final Node netconfNodeBefore = getNetconfNode("netconfNode1", + NetconfNodeConnectionStatus.ConnectionStatus.Connected, OPENROADM_DEVICE_VERSION_2_2_1); + final Node netconfNodeAfter = getNetconfNode("netconfNode1", + NetconfNodeConnectionStatus.ConnectionStatus.Connecting, OPENROADM_DEVICE_VERSION_2_2_1); + when(node.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE); + when(node.getDataBefore()).thenReturn(netconfNodeBefore); + when(node.getDataAfter()).thenReturn(netconfNodeAfter); - //A new node is deleted from Netconf Topology, Data Before was empty - when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE); - when(newNode.getDataBefore()).thenReturn(netconfNode3); + NetConfTopologyListener listener = new NetConfTopologyListener(networkModelService, dataBroker, + deviceTransactionManager, portMapping); listener.onDataTreeChanged(changes); - verify(ch, times(4)).getRootNode(); - verify(newNode, times(10)).getDataAfter(); - verify(newNode, times(7)).getModificationType(); + verify(ch, times(1)).getRootNode(); + verify(node, times(1)).getModificationType(); + verify(node, times(3)).getDataBefore(); + verify(node, times(1)).getDataAfter(); + verify(networkModelService, never()).createOpenRoadmNode(anyString(), anyString()); + verify(networkModelService, never()).deleteOpenRoadmnode(anyString()); + } + + @Test + public void testOnDataTreeChangedWhenShouldNeverHappen() { + final DataObjectModification node = mock(DataObjectModification.class); + final Collection> changes = new HashSet<>(); + final DataTreeModification ch = mock(DataTreeModification.class); + changes.add(ch); + when(ch.getRootNode()).thenReturn(node); + + final Node netconfNodeBefore = getNetconfNode("netconfNode1", + NetconfNodeConnectionStatus.ConnectionStatus.Connected, OPENROADM_DEVICE_VERSION_2_2_1); + when(node.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED); + when(node.getDataBefore()).thenReturn(netconfNodeBefore); + NetConfTopologyListener listener = new NetConfTopologyListener(networkModelService, dataBroker, + deviceTransactionManager, portMapping); + listener.onDataTreeChanged(changes); + verify(ch, times(1)).getRootNode(); + verify(node, times(2)).getModificationType(); + verify(node, times(3)).getDataBefore(); + verify(node, never()).getDataAfter(); + verify(networkModelService, never()).createOpenRoadmNode(anyString(), anyString()); + verify(networkModelService, never()).deleteOpenRoadmnode(anyString()); } - public Node getNetconfNode(final String nodeId, final NetconfNodeConnectionStatus.ConnectionStatus cs, - final String openRoadmVersion) { + private Node getNetconfNode(final String nodeId, final NetconfNodeConnectionStatus.ConnectionStatus cs, + final String openRoadmVersion) { final List avCapList = new ArrayList<>(); avCapList.add(new AvailableCapabilityBuilder() - .setCapabilityOrigin(AvailableCapability.CapabilityOrigin.UserDefined) - .setCapability(openRoadmVersion) - .build()); - final AvailableCapabilities avCaps = - new AvailableCapabilitiesBuilder().setAvailableCapability(avCapList).build(); + .setCapabilityOrigin(AvailableCapability.CapabilityOrigin.UserDefined) + .setCapability(openRoadmVersion) + .build()); + final AvailableCapabilities avCaps = new AvailableCapabilitiesBuilder().setAvailableCapability(avCapList) + .build(); final NetconfNode netconfNode = new NetconfNodeBuilder() - .setConnectionStatus(cs) - .setAvailableCapabilities(avCaps) - .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) - .setPort(new PortNumber(Uint16.valueOf(9999))) - .setReconnectOnChangedSchema(true) - .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000)) - .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100)) - .setKeepaliveDelay(Uint32.valueOf(1000)) - .setTcpOnly(true) - .setCredentials(new LoginPasswordBuilder() - .setUsername("testuser") - .setPassword("testpassword") - .build()) - .build(); - final NodeBuilder nn = new NodeBuilder().setNodeId(new NodeId(nodeId)) - .addAugmentation(netconfNode); - return nn.build(); - + .setConnectionStatus(cs) + .setAvailableCapabilities(avCaps) + .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) + .setPort(new PortNumber(Uint16.valueOf(9999))) + .setReconnectOnChangedSchema(true) + .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000)) + .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100)) + .setKeepaliveDelay(Uint32.valueOf(1000)) + .setTcpOnly(true) + .setCredentials(new LoginPasswordBuilder() + .setUsername("testuser") + .setPassword("testpassword") + .build()) + .build(); + return new NodeBuilder() + .withKey(new NodeKey(new NodeId(nodeId))) + .setNodeId(new NodeId(nodeId)) + .addAugmentation(netconfNode) + .build(); } }