More netconf-topology module unit tests 40/35140/7
authorJakub Morvay <jmorvay@cisco.com>
Tue, 9 Feb 2016 10:32:26 +0000 (11:32 +0100)
committerJakub Morvay <jmorvay@cisco.com>
Thu, 25 Feb 2016 12:29:40 +0000 (13:29 +0100)
Change-Id: Ia21f9c94a28c037b38b7f9ed006bdf514ff3f272
Signed-off-by: Jakub Morvay <jmorvay@cisco.com>
14 files changed:
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseNodeManager.java
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/BaseTopologyManager.java
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/SalNodeWriter.java
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyRoleChangeStrategy.java
netconf/abstract-topology/src/main/java/org/opendaylight/netconf/topology/util/TopologyUtil.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/TopologyNodeWriter.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransaction.java
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/AbstractNetconfTopologyTest.java [new file with mode: 0644]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/NetconfDeviceSlaveDataBrokerTest.java [new file with mode: 0644]
netconf/netconf-topology/src/test/java/org/opendaylight/netconf/topology/pipeline/tx/ProxyReadOnlyTransactionTest.java

index 2f8b1b7f6220cc28cfbff9064f39caa30b281f44..f48f0c4e3269c89b2e649c10d6ac460cc1e1561f 100644 (file)
@@ -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);
     }
 
index 664814223e666830c7346a68229d68ff23eb2e9f..df45d9ae714f876ef2864d2cea89a7b4117077f3 100644 (file)
@@ -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<NetworkTopology> NETWORK_TOPOLOGY_PATH = InstanceIdentifier.builder(NetworkTopology.class).build();
 
     private final KeyedInstanceIdentifier<Topology, TopologyKey> topologyListPath;
 
@@ -98,7 +95,6 @@ public final class BaseTopologyManager
     private final Set<NodeId> created = new HashSet<>();
 
     private final Map<Address, TopologyManager> 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<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = codecRegistry.toNormalizedNode(getNodeIid(topologyId), node);
+                final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> 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<Node> getNodeIid(final String topologyId) {
-        final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
-        return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId))).child(Node.class);
-    }
-
     @Override
     public ListenableFuture<Void> onNodeDeleted(final NodeId nodeId) {
         final ArrayList<ListenableFuture<Void>> futures = new ArrayList<>();
@@ -498,7 +489,7 @@ public final class BaseTopologyManager
         Futures.addCallback(listenableFuture, new FutureCallback<Node>() {
             @Override
             public void onSuccess(Node result) {
-                final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = codecRegistry.toNormalizedNode(getNodeIid(topologyId), result);
+                final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> 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<Topology> result) {
                 if (result.isPresent() && result.get().getNode() != null) {
                     for (final Node node : result.get().getNode()) {
-                        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = codecRegistry.toNormalizedNode(getNodeIid(topologyId), node);
+                        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> 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
                     }
index 8d63e89cf417f416c346458c573053fe2e497bd7..33cde89cd9eeebbe1f1f13622a3db692e394284c 100644 (file)
@@ -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<Topology> 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<Node> createBindingPathForTopology(final NodeId id) {
-        return topologyListPath.child(Node.class, new NodeKey(id));
-    }
-
-    private InstanceIdentifier<Topology> createTopologyId(final String topologyId) {
-        final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
-        return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
-    }
 }
index 94cd8799af1122c56a26a038f65751f856fb28f7..a7fc4121357079922ca179a14de38387da8977d7 100644 (file)
@@ -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<Topology> createTopologyId(final String topologyId) {
-        final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
-        return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
-    }
 }
index 273d062309cbfa0161833f984c4b4c137f1051a6..d7c700d1a99a4946452e88a53370e963a0592110 100644 (file)
@@ -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<Topology> createTopologyId(final String topologyId) {
+    public static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
         final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
         return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
     }
+
+    public static InstanceIdentifier<Node> createTopologyNodeListPath(final NodeKey key, final String topologyId) {
+        return createTopologyListPath(topologyId).child(Node.class, new NodeKey(new NodeId(key.getNodeId().getValue())));
+    }
+
+    public static InstanceIdentifier<Node> createTopologyNodePath(final String topologyId) {
+        return createTopologyListPath(topologyId).child(Node.class);
+    }
 }
index 488b680ab53f048959fa82bed67e5967295cf04c..777adcf405f6fe8fd73ff2f1fd0f7d86e3364175 100644 (file)
@@ -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<Topology> createTopologyId(final String topologyId) {
-        final InstanceIdentifier<NetworkTopology> 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);
index 76656b467435baa459a930e67705235b1f6970bf..1d440cc125f69d45016585673e630be2ae9437da 100644 (file)
@@ -192,7 +192,6 @@ public class ClusteredNetconfTopology extends AbstractNetconfTopology implements
         return ((TopologyMountPointFacade) activeConnectors.get(node).getFacade()).registerConnectionStatusListener(listener);
     }
 
-    @Override
     public Collection<ProviderFunctionality> getProviderFunctionality() {
         return Collections.emptySet();
     }
index 0a147409038fa6e0597ef090eadab2d7466594c3..33b468ce2bc700edb0e70f0df076328677c66d8e 100644 (file)
@@ -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<Node> 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;
             }
         }
