Introduce NetconfTimer
[netconf.git] / apps / netconf-topology-impl / src / main / java / org / opendaylight / netconf / topology / impl / NetconfTopologyImpl.java
index d8530d2c1554abbfd621d271f37296c45132548f..11dc3417ac59904f57ea21cd44813a72d1f48a0b 100644 (file)
@@ -7,44 +7,36 @@
  */
 package org.opendaylight.netconf.topology.impl;
 
-import com.google.common.annotations.VisibleForTesting;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import io.netty.util.concurrent.EventExecutor;
 import java.util.Collection;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
-import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
-import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.mdsal.binding.api.DataBroker;
-import org.opendaylight.mdsal.binding.api.DataObjectModification;
 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
 import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.netconf.client.NetconfClientFactory;
+import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
 import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
-import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
+import org.opendaylight.netconf.common.NetconfTimer;
 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
-import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
+import org.opendaylight.netconf.topology.spi.NetconfClientConfigurationBuilderFactory;
 import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
 import org.opendaylight.netconf.topology.spi.NetconfTopologyRPCProvider;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeTopologyService;
+import org.opendaylight.netconf.topology.spi.NetconfTopologySchemaAssembler;
 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.Registration;
-import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -60,70 +52,66 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology
     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
 
     private Registration dtclReg;
-    private Registration rpcReg;
+    private NetconfTopologyRPCProvider rpcProvider;
 
     @Inject
     @Activate
     public NetconfTopologyImpl(
-            @Reference(target = "(type=netconf-client-dispatcher)") final NetconfClientDispatcher clientDispatcher,
-            @Reference(target = "(type=global-event-executor)") final EventExecutor eventExecutor,
-            @Reference(target = "(type=global-netconf-ssh-scheduled-executor)")
-            final ScheduledThreadPool keepaliveExecutor,
-            @Reference(target = "(type=global-netconf-processing-executor)") final ThreadPool processingExecutor,
+            @Reference(target = "(type=netconf-client-factory)") final NetconfClientFactory clientFactory,
+            @Reference final NetconfTimer timer,
+            @Reference final NetconfTopologySchemaAssembler schemaAssembler,
             @Reference final SchemaResourceManager schemaRepositoryProvider, @Reference final DataBroker dataBroker,
             @Reference final DOMMountPointService mountPointService,
             @Reference final AAAEncryptionService encryptionService,
+            @Reference final NetconfClientConfigurationBuilderFactory builderFactory,
             @Reference final RpcProviderService rpcProviderService, @Reference final BaseNetconfSchemas baseSchemas,
             @Reference final DeviceActionFactory deviceActionFactory) {
-        this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, clientDispatcher, eventExecutor, keepaliveExecutor,
-            processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService,
-            rpcProviderService, baseSchemas, deviceActionFactory);
+        this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, clientFactory, timer, schemaAssembler, schemaRepositoryProvider,
+            dataBroker, mountPointService, encryptionService, builderFactory, rpcProviderService, baseSchemas,
+            deviceActionFactory);
     }
 
-    public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
-            final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
-            final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
-            final DataBroker dataBroker, final DOMMountPointService mountPointService,
-            final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
+    public NetconfTopologyImpl(final String topologyId, final NetconfClientFactory clientclientFactory,
+            final NetconfTimer timer, final NetconfTopologySchemaAssembler schemaAssembler,
+            final SchemaResourceManager schemaRepositoryProvider, final DataBroker dataBroker,
+            final DOMMountPointService mountPointService, final AAAEncryptionService encryptionService,
+            final NetconfClientConfigurationBuilderFactory builderFactory, final RpcProviderService rpcProviderService,
             final BaseNetconfSchemas baseSchemas) {
-        this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
-                schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
-                baseSchemas, null);
+        this(topologyId, clientclientFactory, timer, schemaAssembler, schemaRepositoryProvider, dataBroker,
+            mountPointService, encryptionService, builderFactory, rpcProviderService, baseSchemas, null);
     }
 
     @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR",
         justification = "DTCL registration of 'this'")
