X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Fsal-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Fconnect%2Fnetconf%2FNetconfDevice.java;h=e50ba00fa95073d0f400dbb2ca4185df2fae7aa9;hb=b8f5ebd2f817de1d613d84cf41f3516728767eba;hp=633db8581b43c05d9d121d9bb3f74c69f234cf83;hpb=455dd29862158b2c1bfab4235860e8acec638065;p=netconf.git diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java index 633db8581b..e50ba00fa9 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/NetconfDevice.java @@ -7,34 +7,36 @@ */ package org.opendaylight.netconf.sal.connect.netconf; -import com.google.common.base.Optional; +import static java.util.Objects.requireNonNull; + import com.google.common.base.Preconditions; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FluentFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; +import io.netty.util.concurrent.EventExecutor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.concurrent.GuardedBy; -import org.opendaylight.controller.md.sal.dom.api.DOMNotification; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcException; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; +import org.opendaylight.mdsal.dom.api.DOMNotification; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +import org.opendaylight.mdsal.dom.api.DOMRpcService; import org.opendaylight.netconf.api.NetconfMessage; import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory; import org.opendaylight.netconf.sal.connect.api.MessageTransformer; @@ -54,6 +56,8 @@ import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessag import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil; import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.optional.rev190614.NetconfNodeAugmentedOptional; +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.connection.status.available.capabilities.AvailableCapabilityBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability; import org.opendaylight.yangtools.yang.common.QName; @@ -63,7 +67,6 @@ import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; 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.SchemaResolutionException; -import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation; import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource; @@ -86,8 +89,7 @@ public class NetconfDevice protected final SchemaSourceRegistry schemaRegistry; protected final SchemaRepository schemaRepository; - protected final List> sourceRegistrations = - new ArrayList<>(); + protected final List> sourceRegistrations = new ArrayList<>(); private final RemoteDeviceHandler salFacade; private final ListeningExecutorService processingExecutor; @@ -95,6 +97,9 @@ public class NetconfDevice private final NetconfDeviceSchemasResolver stateSchemasResolver; private final NotificationHandler notificationHandler; private final boolean reconnectOnSchemasChange; + private final NetconfNode node; + private final EventExecutor eventExecutor; + private final NetconfNodeAugmentedOptional nodeOptional; @GuardedBy("this") private boolean connected = false; @@ -108,33 +113,41 @@ public class NetconfDevice */ static NetconfDeviceRpc getRpcForInitialization(final NetconfDeviceCommunicator listener, final boolean notificationSupport) { - final BaseSchema baseSchema = notificationSupport - ? BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS - : BaseSchema.BASE_NETCONF_CTX; + final BaseSchema baseSchema = resolveBaseSchema(notificationSupport); return new NetconfDeviceRpc(baseSchema.getSchemaContext(), listener, new NetconfMessageTransformer(baseSchema.getSchemaContext(), false, baseSchema)); } + private static BaseSchema resolveBaseSchema(final boolean notificationSupport) { + return notificationSupport ? BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS : BaseSchema.BASE_NETCONF_CTX; + } + public NetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler salFacade, - final ExecutorService globalProcessingExecutor, final boolean reconnectOnSchemasChange) { - this(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, reconnectOnSchemasChange, null); + final ListeningExecutorService globalProcessingExecutor, + final boolean reconnectOnSchemasChange) { + this(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, reconnectOnSchemasChange, null, null, null, + null); } public NetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler salFacade, - final ExecutorService globalProcessingExecutor, final boolean reconnectOnSchemasChange, - final DeviceActionFactory deviceActionFactory) { + final ListeningExecutorService globalProcessingExecutor, final boolean reconnectOnSchemasChange, + final DeviceActionFactory deviceActionFactory, final NetconfNode node, final EventExecutor eventExecutor, + final NetconfNodeAugmentedOptional nodeOptional) { this.id = id; this.reconnectOnSchemasChange = reconnectOnSchemasChange; this.deviceActionFactory = deviceActionFactory; + this.node = node; + this.eventExecutor = eventExecutor; + this.nodeOptional = nodeOptional; this.schemaRegistry = schemaResourcesDTO.getSchemaRegistry(); this.schemaRepository = schemaResourcesDTO.getSchemaRepository(); this.schemaContextFactory = schemaResourcesDTO.getSchemaContextFactory(); this.salFacade = salFacade; this.stateSchemasResolver = schemaResourcesDTO.getStateSchemasResolver(); - this.processingExecutor = MoreExecutors.listeningDecorator(globalProcessingExecutor); + this.processingExecutor = requireNonNull(globalProcessingExecutor); this.notificationHandler = new NotificationHandler(salFacade, id); } @@ -152,7 +165,8 @@ public class NetconfDevice final NetconfDeviceRpc initRpc = getRpcForInitialization(listener, remoteSessionCapabilities.isNotificationsSupported()); final DeviceSourcesResolver task = - new DeviceSourcesResolver(remoteSessionCapabilities, id, stateSchemasResolver, initRpc); + new DeviceSourcesResolver(remoteSessionCapabilities, id, stateSchemasResolver, initRpc, + resolveBaseSchema(remoteSessionCapabilities.isNotificationsSupported()).getSchemaContext()); final ListenableFuture sourceResolverFuture = processingExecutor.submit(task); if (shouldListenOnSchemaChange(remoteSessionCapabilities)) { @@ -185,7 +199,7 @@ public class NetconfDevice // TODO check whether the model describing create subscription is present in schema // Perhaps add a default schema context to support create-subscription if the model was not provided // (same as what we do for base netconf operations in transformer) - final CheckedFuture rpcResultListenableFuture = deviceRpc.invokeRpc( + final FluentFuture rpcResultListenableFuture = deviceRpc.invokeRpc( NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.CREATE_SUBSCRIPTION_RPC_QNAME), NetconfMessageTransformUtil.CREATE_SUBSCRIPTION_RPC_CONTENT); @@ -197,7 +211,7 @@ public class NetconfDevice // Only disconnect is enough, // the reconnecting nature of the connector will take care of reconnecting listener.disconnect(); - return Optional.absent(); + return Optional.empty(); } return Optional.of(notification); } @@ -288,10 +302,8 @@ public class NetconfDevice notificationHandler.onRemoteSchemaDown(); salFacade.onDeviceDisconnected(); - for (final SchemaSourceRegistration sourceRegistration - : sourceRegistrations) { - sourceRegistration.close(); - } + sourceRegistrations.forEach(SchemaSourceRegistration::close); + sourceRegistrations.clear(); resetMessageTransformer(); } @@ -351,26 +363,29 @@ public class NetconfDevice private final NetconfSessionPreferences remoteSessionCapabilities; private final RemoteDeviceId id; private final NetconfDeviceSchemasResolver stateSchemasResolver; + private final SchemaContext schemaContext; DeviceSourcesResolver(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, - final RemoteDeviceId id, final NetconfDeviceSchemasResolver stateSchemasResolver) { + final RemoteDeviceId id, final NetconfDeviceSchemasResolver stateSchemasResolver, + final SchemaContext schemaContext) { this.deviceRpc = deviceRpc; this.remoteSessionCapabilities = remoteSessionCapabilities; this.id = id; this.stateSchemasResolver = stateSchemasResolver; + this.schemaContext = schemaContext; } DeviceSourcesResolver(final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id, final NetconfDeviceSchemasResolver stateSchemasResolver, - final NetconfDeviceRpc rpcForMonitoring) { - this(rpcForMonitoring, remoteSessionCapabilities, id, stateSchemasResolver); + final NetconfDeviceRpc rpcForMonitoring, final SchemaContext schemaCtx) { + this(rpcForMonitoring, remoteSessionCapabilities, id, stateSchemasResolver, schemaCtx); } @Override public DeviceSources call() { final NetconfDeviceSchemas availableSchemas = - stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id); + stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id, schemaContext); LOG.debug("{}: Schemas exposed by ietf-netconf-monitoring: {}", id, availableSchemas.getAvailableYangSchemasQNames()); @@ -545,10 +560,21 @@ public class NetconfDevice return; } } - // No more sources, fail - final IllegalStateException cause = new IllegalStateException(id + ": No more sources for schema context"); - handleSalInitializationFailure(cause, listener); - salFacade.onDeviceFailed(cause); + // No more sources, fail or try to reconnect + if (nodeOptional != null && nodeOptional.getIgnoreMissingSchemaSources().isAllowed()) { + eventExecutor.schedule(() -> { + LOG.warn("Reconnection is allowed! This can lead to unexpected errors at runtime."); + LOG.warn("{} : No more sources for schema context.", id); + LOG.info("{} : Try to remount device.", id); + onRemoteSessionDown(); + salFacade.onDeviceReconnected(remoteSessionCapabilities, node); + }, nodeOptional.getIgnoreMissingSchemaSources().getReconnectTime(), TimeUnit.MILLISECONDS); + } else { + final IllegalStateException cause = + new IllegalStateException(id + ": No more sources for schema context"); + handleSalInitializationFailure(cause, listener); + salFacade.onDeviceFailed(cause); + } } private Collection handleMissingSchemaSourceException(