Replace deprecated Futures.addCallback by the newer version
[netconf.git] / netconf / netconf-topology-singleton / src / main / java / org / opendaylight / netconf / topology / singleton / impl / NetconfTopologyManager.java
index 23a46aaa5a7a22e1bd710656ae28c2655b03d65a..48f063e92049400aa34995a201e3d27da2d67a51 100644 (file)
@@ -13,11 +13,14 @@ import akka.util.Timeout;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
 import io.netty.util.concurrent.EventExecutor;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import javax.annotation.Nonnull;
+import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.cluster.ActorSystemProvider;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
@@ -28,9 +31,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
@@ -40,6 +42,7 @@ import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySet
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup.NetconfTopologySetupBuilder;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.Config;
 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;
@@ -63,37 +66,44 @@ public class NetconfTopologyManager
     private final Map<InstanceIdentifier<Node>, ClusterSingletonServiceRegistration>
             clusterRegistrations = new HashMap<>();
 
-    private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
-
     private final DataBroker dataBroker;
     private final RpcProviderRegistry rpcProviderRegistry;
     private final ClusterSingletonServiceProvider clusterSingletonServiceProvider;
-    private final BindingAwareBroker bindingAwareBroker;
     private final ScheduledThreadPool keepaliveExecutor;
     private final ThreadPool processingExecutor;
-    private final Broker domBroker;
     private final ActorSystem actorSystem;
     private final EventExecutor eventExecutor;
     private final NetconfClientDispatcher clientDispatcher;
     private final String topologyId;
+    private final Duration writeTxIdleTimeout;
+    private final DOMMountPointService mountPointService;
+    private final AAAEncryptionService encryptionService;
+    private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
+    private String privateKeyPath;
+    private String privateKeyPassphrase;
 
     public NetconfTopologyManager(final DataBroker dataBroker, final RpcProviderRegistry rpcProviderRegistry,
                                   final ClusterSingletonServiceProvider clusterSingletonServiceProvider,
-                                  final BindingAwareBroker bindingAwareBroker,
                                   final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
-                                  final Broker domBroker, final ActorSystemProvider actorSystemProvider, final EventExecutor eventExecutor,
-                                  final NetconfClientDispatcher clientDispatcher, final String topologyId) {
+                                  final ActorSystemProvider actorSystemProvider,
+                                  final EventExecutor eventExecutor, final NetconfClientDispatcher clientDispatcher,
+                                  final String topologyId, final Config config,
+                                  final DOMMountPointService mountPointService,
+                                  final AAAEncryptionService encryptionService) {
+
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.rpcProviderRegistry = Preconditions.checkNotNull(rpcProviderRegistry);
         this.clusterSingletonServiceProvider = Preconditions.checkNotNull(clusterSingletonServiceProvider);
-        this.bindingAwareBroker = Preconditions.checkNotNull(bindingAwareBroker);
         this.keepaliveExecutor = Preconditions.checkNotNull(keepaliveExecutor);
         this.processingExecutor = Preconditions.checkNotNull(processingExecutor);
-        this.domBroker = Preconditions.checkNotNull(domBroker);
         this.actorSystem = Preconditions.checkNotNull(actorSystemProvider).getActorSystem();
         this.eventExecutor = Preconditions.checkNotNull(eventExecutor);
         this.clientDispatcher = Preconditions.checkNotNull(clientDispatcher);
         this.topologyId = Preconditions.checkNotNull(topologyId);
+        this.writeTxIdleTimeout = Duration.apply(config.getWriteTransactionIdleTimeout(), TimeUnit.SECONDS);
+        this.mountPointService = mountPointService;
+        this.encryptionService = Preconditions.checkNotNull(encryptionService);
+
     }
 
     // Blueprint init method
@@ -136,6 +146,11 @@ public class NetconfTopologyManager
         context.refresh(createSetup(instanceIdentifier, node));
     }
 
+    // ClusterSingletonServiceRegistration registerClusterSingletonService method throws a Runtime exception if there
+    // are problems with registration and client has to deal with it. Only thing we can do if this error occurs is to
+    // retry registration several times and log the error.
+    // TODO change to a specific documented Exception when changed in ClusterSingletonServiceProvider
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private void startNetconfDeviceContext(final InstanceIdentifier<Node> instanceIdentifier, final Node node) {
         final NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
         Preconditions.checkNotNull(netconfNode);
@@ -150,15 +165,31 @@ public class NetconfTopologyManager
 
         final NetconfTopologyContext newNetconfTopologyContext =
                 new NetconfTopologyContext(createSetup(instanceIdentifier, node), serviceGroupIdent,
-                        actorResponseWaitTime);
+                        actorResponseWaitTime, mountPointService);
 
