import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.controller.sal.connect.netconf.NetconfStateSchemas;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.controller.sal.connect.netconf.sal.KeepaliveSalFacade;
import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceSalFacade;
-import org.opendaylight.controller.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.protocol.framework.ReconnectStrategy;
checkNotNull(getConnectionTimeoutMillis(), connectionTimeoutMillisJmxAttribute);
checkCondition(getConnectionTimeoutMillis() > 0, "must be > 0", connectionTimeoutMillisJmxAttribute);
+ checkNotNull(getConnectionTimeoutMillis(), defaultRequestTimeoutMillisJmxAttribute);
+ checkCondition(getConnectionTimeoutMillis() > 0, "must be > 0", defaultRequestTimeoutMillisJmxAttribute);
+
checkNotNull(getBetweenAttemptsTimeoutMillis(), betweenAttemptsTimeoutMillisJmxAttribute);
checkCondition(getBetweenAttemptsTimeoutMillis() > 0, "must be > 0", betweenAttemptsTimeoutMillisJmxAttribute);
}
userCapabilities = getUserCapabilities();
+
+ if(getKeepaliveExecutor() == null) {
+ logger.warn("Keepalive executor missing. Using default instance for now, the configuration needs to be updated");
+
+ // Instantiate the default executor, now we know its necessary
+ if(DEFAULT_KEEPALIVE_EXECUTOR == null) {
+ DEFAULT_KEEPALIVE_EXECUTOR = Executors.newScheduledThreadPool(2, new ThreadFactory() {
+ @Override
+ public Thread newThread(final Runnable r) {
+ final Thread thread = new Thread(r);
+ thread.setName("netconf-southound-keepalives-" + thread.getId());
+ thread.setDaemon(true);
+ return thread;
+ }
+ });
+ }
+ }
}
private boolean isHostAddressPresent(final Host address) {
address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
}
+ @Deprecated
+ private static ScheduledExecutorService DEFAULT_KEEPALIVE_EXECUTOR;
+
@Override
public java.lang.AutoCloseable createInstance() {
final RemoteDeviceId id = new RemoteDeviceId(getIdentifier(), getSocketAddress());
final Broker domBroker = getDomRegistryDependency();
final BindingAwareBroker bindingBroker = getBindingRegistryDependency();
- final RemoteDeviceHandler<NetconfSessionPreferences> salFacade
- = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, globalProcessingExecutor);
+ RemoteDeviceHandler<NetconfSessionPreferences> salFacade
+ = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, getDefaultRequestTimeoutMillis());
+
+ final Long keepaliveDelay = getKeepaliveDelay();
+ if(shouldSendKeepalive()) {
+ // Keepalive executor is optional for now and a default instance is supported
+ final ScheduledExecutorService executor = getKeepaliveExecutor() == null ?
+ DEFAULT_KEEPALIVE_EXECUTOR : getKeepaliveExecutorDependency().getExecutor();
+ salFacade = new KeepaliveSalFacade(id, salFacade, executor, keepaliveDelay);
+ }
final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO =
new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory, new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
final NetconfDevice device =
- new NetconfDevice(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, new NetconfMessageTransformer(), getReconnectOnChangedSchema());
+ new NetconfDevice(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, getReconnectOnChangedSchema());
final NetconfDeviceCommunicator listener = userCapabilities.isPresent() ?
new NetconfDeviceCommunicator(id, device, userCapabilities.get()) : new NetconfDeviceCommunicator(id, device);
+ if(shouldSendKeepalive()) {
+ ((KeepaliveSalFacade) salFacade).setListener(listener);
+ }
+
final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(listener);
final NetconfClientDispatcher dispatcher = getClientDispatcherDependency();
return new SalConnectorCloseable(listener, salFacade);
}
+ private boolean shouldSendKeepalive() {
+ return getKeepaliveDelay() > 0;
+ }
+
private Optional<NetconfSessionPreferences> getUserCapabilities() {
if(getYangModuleCapabilities() == null) {
return Optional.absent();
return Optional.of(parsedOverrideCapabilities);
}
- public void setBundleContext(final BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
public NetconfReconnectingClientConfiguration getClientConfig(final NetconfDeviceCommunicator listener) {
final InetSocketAddress socketAddress = getSocketAddress();
final long clientConnectionTimeoutMillis = getConnectionTimeoutMillis();
.withAddress(socketAddress)
.withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
.withReconnectStrategy(strategy)
- .withAuthHandler(new LoginPassword(getUsername(),getPassword()))
+ .withAuthHandler(new LoginPassword(getUsername(), getPassword()))
.withProtocol(getTcpOnly() ?
NetconfClientConfiguration.NetconfClientProtocol.TCP :
NetconfClientConfiguration.NetconfClientProtocol.SSH)