index 90caf84bd767126dbfb1a8973358c5899eabefa1..810679917c422e6bf986fa27f69143fb0e746838 100644 (file)
@@ -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<Node> path = createBindingPathForTopology(new NodeKey(id), topologyId);
+            final InstanceIdentifier<Node> 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<Node> path = createBindingPathForTopology(new NodeKey(id), topologyId);
+            final InstanceIdentifier<Node> 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<Node> path = createBindingPathForTopology(new NodeKey(id), topologyId);
+            final InstanceIdentifier<Node> 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<Node> createBindingPathForTopology(final NodeKey key, final String topologyId) {
-        final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.builder(NetworkTopology.class).build();
-        final KeyedInstanceIdentifier<Topology, TopologyKey> topology = networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
-        return topology
-                .child(Node.class, new NodeKey(new NodeId(key.getNodeId().getValue())));
-    }
 }
index c67673b05b99d4e583a0485ca3d26af3363c9e75..a093e1cc8d68a7c15b4bdcbe2f03586fdec955d5 100644 (file)
@@ -58,13 +58,17 @@ public class ProxyReadOnlyTransaction implements DOMDataReadOnlyTransaction{
             @Override
             public void onComplete(Throwable throwable, Optional<NormalizedNodeMessage> normalizedNodeMessage) throws Throwable {
                 if (throwable == null) {
-                    settableFuture.set(normalizedNodeMessage.transform(new Function<NormalizedNodeMessage, NormalizedNode<?, ?>>() {
-                        @Nullable
-                        @Override
-                        public NormalizedNode<?, ?> apply(NormalizedNodeMessage input) {
-                            return input.getNode();
-                        }
-                    }));
+                    if (normalizedNodeMessage.isPresent()) {
+                        settableFuture.set(normalizedNodeMessage.transform(new Function<NormalizedNodeMessage, NormalizedNode<?, ?>>() {
+                            @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 (file)
index 0000000..a29d95e
--- /dev/null
@@ -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<Void> 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<? extends DataContainer> 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<NetconfSessionPreferences> getFacade() {
+            return salFacade;
+        }
+
+        @Override
+        public void onSessionInitiated(BindingAwareBroker.ProviderContext session) {
+
+        }
+
+        @Override
+        protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker, long defaultRequestTimeoutMillis) {
+            return salFacade;
+        }
+
+        @Override
+        public TopologyMountPointFacade.ConnectionStatusListenerRegistration registerConnectionStatusListener(NodeId node, RemoteDeviceHandler<NetconfSessionPreferences> 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
index 1c84668ba86c5bae9b4cac1b4e66e9a8c68f13e4..caff132e58dce945f7448e28e72fc2793264e7a3 100644 (file)
@@ -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 (file)
index 0000000..417978d
--- /dev/null
@@ -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
index d7d7c94d51e16cd961315c7704cd6ee7b1963b76..afde0a0537c6d63569deb9f325a3d76249f17a5f 100644 (file)
@@ -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<Optional<NormalizedNode<?, ?>>, 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() {