-        final ClusterSingletonServiceRegistration clusterSingletonServiceRegistration  =
-                clusterSingletonServiceProvider.registerClusterSingletonService(newNetconfTopologyContext);
+        int tries = 3;
+        while (true) {
+            try {
+                final ClusterSingletonServiceRegistration clusterSingletonServiceRegistration =
+                        clusterSingletonServiceProvider.registerClusterSingletonService(newNetconfTopologyContext);
+                clusterRegistrations.put(instanceIdentifier, clusterSingletonServiceRegistration);
+                contexts.put(instanceIdentifier, newNetconfTopologyContext);
+                break;
+            } catch (final RuntimeException e) {
+                LOG.warn("Unable to register cluster singleton service {}, trying again", newNetconfTopologyContext, e);
+
+                if (--tries <= 0) {
+                    LOG.error("Unable to register cluster singleton service {} - done trying, closing topology context",
+                            newNetconfTopologyContext, e);
+                    close();
+                    break;
+                }
+            }
+        }
 
-        clusterRegistrations.put(instanceIdentifier, clusterSingletonServiceRegistration);
-        contexts.put(instanceIdentifier, newNetconfTopologyContext);
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     private void stopNetconfDeviceContext(final InstanceIdentifier<Node> instanceIdentifier) {
         if (contexts.containsKey(instanceIdentifier)) {
             try {
@@ -172,6 +203,7 @@ public class NetconfTopologyManager
         }
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
     @Override
     public void close() {
         if (dataChangeListenerRegistration != null) {
@@ -196,6 +228,20 @@ public class NetconfTopologyManager
         clusterRegistrations.clear();
     }
 
+    /**
+     * Sets the private key path from location specified in configuration file using blueprint.
+     */
+    public void setPrivateKeyPath(String privateKeyPath) {
+        this.privateKeyPath = privateKeyPath;
+    }
+
+    /**
+     * Sets the private key passphrase from location specified in configuration file using blueprint.
+     */
+    public void setPrivateKeyPassphrase(String privateKeyPassphrase) {
+        this.privateKeyPassphrase = privateKeyPassphrase;
+    }
+
     private ListenerRegistration<NetconfTopologyManager> registerDataTreeChangeListener(final String topologyId) {
         final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         initTopology(wtx, LogicalDatastoreType.CONFIGURATION, topologyId);
@@ -210,15 +256,16 @@ public class NetconfTopologyManager
             public void onFailure(@Nonnull final Throwable throwable) {
                 LOG.error("Unable to initialize netconf-topology, {}", throwable);
             }
-        });
+        }, MoreExecutors.directExecutor());
 
         LOG.debug("Registering datastore listener");
         return dataBroker.registerDataTreeChangeListener(
-                        new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
-                                NetconfTopologyUtils.createTopologyListPath(topologyId).child(Node.class)), this);
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                        NetconfTopologyUtils.createTopologyListPath(topologyId).child(Node.class)), this);
     }
 
-    private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType, final String topologyId) {
+    private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType,
+                              final String topologyId) {
         final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
         final InstanceIdentifier<NetworkTopology> networkTopologyId =
                 InstanceIdentifier.builder(NetworkTopology.class).build();
@@ -235,14 +282,17 @@ public class NetconfTopologyManager
                 .setInstanceIdentifier(instanceIdentifier)
                 .setRpcProviderRegistry(rpcProviderRegistry)
                 .setNode(node)
-                .setBindingAwareBroker(bindingAwareBroker)
                 .setActorSystem(actorSystem)
                 .setEventExecutor(eventExecutor)
-                .setDomBroker(domBroker)
                 .setKeepaliveExecutor(keepaliveExecutor)
                 .setProcessingExecutor(processingExecutor)
                 .setTopologyId(topologyId)
-                .setNetconfClientDispatcher(clientDispatcher);
+                .setNetconfClientDispatcher(clientDispatcher)
+                .setSchemaResourceDTO(NetconfTopologyUtils.setupSchemaCacheDTO(node))
+                .setIdleTimeout(writeTxIdleTimeout)
+                .setPrivateKeyPath(privateKeyPath)
+                .setPrivateKeyPassphrase(privateKeyPassphrase)
+                .setEncryptionService(encryptionService);
 
         return builder.build();
     }