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=31aa51a3b9caaa239d3fd9880b34f6b5072cf6c7;hb=1e1e99672bf3450a165b3ee0be5d38e856586da4;hp=ac02d453ab96019bfddd1a48b8e86ad97fe287b7;hpb=78c4689b8fd3b30bc776a4906e18f6ce7ebec986;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 ac02d453ab..31aa51a3b9 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 @@ -21,17 +21,21 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import java.util.Collection; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; 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.netconf.api.NetconfMessage; import org.opendaylight.netconf.sal.connect.api.MessageTransformer; +import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas; +import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemasResolver; import org.opendaylight.netconf.sal.connect.api.RemoteDevice; import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator; import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler; @@ -40,6 +44,8 @@ import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommun import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences; import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc; import org.opendaylight.netconf.sal.connect.netconf.schema.NetconfRemoteSchemaYangSourceProvider; +import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider; +import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseSchema; import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer; import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil; import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; @@ -48,14 +54,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev15 import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException; +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.SchemaSourceException; 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; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider; import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration; import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry; +import org.opendaylight.yangtools.yang.parser.util.ASTSchemaSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,7 +80,8 @@ public class NetconfDevice implements RemoteDevice QNAME_TO_SOURCE_ID_FUNCTION = new Function() { @Override public SourceIdentifier apply(final QName input) { - return new SourceIdentifier(input.getLocalName(), Optional.fromNullable(input.getFormattedRevision())); + return RevisionSourceIdentifier + .create(input.getLocalName(), Optional.fromNullable(input.getFormattedRevision())); } }; @@ -80,36 +92,31 @@ public class NetconfDevice implements RemoteDevice salFacade; private final ListeningExecutorService processingExecutor; protected final SchemaSourceRegistry schemaRegistry; - private final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver; + protected final SchemaRepository schemaRepository; + private final NetconfDeviceSchemasResolver stateSchemasResolver; private final NotificationHandler notificationHandler; protected final List> sourceRegistrations = Lists.newArrayList(); // Message transformer is constructed once the schemas are available private MessageTransformer messageTransformer; - public NetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler salFacade, - final ExecutorService globalProcessingExecutor) { - this(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, false); - } - /** * Create rpc implementation capable of handling RPC for monitoring and notifications even before the schemas of remote device are downloaded */ static NetconfDeviceRpc getRpcForInitialization(final NetconfDeviceCommunicator listener, final boolean notificationSupport) { - NetconfMessageTransformer.BaseSchema baseSchema = notificationSupport ? - NetconfMessageTransformer.BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS : - NetconfMessageTransformer.BaseSchema.BASE_NETCONF_CTX; + final BaseSchema baseSchema = notificationSupport ? + BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS : + BaseSchema.BASE_NETCONF_CTX; return new NetconfDeviceRpc(baseSchema.getSchemaContext(), listener, new NetconfMessageTransformer(baseSchema.getSchemaContext(), false, baseSchema)); } - - // FIXME reduce parameters - public NetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler salFacade, + protected NetconfDevice(final SchemaResourcesDTO schemaResourcesDTO, final RemoteDeviceId id, final RemoteDeviceHandler salFacade, final ExecutorService globalProcessingExecutor, final boolean reconnectOnSchemasChange) { this.id = id; this.reconnectOnSchemasChange = reconnectOnSchemasChange; this.schemaRegistry = schemaResourcesDTO.getSchemaRegistry(); + this.schemaRepository = schemaResourcesDTO.getSchemaRepository(); this.schemaContextFactory = schemaResourcesDTO.getSchemaContextFactory(); this.salFacade = salFacade; this.stateSchemasResolver = schemaResourcesDTO.getStateSchemasResolver(); @@ -138,7 +145,7 @@ public class NetconfDevice implements RemoteDevice resolvedSourceCallback = new FutureCallback() { @Override public void onSuccess(final DeviceSources result) { - addProvidedSourcesToSchemaRegistry(initRpc, result); + addProvidedSourcesToSchemaRegistry(result); setUpSchema(result); } @@ -197,10 +204,10 @@ public class NetconfDevice implements RemoteDevice yangProvider = deviceSources.getSourceProvider(); for (final SourceIdentifier sourceId : deviceSources.getProvidedSources()) { sourceRegistrations.add(schemaRegistry.registerSchemaSource(yangProvider, PotentialSchemaSource.create(sourceId, YangTextSchemaSource.class, PotentialSchemaSource.Costs.REMOTE_IO.getValue()))); @@ -263,24 +270,33 @@ public class NetconfDevice implements RemoteDevice requiredSources = Sets.newHashSet(remoteSessionCapabilities.getModuleBasedCaps()); @@ -335,7 +351,15 @@ public class NetconfDevice implements RemoteDevice sourceProvider; + if(availableSchemas instanceof LibraryModulesSchemas) { + sourceProvider = new YangLibrarySchemaYangSourceProvider(id, + ((LibraryModulesSchemas) availableSchemas).getAvailableModels()); + } else { + sourceProvider = new NetconfRemoteSchemaYangSourceProvider(id, deviceRpc); + } + + return new DeviceSources(requiredSources, providedSources, sourceProvider); } } @@ -345,10 +369,13 @@ public class NetconfDevice implements RemoteDevice requiredSources; private final Set providedSources; + private final SchemaSourceProvider sourceProvider; - public DeviceSources(final Set requiredSources, final Set providedSources) { + public DeviceSources(final Set requiredSources, final Set providedSources, + final SchemaSourceProvider sourceProvider) { this.requiredSources = requiredSources; this.providedSources = providedSources; + this.sourceProvider = sourceProvider; } public Set getRequiredSourcesQName() { @@ -367,6 +394,9 @@ public class NetconfDevice implements RemoteDevice getSourceProvider() { + return sourceProvider; + } } /** @@ -387,7 +417,28 @@ public class NetconfDevice implements RemoteDevice requiredSources = deviceSources.getRequiredSources(); + final Collection missingSources = filterMissingSources(requiredSources); + + capabilities.addUnresolvedCapabilities(getQNameFromSourceIdentifiers(missingSources), + UnavailableCapability.FailureReason.MissingSource); + + requiredSources.removeAll(missingSources); + setUpSchema(requiredSources); + } + + private Collection filterMissingSources(final Collection requiredSources) { + + return requiredSources.parallelStream().filter(sourceIdentifier -> { + boolean remove = false; + try { + schemaRepository.getSchemaSource(sourceIdentifier, ASTSchemaSource.class).checkedGet(); + } catch (SchemaSourceException e) { + remove = true; + } + return remove; + }).collect(Collectors.toList()); } /** @@ -405,14 +456,13 @@ public class NetconfDevice implements RemoteDevice handleMissingSchemaSourceException(Collection requiredSources, final MissingSchemaSourceException t) { + private Collection handleMissingSchemaSourceException(final Collection requiredSources, final MissingSchemaSourceException t) { // In case source missing, try without it final SourceIdentifier missingSource = t.getSourceId(); LOG.warn("{}: Unable to build schema context, missing source {}, will reattempt without it", id, missingSource); @@ -440,11 +490,23 @@ public class NetconfDevice implements RemoteDevice handleSchemaResolutionException(Collection requiredSources, final SchemaResolutionException resolutionException) { + private Collection handleSchemaResolutionException(final Collection requiredSources, final SchemaResolutionException resolutionException) { // In case resolution error, try only with resolved sources + // There are two options why schema resolution exception occurred : unsatisfied imports or flawed model + // FIXME Do we really have assurance that these two cases cannot happen at once? + if (resolutionException.getFailedSource() != null) { + // flawed model - exclude it + final SourceIdentifier failedSourceId = resolutionException.getFailedSource(); + LOG.warn("{}: Unable to build schema context, failed to resolve source {}, will reattempt without it", id, failedSourceId); + LOG.warn("{}: Unable to build schema context, failed to resolve source {}, will reattempt without it", id, resolutionException); + capabilities.addUnresolvedCapabilities(getQNameFromSourceIdentifiers(Collections.singleton(failedSourceId)), + UnavailableCapability.FailureReason.UnableToResolve); + return stripUnavailableSource(requiredSources, resolutionException.getFailedSource()); + } + // unsatisfied imports final Set unresolvedSources = resolutionException.getUnsatisfiedImports().keySet(); capabilities.addUnresolvedCapabilities(getQNameFromSourceIdentifiers(unresolvedSources), UnavailableCapability.FailureReason.UnableToResolve); LOG.warn("{}: Unable to build schema context, unsatisfied imports {}, will reattempt with resolved only", id, resolutionException.getUnsatisfiedImports()); @@ -456,7 +518,7 @@ public class NetconfDevice implements RemoteDevice stripMissingSource(final Collection requiredSources, final SourceIdentifier sIdToRemove) { + private Collection stripUnavailableSource(final Collection requiredSources, final SourceIdentifier sIdToRemove) { final LinkedList sourceIdentifiers = Lists.newLinkedList(requiredSources); final boolean removed = sourceIdentifiers.remove(sIdToRemove); Preconditions.checkState(removed, "{}: Trying to remove {} from {} failed", id, sIdToRemove, requiredSources);