-    public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
-            final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
-            final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
-            final DataBroker dataBroker, final DOMMountPointService mountPointService,
-            final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
+    public NetconfTopologyImpl(final String topologyId, final NetconfClientFactory clientFactory,
+            final NetconfTimer timer, final NetconfTopologySchemaAssembler schemaAssembler,
+            final SchemaResourceManager schemaRepositoryProvider, final DataBroker dataBroker,
+            final DOMMountPointService mountPointService, final AAAEncryptionService encryptionService,
+            final NetconfClientConfigurationBuilderFactory builderFactory, final RpcProviderService rpcProviderService,
             final BaseNetconfSchemas baseSchemas, final DeviceActionFactory deviceActionFactory) {
-        super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
-                schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
-                baseSchemas);
+        super(topologyId, clientFactory, timer, schemaAssembler, schemaRepositoryProvider, dataBroker,
+            mountPointService, builderFactory, deviceActionFactory, baseSchemas);
 
         LOG.debug("Registering datastore listener");
         dtclReg = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
-            LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
-        rpcReg = rpcProviderService.registerRpcImplementation(NetconfNodeTopologyService.class,
-            new NetconfTopologyRPCProvider(dataBroker, encryptionService, topologyId));
+            LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
+                .child(Node.class)
+                .build()), this);
+        rpcProvider = new NetconfTopologyRPCProvider(rpcProviderService, dataBroker, encryptionService, topologyId);
     }
 
     @PreDestroy
     @Deactivate
     @Override
     public void close() {
-        if (rpcReg != null) {
-            rpcReg.close();
-            rpcReg = null;
+        if (rpcProvider != null) {
+            rpcProvider.close();
+            rpcProvider = null;
         }
 
         // close all existing connectors, delete whole topology in datastore?
-        for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
-            connectorDTO.close();
-        }
-        activeConnectors.clear();
+        deleteAllNodes();
 
         if (dtclReg != null) {
             dtclReg.close();
@@ -132,58 +120,26 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology
     }
 
     @Override
-    public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
-        for (final DataTreeModification<Node> change : collection) {
-            final DataObjectModification<Node> rootNode = change.getRootNode();
-            final NodeId nodeId;
-            switch (rootNode.getModificationType()) {
-                case SUBTREE_MODIFIED:
-                    nodeId = getNodeId(rootNode.getIdentifier());
-                    LOG.debug("Config for node {} updated", nodeId);
-                    disconnectNode(nodeId);
-                    connectNode(nodeId, rootNode.getDataAfter());
-                    break;
-                case WRITE:
-                    nodeId = getNodeId(rootNode.getIdentifier());
-                    LOG.debug("Config for node {} created", nodeId);
-                    if (activeConnectors.containsKey(nodeId)) {
-                        LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
-                        disconnectNode(nodeId);
-                    }
-                    connectNode(nodeId, rootNode.getDataAfter());
-                    break;
-                case DELETE:
-                    nodeId = getNodeId(rootNode.getIdentifier());
+    public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
+        for (var change : changes) {
+            final var rootNode = change.getRootNode();
+            final var modType = rootNode.getModificationType();
+            switch (modType) {
+                case SUBTREE_MODIFIED -> ensureNode("updated", rootNode.getDataAfter());
+                case WRITE -> ensureNode("created", rootNode.getDataAfter());
+                case DELETE -> {
+                    final var nodeId = InstanceIdentifier.keyOf(change.getRootPath().getRootIdentifier()).getNodeId();
                     LOG.debug("Config for node {} deleted", nodeId);
-                    disconnectNode(nodeId);
-                    break;
-                default:
-                    LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
-            }
-        }
-    }
-
-    /**
-     * Determines the Netconf Node Node ID, given the node's instance
-     * identifier.
-     *
-     * @param pathArgument Node's path argument
-     * @return     NodeId for the node
-     */
-    @VisibleForTesting
-    static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
-        if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
-            final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) pathArgument).getKey();
-            if (key instanceof NodeKey) {
-                return ((NodeKey) key).getNodeId();
+                    deleteNode(nodeId);
+                }
+                default -> LOG.debug("Unsupported modification type: {}.", modType);
             }
         }
-        throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
     }
 
-    @VisibleForTesting
-    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)));
+    private void ensureNode(final String operation, final Node node) {
+        final var nodeId = node.getNodeId();
+        LOG.debug("Config for node {} {}", nodeId, operation);
+        ensureNode(node);
     }
 }