X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=opendaylight%2Fmd-sal%2Fsal-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fconfig%2Fyang%2Fmd%2Fsal%2Fconnector%2Fnetconf%2FNetconfConnectorModule.java;h=12e4855fbde9d8de73c049c2a10f2124c76f33bb;hb=b7f6cdbd53ca0c74998e73cfd4d86bcf2d5785f0;hp=97e294016d908936cbe2fe9e28c94d94027cc7d7;hpb=992a433ff8fd0ce7335bf5ea9e59a75602a95a19;p=controller.git diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java index 97e294016d..12e4855fbd 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java @@ -9,12 +9,16 @@ package org.opendaylight.controller.config.yang.md.sal.connector.netconf; import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkCondition; import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkNotNull; + import com.google.common.base.Optional; import io.netty.util.concurrent.EventExecutor; import java.math.BigDecimal; 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; @@ -26,9 +30,9 @@ import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler; import org.opendaylight.controller.sal.connect.netconf.NetconfDevice; 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.NetconfSessionCapabilities; +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; @@ -50,7 +54,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co private static final Logger logger = LoggerFactory.getLogger(NetconfConnectorModule.class); private BundleContext bundleContext; - private Optional userCapabilities; + private Optional userCapabilities; private SchemaSourceRegistry schemaRegistry; private SchemaContextFactory schemaContextFactory; @@ -73,6 +77,9 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co 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); @@ -88,6 +95,22 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co 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) { @@ -95,36 +118,55 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co 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()); + final RemoteDeviceId id = new RemoteDeviceId(getIdentifier(), getSocketAddress()); final ExecutorService globalProcessingExecutor = getProcessingExecutorDependency().getExecutor(); final Broker domBroker = getDomRegistryDependency(); final BindingAwareBroker bindingBroker = getBindingRegistryDependency(); - final RemoteDeviceHandler salFacade - = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, globalProcessingExecutor); + RemoteDeviceHandler salFacade + = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, 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()); + new NetconfDevice(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, getReconnectOnChangedSchema()); final NetconfDeviceCommunicator listener = userCapabilities.isPresent() ? new NetconfDeviceCommunicator(id, device, userCapabilities.get()) : new NetconfDeviceCommunicator(id, device); - final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(listener); + if(shouldSendKeepalive()) { + ((KeepaliveSalFacade) salFacade).setListener(listener); + } + final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(listener); final NetconfClientDispatcher dispatcher = getClientDispatcherDependency(); + listener.initializeRemoteConnection(dispatcher, clientConfig); - return new MyAutoCloseable(listener, salFacade); + return new SalConnectorCloseable(listener, salFacade); } - private Optional getUserCapabilities() { + private boolean shouldSendKeepalive() { + return getKeepaliveDelay() > 0; + } + + private Optional getUserCapabilities() { if(getYangModuleCapabilities() == null) { return Optional.absent(); } @@ -134,7 +176,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co return Optional.absent(); } - final NetconfSessionCapabilities parsedOverrideCapabilities = NetconfSessionCapabilities.fromStrings(capabilities); + final NetconfSessionPreferences parsedOverrideCapabilities = NetconfSessionPreferences.fromStrings(capabilities); JmxAttributeValidationException.checkCondition( parsedOverrideCapabilities.getNonModuleCaps().isEmpty(), "Capabilities to override can only contain module based capabilities, non-module capabilities will be retrieved from the device," + @@ -152,7 +194,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co final InetSocketAddress socketAddress = getSocketAddress(); final long clientConnectionTimeoutMillis = getConnectionTimeoutMillis(); - final ReconnectStrategyFactory sf = new MyReconnectStrategyFactory( + final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory( getEventExecutorDependency(), getMaxConnectionAttempts(), getBetweenAttemptsTimeoutMillis(), getSleepFactor()); final ReconnectStrategy strategy = sf.createReconnectStrategy(); @@ -160,21 +202,21 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co .withAddress(socketAddress) .withConnectionTimeoutMillis(clientConnectionTimeoutMillis) .withReconnectStrategy(strategy) - .withSessionListener(listener) - .withAuthHandler(new LoginPassword(getUsername(),getPassword())) + .withAuthHandler(new LoginPassword(getUsername(), getPassword())) .withProtocol(getTcpOnly() ? NetconfClientConfiguration.NetconfClientProtocol.TCP : NetconfClientConfiguration.NetconfClientProtocol.SSH) .withConnectStrategyFactory(sf) + .withSessionListener(listener) .build(); } - private static final class MyAutoCloseable implements AutoCloseable { - private final RemoteDeviceHandler salFacade; + private static final class SalConnectorCloseable implements AutoCloseable { + private final RemoteDeviceHandler salFacade; private final NetconfDeviceCommunicator listener; - public MyAutoCloseable(final NetconfDeviceCommunicator listener, - final RemoteDeviceHandler salFacade) { + public SalConnectorCloseable(final NetconfDeviceCommunicator listener, + final RemoteDeviceHandler salFacade) { this.listener = listener; this.salFacade = salFacade; } @@ -186,13 +228,13 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co } } - private static final class MyReconnectStrategyFactory implements ReconnectStrategyFactory { + private static final class TimedReconnectStrategyFactory implements ReconnectStrategyFactory { private final Long connectionAttempts; private final EventExecutor executor; private final double sleepFactor; private final int minSleep; - MyReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts, final int minSleep, final BigDecimal sleepFactor) { + TimedReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts, final int minSleep, final BigDecimal sleepFactor) { if (maxConnectionAttempts != null && maxConnectionAttempts > 0) { connectionAttempts = maxConnectionAttempts; } else {