From cecf45ffa89611c6e1136e5b3f4df5f6510c4eb6 Mon Sep 17 00:00:00 2001 From: Jakub Morvay Date: Tue, 9 Feb 2016 11:32:26 +0100 Subject: [PATCH] More netconf-topology module unit tests Change-Id: Ia21f9c94a28c037b38b7f9ed006bdf514ff3f272 Signed-off-by: Jakub Morvay --- .../topology/util/BaseNodeManager.java | 9 +- .../topology/util/BaseTopologyManager.java | 17 +- .../netconf/topology/util/SalNodeWriter.java | 23 +- .../util/TopologyRoleChangeStrategy.java | 42 +-- .../netconf/topology/util/TopologyUtil.java | 12 +- .../topology/AbstractNetconfTopology.java | 42 +-- .../impl/ClusteredNetconfTopology.java | 1 - .../topology/impl/NetconfTopologyImpl.java | 24 +- .../topology/impl/TopologyNodeWriter.java | 14 +- .../pipeline/tx/ProxyReadOnlyTransaction.java | 18 +- .../topology/AbstractNetconfTopologyTest.java | 314 ++++++++++++++++++ .../impl/NetconfTopologyImplTest.java | 3 +- .../NetconfDeviceSlaveDataBrokerTest.java | 58 ++++ .../tx/ProxyReadOnlyTransactionTest.java | 9 + 14 files changed, 439 insertions(+), 147 deletions(-) create mode 100644 netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java create mode 100644 netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java index 2f8b1b7f62..f48f0c4e32 100644 --- a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java +++ b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java @@ -37,11 +37,7 @@ public final class BaseNodeManager implements NodeManager { private static final Logger LOG = LoggerFactory.getLogger(BaseNodeManager.class); private final String nodeId; - private final String topologyId; - private final ActorSystem actorSystem; - - private boolean isMaster = false; - private NodeManagerCallback delegate; + private final NodeManagerCallback delegate; private BaseNodeManager(final String nodeId, final String topologyId, @@ -50,8 +46,6 @@ public final class BaseNodeManager implements NodeManager { final RoleChangeStrategy roleChangeStrategy) { LOG.debug("Creating BaseNodeManager, id: {}, {}", topologyId, nodeId ); this.nodeId = nodeId; - this.topologyId = topologyId; - this.actorSystem = actorSystem; this.delegate = delegateFactory.create(nodeId, topologyId, actorSystem); // if we want to override the place election happens, // we need to override this with noop election strategy and implement election in callback @@ -97,7 +91,6 @@ public final class BaseNodeManager implements NodeManager { (roleChangeDTO.wasOwner() ? "master" : "slave"), (roleChangeDTO.isOwner() ? "master" : "slave")); - isMaster = roleChangeDTO.isOwner(); delegate.onRoleChanged(roleChangeDTO); } diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java index 664814223e..df45d9ae71 100644 --- a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java +++ b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java @@ -54,9 +54,7 @@ import org.opendaylight.netconf.topology.TopologyManagerCallback.TopologyManager import org.opendaylight.netconf.topology.util.messages.CustomIdentifyMessage; import org.opendaylight.netconf.topology.util.messages.CustomIdentifyMessageReply; import org.opendaylight.netconf.topology.util.messages.NormalizedNodeMessage; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; 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.TopologyId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; @@ -76,7 +74,6 @@ public final class BaseTopologyManager implements TopologyManager { private static final Logger LOG = LoggerFactory.getLogger(BaseTopologyManager.class); - private static final InstanceIdentifier NETWORK_TOPOLOGY_PATH = InstanceIdentifier.builder(NetworkTopology.class).build(); private final KeyedInstanceIdentifier topologyListPath; @@ -98,7 +95,6 @@ public final class BaseTopologyManager private final Set created = new HashSet<>(); private final Map peers = new HashMap<>(); - private TopologyManager masterPeer = null; private final int id = new Random().nextInt(); private boolean isMaster; @@ -138,7 +134,7 @@ public final class BaseTopologyManager // election has not yet happened this.isMaster = isMaster; - this.topologyListPath = NETWORK_TOPOLOGY_PATH.child(Topology.class, new TopologyKey(new TopologyId(topologyId))); + this.topologyListPath = TopologyUtil.createTopologyListPath(topologyId); LOG.debug("Base manager started ", +id); } @@ -176,7 +172,7 @@ public final class BaseTopologyManager // only master should call connect on peers and aggregate futures for (TopologyManager topologyManager : peers.values()) { // convert binding into NormalizedNode for transfer - final Entry> normalizedNodeEntry = codecRegistry.toNormalizedNode(getNodeIid(topologyId), node); + final Entry> normalizedNodeEntry = codecRegistry.toNormalizedNode(TopologyUtil.createTopologyNodePath(topologyId), node); LOG.debug("YangInstanceIdentifier {}", normalizedNodeEntry.getKey()); LOG.debug("Value {}", normalizedNodeEntry.getValue()); @@ -268,11 +264,6 @@ public final class BaseTopologyManager return delegateTopologyHandler.onNodeUpdated(nodeId, node); } - private static InstanceIdentifier getNodeIid(final String topologyId) { - final InstanceIdentifier networkTopology = InstanceIdentifier.create(NetworkTopology.class); - return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId))).child(Node.class); - } - @Override public ListenableFuture onNodeDeleted(final NodeId nodeId) { final ArrayList> futures = new ArrayList<>(); @@ -498,7 +489,7 @@ public final class BaseTopologyManager Futures.addCallback(listenableFuture, new FutureCallback() { @Override public void onSuccess(Node result) { - final Entry> entry = codecRegistry.toNormalizedNode(getNodeIid(topologyId), result); + final Entry> entry = codecRegistry.toNormalizedNode(TopologyUtil.createTopologyNodePath(topologyId), result); promise.success(new NormalizedNodeMessage(entry.getKey(), entry.getValue())); } @@ -605,7 +596,7 @@ public final class BaseTopologyManager public void onSuccess(Optional result) { if (result.isPresent() && result.get().getNode() != null) { for (final Node node : result.get().getNode()) { - final Entry> entry = codecRegistry.toNormalizedNode(getNodeIid(topologyId), node); + final Entry> entry = codecRegistry.toNormalizedNode(TopologyUtil.createTopologyNodePath(topologyId), node); peer.onRemoteNodeCreated(new NormalizedNodeMessage(entry.getKey(), entry.getValue())); // we dont care about the future from now on since we will be notified by the onConnected event } diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java index 8d63e89cf4..33cde89cd9 100644 --- a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java +++ b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java @@ -16,14 +16,9 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; 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.TopologyId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; 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.NodeKey; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,33 +29,30 @@ public final class SalNodeWriter implements NodeWriter { private final DataBroker dataBroker; private final String topologyId; - private final InstanceIdentifier topologyListPath; - public SalNodeWriter(final DataBroker dataBroker, final String topologyId) { this.dataBroker = dataBroker; this.topologyId = topologyId; - this.topologyListPath = createTopologyId(this.topologyId); } //FIXME change to txChains @Override public void init(@Nonnull final NodeId id, @Nonnull final Node operationalDataNode) { // put into Datastore final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction(); - wTx.put(LogicalDatastoreType.OPERATIONAL, createBindingPathForTopology(id), operationalDataNode); + wTx.put(LogicalDatastoreType.OPERATIONAL, TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId), operationalDataNode); commitTransaction(wTx, id, "init"); } @Override public void update(@Nonnull final NodeId id, @Nonnull final Node operationalDataNode) { // merge final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction(); - wTx.put(LogicalDatastoreType.OPERATIONAL, createBindingPathForTopology(id), operationalDataNode); + wTx.put(LogicalDatastoreType.OPERATIONAL, TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId), operationalDataNode); commitTransaction(wTx, id, "update"); } @Override public void delete(@Nonnull final NodeId id) { // delete final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction(); - wTx.delete(LogicalDatastoreType.OPERATIONAL, createBindingPathForTopology(id)); + wTx.delete(LogicalDatastoreType.OPERATIONAL, TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId)); commitTransaction(wTx, id, "delete"); } @@ -84,13 +76,4 @@ public final class SalNodeWriter implements NodeWriter { } }); } - - private InstanceIdentifier createBindingPathForTopology(final NodeId id) { - return topologyListPath.child(Node.class, new NodeKey(id)); - } - - private InstanceIdentifier createTopologyId(final String topologyId) { - final InstanceIdentifier networkTopology = InstanceIdentifier.create(NetworkTopology.class); - return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId))); - } } diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java index 94cd8799af..a7fc412135 100644 --- a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java +++ b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java @@ -25,17 +25,8 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.netconf.topology.NodeListener; import org.opendaylight.netconf.topology.RoleChangeStrategy; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; -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.TopologyId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; 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.NodeKey; import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.Identifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -103,9 +94,9 @@ public class TopologyRoleChangeStrategy implements RoleChangeStrategy, Clustered LOG.warn("Gained ownership of entity, registering datastore listener"); if (datastoreListenerRegistration == null) { - LOG.debug("Listener on path {}", createTopologyId(entityType).child(Node.class).getPathArguments()); + LOG.debug("Listener on path {}", TopologyUtil.createTopologyListPath(entityType).child(Node.class).getPathArguments()); datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener( - new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, createTopologyId(entityType).child(Node.class)), this); + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, TopologyUtil.createTopologyListPath(entityType).child(Node.class)), this); } } else if (datastoreListenerRegistration != null) { LOG.warn("No longer owner of entity, unregistering datastore listener"); @@ -127,39 +118,16 @@ public class TopologyRoleChangeStrategy implements RoleChangeStrategy, Clustered switch (rootNode.getModificationType()) { case WRITE: LOG.debug("Data was Created {}, {}", rootNode.getIdentifier(), rootNode.getDataAfter()); - ownershipCandidate.onNodeCreated(getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); + ownershipCandidate.onNodeCreated(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); break; case SUBTREE_MODIFIED: LOG.debug("Data was Updated {}, {}", rootNode.getIdentifier(), rootNode.getDataAfter()); - ownershipCandidate.onNodeUpdated(getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); + ownershipCandidate.onNodeUpdated(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); break; case DELETE: LOG.debug("Data was Deleted {}", rootNode.getIdentifier()); - ownershipCandidate.onNodeDeleted(getNodeId(rootNode.getIdentifier())); + ownershipCandidate.onNodeDeleted(TopologyUtil.getNodeId(rootNode.getIdentifier())); } } } - - /** - * Determines the Netconf Node Node ID, given the node's instance - * identifier. - * - * @param pathArgument Node's path arument - * @return NodeId for the node - */ - private NodeId getNodeId(final PathArgument pathArgument) { - if (pathArgument instanceof InstanceIdentifier.IdentifiableItem) { - - final Identifier key = ((InstanceIdentifier.IdentifiableItem) pathArgument).getKey(); - if(key instanceof NodeKey) { - return ((NodeKey) key).getNodeId(); - } - } - throw new IllegalStateException("Unable to create NodeId from: " + pathArgument); - } - - private static InstanceIdentifier createTopologyId(final String topologyId) { - final InstanceIdentifier networkTopology = InstanceIdentifier.create(NetworkTopology.class); - return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId))); - } } diff --git a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyUtil.java b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyUtil.java index 273d062309..d7c700d1a9 100644 --- a/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyUtil.java +++ b/netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyUtil.java @@ -13,9 +13,11 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +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.NodeKey; import org.opendaylight.yangtools.yang.binding.Identifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; public final class TopologyUtil { @@ -41,8 +43,16 @@ public final class TopologyUtil { throw new IllegalStateException("Unable to create NodeId from: " + pathArgument); } - public static InstanceIdentifier createTopologyId(final String topologyId) { + public static KeyedInstanceIdentifier createTopologyListPath(final String topologyId) { final InstanceIdentifier networkTopology = InstanceIdentifier.create(NetworkTopology.class); return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId))); } + + public static InstanceIdentifier createTopologyNodeListPath(final NodeKey key, final String topologyId) { + return createTopologyListPath(topologyId).child(Node.class, new NodeKey(new NodeId(key.getNodeId().getValue()))); + } + + public static InstanceIdentifier createTopologyNodePath(final String topologyId) { + return createTopologyListPath(topologyId).child(Node.class); + } } diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java index 488b680ab5..777adcf405 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java @@ -57,16 +57,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; 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.netconf.node.credentials.Credentials; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; 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.TopologyId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; 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.NodeKey; -import org.opendaylight.yangtools.yang.binding.Identifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory; import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository; import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter; @@ -302,7 +294,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null; final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory(); // Only checks to ensure the String is not empty or null; further checks related to directory accessibility and file permissions - // are handled during the FilesystemScehamSourceCache initialization. + // are handled during the FilesystemSchemaSourceCache initialization. if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) { // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry and // SchemaContextFactory remain the default values. @@ -312,7 +304,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if they already exist schemaResourcesDTO = schemaResourcesDTOs.get(moduleSchemaCacheDirectory); if (schemaResourcesDTO == null) { - schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory, nodeId.getValue()); + schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory); schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener( TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(), schemaResourcesDTO.getSchemaRegistry()) ); @@ -341,9 +333,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin * @param moduleSchemaCacheDirectory The string directory relative to "cache" * @return A DTO containing the Schema classes for the Netconf mount. */ - private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory, - final String instanceName) { - + private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) { final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory); final SchemaContextFactory schemaContextFactory = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); @@ -412,7 +402,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin @Override public void onSessionInitiated(ProviderSession session) { - mountPointService = session.getService(DOMMountPointService.class); + mountPointService = session.getService(DOMMountPointService.class); } @Override @@ -420,30 +410,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin return Collections.emptySet(); } - //TODO this needs to be an util method, since netconf clustering uses this aswell - /** - * Determines the Netconf Node Node ID, given the node's instance - * identifier. - * - * @param pathArgument Node's path arument - * @return NodeId for the node - */ - protected NodeId getNodeId(final PathArgument pathArgument) { - if (pathArgument instanceof InstanceIdentifier.IdentifiableItem) { - - final Identifier key = ((InstanceIdentifier.IdentifiableItem) pathArgument).getKey(); - if(key instanceof NodeKey) { - return ((NodeKey) key).getNodeId(); - } - } - throw new IllegalStateException("Unable to create NodeId from: " + pathArgument); - } - - protected static InstanceIdentifier createTopologyId(final String topologyId) { - final InstanceIdentifier networkTopology = InstanceIdentifier.create(NetworkTopology.class); - return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId))); - } - private InetSocketAddress getSocketAddress(final Host host, int port) { if(host.getDomainName() != null) { return new InetSocketAddress(host.getDomainName().getValue(), port); diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java index 76656b4674..1d440cc125 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java @@ -192,7 +192,6 @@ public class ClusteredNetconfTopology extends AbstractNetconfTopology implements return ((TopologyMountPointFacade) activeConnectors.get(node).getFacade()).registerConnectionStatusListener(listener); } - @Override public Collection getProviderFunctionality() { return Collections.emptySet(); } diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java index 0a14740903..33b468ce2b 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java @@ -35,6 +35,7 @@ import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; import org.opendaylight.netconf.topology.AbstractNetconfTopology; import org.opendaylight.netconf.topology.SchemaRepositoryProvider; import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade.ConnectionStatusListenerRegistration; +import org.opendaylight.netconf.topology.util.TopologyUtil; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; @@ -125,7 +126,8 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology implements Data LOG.debug("Registering datastore listener"); datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener( - new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, createTopologyId(topologyId).child(Node.class)), this); + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, + TopologyUtil.createTopologyListPath(topologyId).child(Node.class)), this); } @@ -136,21 +138,21 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology implements Data final DataObjectModification rootNode = change.getRootNode(); switch (rootNode.getModificationType()) { case SUBTREE_MODIFIED: - LOG.debug("Config for node {} updated", getNodeId(rootNode.getIdentifier())); - disconnectNode(getNodeId(rootNode.getIdentifier())); - connectNode(getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); + LOG.debug("Config for node {} updated", TopologyUtil.getNodeId(rootNode.getIdentifier())); + disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier())); + connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); break; case WRITE: - LOG.debug("Config for node {} created", getNodeId(rootNode.getIdentifier())); - if (activeConnectors.containsKey(getNodeId(rootNode.getIdentifier()))) { - LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", getNodeId(rootNode.getIdentifier())); - disconnectNode(getNodeId(rootNode.getIdentifier())); + LOG.debug("Config for node {} created", TopologyUtil.getNodeId(rootNode.getIdentifier())); + if (activeConnectors.containsKey(TopologyUtil.getNodeId(rootNode.getIdentifier()))) { + LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", TopologyUtil.getNodeId(rootNode.getIdentifier())); + disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier())); } - connectNode(getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); + connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter()); break; case DELETE: - LOG.debug("Config for node {} deleted", getNodeId(rootNode.getIdentifier())); - disconnectNode(getNodeId(rootNode.getIdentifier())); + LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier())); + disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier())); break; } } diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java index 90caf84bd7..810679917c 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java @@ -23,6 +23,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionChain; import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.netconf.topology.util.NodeWriter; +import org.opendaylight.netconf.topology.util.TopologyUtil; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; @@ -82,7 +83,7 @@ public class TopologyNodeWriter implements NodeWriter{ final WriteTransaction writeTx = txChain.newWriteOnlyTransaction(); createNetworkTopologyIfNotPresent(writeTx, LogicalDatastoreType.OPERATIONAL); - final InstanceIdentifier path = createBindingPathForTopology(new NodeKey(id), topologyId); + final InstanceIdentifier path = TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId); LOG.trace("{}: Init device state transaction {} putting if absent operational data started. Putting data on path {}", id.getValue(), writeTx.getIdentifier(), path); @@ -102,7 +103,7 @@ public class TopologyNodeWriter implements NodeWriter{ try { final WriteTransaction writeTx = txChain.newWriteOnlyTransaction(); - final InstanceIdentifier path = createBindingPathForTopology(new NodeKey(id), topologyId); + final InstanceIdentifier path = TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId); LOG.trace("{}: Update device state transaction {} merging operational data started. Putting data on path {}", id, writeTx.getIdentifier(), operationalDataNode); writeTx.put(LogicalDatastoreType.OPERATIONAL, path, operationalDataNode); @@ -122,7 +123,7 @@ public class TopologyNodeWriter implements NodeWriter{ try { final WriteTransaction writeTx = txChain.newWriteOnlyTransaction(); - final InstanceIdentifier path = createBindingPathForTopology(new NodeKey(id), topologyId); + final InstanceIdentifier path = TopologyUtil.createTopologyNodeListPath(new NodeKey(id), topologyId); LOG.trace( "{}: Close device state transaction {} removing all data started. Path: {}", @@ -171,11 +172,4 @@ public class TopologyNodeWriter implements NodeWriter{ Topology.QNAME, writeTx.getIdentifier()); writeTx.merge(datastoreType, topologyListPath, topology); } - - private static InstanceIdentifier createBindingPathForTopology(final NodeKey key, final String topologyId) { - final InstanceIdentifier networkTopology = InstanceIdentifier.builder(NetworkTopology.class).build(); - final KeyedInstanceIdentifier topology = networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId))); - return topology - .child(Node.class, new NodeKey(new NodeId(key.getNodeId().getValue()))); - } } diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransaction.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransaction.java index c67673b05b..a093e1cc8d 100644 --- a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransaction.java +++ b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransaction.java @@ -58,13 +58,17 @@ public class ProxyReadOnlyTransaction implements DOMDataReadOnlyTransaction{ @Override public void onComplete(Throwable throwable, Optional normalizedNodeMessage) throws Throwable { if (throwable == null) { - settableFuture.set(normalizedNodeMessage.transform(new Function>() { - @Nullable - @Override - public NormalizedNode apply(NormalizedNodeMessage input) { - return input.getNode(); - } - })); + if (normalizedNodeMessage.isPresent()) { + settableFuture.set(normalizedNodeMessage.transform(new Function>() { + @Nullable + @Override + public NormalizedNode apply(NormalizedNodeMessage input) { + return input.getNode(); + } + })); + } else { + settableFuture.set(Optional.absent()); + } } else { settableFuture.setException(throwable); } diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java new file mode 100644 index 0000000000..a29d95eb1a --- /dev/null +++ b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. 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.netconf.topology; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import akka.actor.ActorContext; +import akka.actor.ActorRef; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; +import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.ImmediateEventExecutor; +import io.netty.util.concurrent.SucceededFuture; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.concurrent.ExecutionException; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.config.threadpool.ScheduledThreadPool; +import org.opendaylight.controller.config.threadpool.ThreadPool; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.netconf.client.NetconfClientDispatcher; +import org.opendaylight.netconf.client.NetconfClientSessionListener; +import org.opendaylight.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration; +import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler; +import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice; +import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities; +import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences; +import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade; +import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; +import org.opendaylight.netconf.topology.pipeline.TopologyMountPointFacade; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; +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.NetconfNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder; +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.yangtools.yang.binding.DataContainer; +import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository; + +public class AbstractNetconfTopologyTest { + + private static final NodeId NODE_ID = new NodeId("testing-node"); + private static final String TOPOLOGY_ID = "testing-topology"; + + @Mock + private Broker mockedDataBroker; + + @Mock + private NetconfClientDispatcher mockedClientDispatcher; + + @Mock + private BindingAwareBroker mockedBindingAwareBroker; + + @Mock + private EventExecutor mockedEventExecutor; + + @Mock + private ScheduledThreadPool mockedKeepaliveExecutor; + + @Mock + private ThreadPool mockedProcessingExecutor; + + @Mock + private SchemaRepositoryProvider mockedSchemaRepositoryProvider; + + + private TestingAbstractNetconfTopology topology; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(mockedSchemaRepositoryProvider.getSharedSchemaRepository()).thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo")); + when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService()); + Future future = new SucceededFuture<>(ImmediateEventExecutor.INSTANCE, null); + when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class))).thenReturn(future); + + topology = new TestingAbstractNetconfTopology(TOPOLOGY_ID, mockedClientDispatcher, mockedBindingAwareBroker, + mockedDataBroker, mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider); + } + + @Test + public void testCreateSalFacade() { + NetconfNode testingNode = new NetconfNodeBuilder() + .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) + .setPort(new PortNumber(9999)) + .setReconnectOnChangedSchema(true) + .setDefaultRequestTimeoutMillis(1000L) + .setBetweenAttemptsTimeoutMillis(100) + .build(); + + AbstractNetconfTopology.NetconfConnectorDTO connectorDTO = topology.createDeviceCommunicator(NODE_ID, testingNode); + assertSame(connectorDTO.getFacade(), topology.getFacade()); + } + + @Test + public void testCreateKeepAliveSalFacade() { + NetconfNode testingNode = new NetconfNodeBuilder() + .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) + .setPort(new PortNumber(9999)) + .setReconnectOnChangedSchema(true) + .setDefaultRequestTimeoutMillis(1000L) + .setBetweenAttemptsTimeoutMillis(100) + .setKeepaliveDelay(1L) + .build(); + + AbstractNetconfTopology.NetconfConnectorDTO connectorDTO = topology.createDeviceCommunicator(NODE_ID, testingNode); + assertTrue(connectorDTO.getFacade() instanceof KeepaliveSalFacade); + } + + @Test + public void testSetupSchemaResourceDTO() { + NetconfNode testingNode = new NetconfNodeBuilder() + .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) + .setPort(new PortNumber(9999)) + .setReconnectOnChangedSchema(true) + .setDefaultRequestTimeoutMillis(1000L) + .setBetweenAttemptsTimeoutMillis(100) + .setKeepaliveDelay(1000L).build(); + + NetconfDevice.SchemaResourcesDTO resultDTO = topology.setupSchemaCacheDTO(NODE_ID, testingNode); + SharedSchemaRepository repo = (SharedSchemaRepository) resultDTO.getSchemaRegistry(); + assertEquals(repo.getIdentifier(), "sal-netconf-connector"); + + testingNode = new NetconfNodeBuilder() + .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) + .setPort(new PortNumber(9999)) + .setReconnectOnChangedSchema(true) + .setDefaultRequestTimeoutMillis(1000L) + .setBetweenAttemptsTimeoutMillis(100) + .setKeepaliveDelay(1000L) + .setSchemaCacheDirectory("test-directory") + .build(); + + resultDTO = topology.setupSchemaCacheDTO(NODE_ID, testingNode); + repo = (SharedSchemaRepository) resultDTO.getSchemaRegistry(); + assertEquals(repo.getIdentifier(), "test-directory"); + } + + @Test + public void testGetClientConfig() throws UnknownHostException { + NetconfClientSessionListener listener = mock(NetconfClientSessionListener.class); + Host host = new Host(new IpAddress(new Ipv4Address("127.0.0.1"))); + PortNumber portNumber = new PortNumber(9999); + NetconfNode testingNode = new NetconfNodeBuilder() + .setConnectionTimeoutMillis(1000L) + .setDefaultRequestTimeoutMillis(2000L) + .setHost(host) + .setPort(portNumber) + .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build()) + .setTcpOnly(true) + .build(); + NetconfReconnectingClientConfiguration defaultClientConfig = topology.getClientConfig(listener, testingNode); + + assertEquals(defaultClientConfig.getConnectionTimeoutMillis().longValue(), 1000L); + assertEquals(defaultClientConfig.getAddress(), new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999)); + assertSame(defaultClientConfig.getSessionListener(), listener); + assertEquals(defaultClientConfig.getAuthHandler().getUsername(), "testuser"); + assertEquals(defaultClientConfig.getProtocol(), NetconfClientConfiguration.NetconfClientProtocol.TCP); + } + + @Test + public void testGetClientConfigNotSupportedCredentialsFail() { + NetconfClientSessionListener listener = mock(NetconfClientSessionListener.class); + Host host = new Host(new IpAddress(new Ipv4Address("127.0.0.1"))); + PortNumber portNumber = new PortNumber(9999); + + Credentials notSupportedCredentials = new Credentials() { + @Override + public Class getImplementedInterface() { + return Credentials.class; + } + }; + + NetconfNode testingNode = new NetconfNodeBuilder() + .setConnectionTimeoutMillis(1000L) + .setDefaultRequestTimeoutMillis(2000L) + .setHost(host) + .setPort(portNumber) + .setCredentials(notSupportedCredentials) + .setTcpOnly(true) + .build(); + try { + topology.getClientConfig(listener, testingNode); + fail("Exception expected here."); + } catch(Exception e) { + assertTrue(e instanceof IllegalStateException); + } + } + + @Test + public void testConnectNode() { + NetconfNode testingNode = new NetconfNodeBuilder() + .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) + .setPort(new PortNumber(9999)) + .setReconnectOnChangedSchema(true) + .setDefaultRequestTimeoutMillis(1000L) + .setBetweenAttemptsTimeoutMillis(100) + .setKeepaliveDelay(1000L) + .setTcpOnly(true) + .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build()) + .build(); + Node nd = mock(Node.class); + when(nd.getAugmentation(NetconfNode.class)).thenReturn(testingNode); + topology.connectNode(NODE_ID, nd); + assertTrue(topology.activeConnectors.containsKey(NODE_ID)); + } + + @Test + public void testDisconnectNode() { + NetconfNode testingNode = new NetconfNodeBuilder() + .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1")))) + .setPort(new PortNumber(9999)) + .setReconnectOnChangedSchema(true) + .setDefaultRequestTimeoutMillis(1000L) + .setBetweenAttemptsTimeoutMillis(100) + .setKeepaliveDelay(1000L) + .setTcpOnly(true) + .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build()) + .build(); + Node nd = mock(Node.class); + when(nd.getAugmentation(NetconfNode.class)).thenReturn(testingNode); + topology.connectNode(NODE_ID, nd); + assertTrue(topology.activeConnectors.containsKey(NODE_ID)); + assertTrue(topology.disconnectNode(NODE_ID).isDone()); + assertTrue(!topology.activeConnectors.containsKey(NODE_ID)); + verify(topology.getFacade()).close(); + } + + @Test + public void testDisconnectNotConnectedNode() throws ExecutionException, InterruptedException { + ListenableFuture disconnectFuture = topology.disconnectNode(NODE_ID); + assertTrue(disconnectFuture.isDone()); + try { + disconnectFuture.get(); + fail("Exception expected!"); + } catch(Exception e) { + assertTrue(e instanceof ExecutionException); + assertTrue(e.getCause() instanceof IllegalStateException); + } + } + + public static class TestingAbstractNetconfTopology extends AbstractNetconfTopology { + + private RemoteDeviceHandler salFacade; + + protected TestingAbstractNetconfTopology(String topologyId, NetconfClientDispatcher clientDispatcher, + BindingAwareBroker bindingAwareBroker, Broker domBroker, + EventExecutor eventExecutor, ScheduledThreadPool keepaliveExecutor, + ThreadPool processingExecutor, + SchemaRepositoryProvider schemaRepositoryProvider) { + super(topologyId, clientDispatcher, bindingAwareBroker, domBroker, eventExecutor, keepaliveExecutor, processingExecutor, schemaRepositoryProvider); + salFacade = mock(RemoteDeviceHandler.class); + } + + public RemoteDeviceHandler getFacade() { + return salFacade; + } + + @Override + public void onSessionInitiated(BindingAwareBroker.ProviderContext session) { + + } + + @Override + protected RemoteDeviceHandler createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker, long defaultRequestTimeoutMillis) { + return salFacade; + } + + @Override + public TopologyMountPointFacade.ConnectionStatusListenerRegistration registerConnectionStatusListener(NodeId node, RemoteDeviceHandler listener) { + return null; + } + + @Override + public void registerMountPoint(ActorContext context, NodeId nodeId) { + + } + + @Override + public void registerMountPoint(ActorContext context, NodeId nodeId, ActorRef masterRef) { + + } + + @Override + public void unregisterMountPoint(NodeId nodeId) { + + } + } +} \ No newline at end of file diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java index 1c84668ba8..caff132e58 100644 --- a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java +++ b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java @@ -158,7 +158,8 @@ public class NetconfTopologyImplTest { when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE); InstanceIdentifier.PathArgument pa = null; - for (InstanceIdentifier.PathArgument p : TopologyUtil.createTopologyId(TOPOLOGY_ID).child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) { + + for (InstanceIdentifier.PathArgument p : TopologyUtil.createTopologyListPath(TOPOLOGY_ID).child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) { pa = p; } diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java new file mode 100644 index 0000000000..417978d6c1 --- /dev/null +++ b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. 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.netconf.topology.pipeline; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import akka.actor.ActorSystem; +import java.net.InetSocketAddress; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; +import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; + +public class NetconfDeviceSlaveDataBrokerTest { + + private static final RemoteDeviceId REMOTE_DEVICE_ID = new RemoteDeviceId("testing-device", new InetSocketAddress(9999)); + + @Mock + private ProxyNetconfDeviceDataBroker mockedDataBroker; + + @Mock + private ActorSystem mockedActorSystem; + + private NetconfDeviceSlaveDataBroker slaveDataBroker; + + @Before + public void setUp() { + slaveDataBroker = new NetconfDeviceSlaveDataBroker(mockedActorSystem, REMOTE_DEVICE_ID, mockedDataBroker); + } + + @Test(expected = UnsupportedOperationException.class) + public void testRegisterDataChangeListener() { + slaveDataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY, + mock(DOMDataChangeListener.class), AsyncDataBroker.DataChangeScope.SUBTREE); + } + + @Test(expected = UnsupportedOperationException.class) + public void testCreateTransactionChain() { + slaveDataBroker.createTransactionChain(mock(TransactionChainListener.class)); + } + + @Test + public void testGetSupportedExtensions() { + assertTrue(slaveDataBroker.getSupportedExtensions().isEmpty()); + } +} \ No newline at end of file diff --git a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java index d7d7c94d51..afde0a0537 100644 --- a/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java +++ b/netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java @@ -89,6 +89,15 @@ public class ProxyReadOnlyTransactionTest { } } + @Test + public void testDataOnPathDoesNotExistPathRead() throws ReadFailedException { + when(mockedProxyDataBroker.read(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class))) + .thenReturn(Futures.successful(Optional.absent())); + CheckedFuture>, ReadFailedException> readResultFuture = proxyReadOnlyTx.read(LogicalDatastoreType.CONFIGURATION, path); + verify(mockedProxyDataBroker).read(eq(LogicalDatastoreType.CONFIGURATION), eq(path)); + assertTrue(readResultFuture.isDone()); + assertTrue(!readResultFuture.checkedGet().isPresent()); + } @Test public void testFailedExists() { -- 2.36.6