From 4b24bbfb5b03f6e54c9a5ea127f8d02683574991 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 26 Aug 2019 15:38:45 +0200 Subject: [PATCH 1/1] Separate out DeviceSources(Resolver) NetconfDevice is quite overloaded, making it unclear what methods participate on each stage of context assebly. This separates out DeviceSourcesResolver, so that the logic inside it is well contained outside of NetconfDevice. Change-Id: I3f05a73470f0c3b15fc6a111202bd5e0dacb92d3 Signed-off-by: Robert Varga --- .../sal/connect/netconf/DeviceSources.java | 59 ++++++++ .../netconf/DeviceSourcesResolver.java | 89 +++++++++++++ .../sal/connect/netconf/NetconfDevice.java | 126 +----------------- 3 files changed, 154 insertions(+), 120 deletions(-) create mode 100644 netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSources.java create mode 100644 netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSourcesResolver.java diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSources.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSources.java new file mode 100644 index 0000000000..132468f1b6 --- /dev/null +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSources.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.netconf.sal.connect.netconf; + +import static java.util.Objects.requireNonNull; + +import com.google.common.collect.Collections2; +import java.util.Collection; +import java.util.Set; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; +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.SchemaSourceProvider; + +/** + * Contains RequiredSources - sources from capabilities. + */ +final class DeviceSources { + private final Set requiredSources; + private final Set providedSources; + private final SchemaSourceProvider sourceProvider; + + DeviceSources(final Set requiredSources, final Set providedSources, + final SchemaSourceProvider sourceProvider) { + this.requiredSources = requireNonNull(requiredSources); + this.providedSources = requireNonNull(providedSources); + this.sourceProvider = requireNonNull(sourceProvider); + } + + Set getRequiredSourcesQName() { + return requiredSources; + } + + Set getProvidedSourcesQName() { + return providedSources; + } + + Collection getRequiredSources() { + return Collections2.transform(requiredSources, DeviceSources::toSourceId); + } + + Collection getProvidedSources() { + return Collections2.transform(providedSources, DeviceSources::toSourceId); + } + + SchemaSourceProvider getSourceProvider() { + return sourceProvider; + } + + private static SourceIdentifier toSourceId(final QName input) { + return RevisionSourceIdentifier.create(input.getLocalName(), input.getRevision()); + } +} \ No newline at end of file diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSourcesResolver.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSourcesResolver.java new file mode 100644 index 0000000000..771d5a997b --- /dev/null +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/DeviceSourcesResolver.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.netconf.sal.connect.netconf; + +import static java.util.Objects.requireNonNull; +import static org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.LOG; + +import com.google.common.collect.Sets; +import java.util.Set; +import java.util.concurrent.Callable; +import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas; +import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemasResolver; +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.util.RemoteDeviceId; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider; + +/** + * Schema building callable. + */ +final class DeviceSourcesResolver implements Callable { + private final NetconfSessionPreferences remoteSessionCapabilities; + private final NetconfDeviceSchemasResolver stateSchemasResolver; + private final NetconfDeviceRpc deviceRpc; + private final BaseSchema baseSchema; + private final RemoteDeviceId id; + + DeviceSourcesResolver(final RemoteDeviceId id, final BaseSchema baseSchema, final NetconfDeviceRpc deviceRpc, + final NetconfSessionPreferences remoteSessionCapabilities, + final NetconfDeviceSchemasResolver stateSchemasResolver) { + this.id = requireNonNull(id); + this.baseSchema = requireNonNull(baseSchema); + this.deviceRpc = requireNonNull(deviceRpc); + this.remoteSessionCapabilities = requireNonNull(remoteSessionCapabilities); + this.stateSchemasResolver = requireNonNull(stateSchemasResolver); + } + + @Override + public DeviceSources call() { + final NetconfDeviceSchemas availableSchemas = stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, + id, baseSchema.getSchemaContext()); + LOG.debug("{}: Schemas exposed by ietf-netconf-monitoring: {}", id, + availableSchemas.getAvailableYangSchemasQNames()); + + final Set requiredSources = Sets.newHashSet(remoteSessionCapabilities.getModuleBasedCaps()); + final Set providedSources = availableSchemas.getAvailableYangSchemasQNames(); + + final Set requiredSourcesNotProvided = Sets.difference(requiredSources, providedSources); + if (!requiredSourcesNotProvided.isEmpty()) { + LOG.warn("{}: Netconf device does not provide all yang models reported in hello message capabilities," + + " required but not provided: {}", id, requiredSourcesNotProvided); + LOG.warn("{}: Attempting to build schema context from required sources", id); + } + + // Here all the sources reported in netconf monitoring are merged with those reported in hello. + // It is necessary to perform this since submodules are not mentioned in hello but still required. + // This clashes with the option of a user to specify supported yang models manually in configuration + // for netconf-connector and as a result one is not able to fully override yang models of a device. + // It is only possible to add additional models. + final Set providedSourcesNotRequired = Sets.difference(providedSources, requiredSources); + if (!providedSourcesNotRequired.isEmpty()) { + LOG.warn("{}: Netconf device provides additional yang models not reported in " + + "hello message capabilities: {}", id, providedSourcesNotRequired); + LOG.warn("{}: Adding provided but not required sources as required to prevent failures", id); + LOG.debug("{}: Netconf device reported in hello: {}", id, requiredSources); + requiredSources.addAll(providedSourcesNotRequired); + } + + final SchemaSourceProvider sourceProvider; + if (availableSchemas instanceof LibraryModulesSchemas) { + sourceProvider = new YangLibrarySchemaYangSourceProvider(id, + ((LibraryModulesSchemas) availableSchemas).getAvailableModels()); + } else { + sourceProvider = new NetconfRemoteSchemaYangSourceProvider(id, deviceRpc); + } + + return new DeviceSources(requiredSources, providedSources, sourceProvider); + } +} \ No newline at end of file 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 a56cd8c057..88e5af62b1 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 @@ -19,6 +19,7 @@ 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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.netty.util.concurrent.EventExecutor; import java.util.ArrayList; import java.util.Collection; @@ -27,7 +28,6 @@ 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.TimeUnit; import java.util.stream.Collectors; @@ -37,7 +37,6 @@ 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; -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; @@ -46,8 +45,6 @@ import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabi import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator; 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; @@ -62,7 +59,6 @@ import org.opendaylight.yangtools.rfc8528.data.api.MountPointContext; 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; @@ -81,7 +77,9 @@ import org.slf4j.LoggerFactory; public class NetconfDevice implements RemoteDevice { - private static final Logger LOG = LoggerFactory.getLogger(NetconfDevice.class); + @SuppressFBWarnings(value = "SLF4J_LOGGER_SHOULD_BE_PRIVATE", + justification = "Needed for common logging of related classes") + static final Logger LOG = LoggerFactory.getLogger(NetconfDevice.class); protected final RemoteDeviceId id; protected final SchemaContextFactory schemaContextFactory; @@ -148,9 +146,8 @@ public class NetconfDevice final BaseSchema baseSchema = resolveBaseSchema(remoteSessionCapabilities.isNotificationsSupported()); final NetconfDeviceRpc initRpc = new NetconfDeviceRpc(baseSchema.getSchemaContext(), listener, new NetconfMessageTransformer(baseSchema.getMountPointContext(), false, baseSchema)); - final DeviceSourcesResolver task = new DeviceSourcesResolver(remoteSessionCapabilities, id, - stateSchemasResolver, initRpc, baseSchema.getSchemaContext()); - final ListenableFuture sourceResolverFuture = processingExecutor.submit(task); + final ListenableFuture sourceResolverFuture = processingExecutor.submit( + new DeviceSourcesResolver(id, baseSchema, initRpc, remoteSessionCapabilities, stateSchemasResolver)); if (shouldListenOnSchemaChange(remoteSessionCapabilities)) { registerToBaseNetconfStream(initRpc, listener); @@ -331,117 +328,6 @@ public class NetconfDevice } } - /** - * Schema building callable. - */ - private static class DeviceSourcesResolver implements Callable { - - private final NetconfDeviceRpc deviceRpc; - 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 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, final SchemaContext schemaCtx) { - this(rpcForMonitoring, remoteSessionCapabilities, id, stateSchemasResolver, schemaCtx); - } - - @Override - public DeviceSources call() { - final NetconfDeviceSchemas availableSchemas = - stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id, schemaContext); - LOG.debug("{}: Schemas exposed by ietf-netconf-monitoring: {}", id, - availableSchemas.getAvailableYangSchemasQNames()); - - final Set requiredSources = Sets.newHashSet(remoteSessionCapabilities.getModuleBasedCaps()); - final Set providedSources = availableSchemas.getAvailableYangSchemasQNames(); - - final Set requiredSourcesNotProvided = Sets.difference(requiredSources, providedSources); - if (!requiredSourcesNotProvided.isEmpty()) { - LOG.warn("{}: Netconf device does not provide all yang models reported in hello message capabilities," - + " required but not provided: {}", id, requiredSourcesNotProvided); - LOG.warn("{}: Attempting to build schema context from required sources", id); - } - - // Here all the sources reported in netconf monitoring are merged with those reported in hello. - // It is necessary to perform this since submodules are not mentioned in hello but still required. - // This clashes with the option of a user to specify supported yang models manually in configuration - // for netconf-connector and as a result one is not able to fully override yang models of a device. - // It is only possible to add additional models. - final Set providedSourcesNotRequired = Sets.difference(providedSources, requiredSources); - if (!providedSourcesNotRequired.isEmpty()) { - LOG.warn("{}: Netconf device provides additional yang models not reported in " - + "hello message capabilities: {}", id, providedSourcesNotRequired); - LOG.warn("{}: Adding provided but not required sources as required to prevent failures", id); - LOG.debug("{}: Netconf device reported in hello: {}", id, requiredSources); - requiredSources.addAll(providedSourcesNotRequired); - } - - final SchemaSourceProvider sourceProvider; - if (availableSchemas instanceof LibraryModulesSchemas) { - sourceProvider = new YangLibrarySchemaYangSourceProvider(id, - ((LibraryModulesSchemas) availableSchemas).getAvailableModels()); - } else { - sourceProvider = new NetconfRemoteSchemaYangSourceProvider(id, deviceRpc); - } - - return new DeviceSources(requiredSources, providedSources, sourceProvider); - } - } - - /** - * Contains RequiredSources - sources from capabilities. - */ - private static final class DeviceSources { - private final Set requiredSources; - private final Set providedSources; - private final SchemaSourceProvider sourceProvider; - - DeviceSources(final Set requiredSources, final Set providedSources, - final SchemaSourceProvider sourceProvider) { - this.requiredSources = requiredSources; - this.providedSources = providedSources; - this.sourceProvider = sourceProvider; - } - - public Set getRequiredSourcesQName() { - return requiredSources; - } - - public Set getProvidedSourcesQName() { - return providedSources; - } - - public Collection getRequiredSources() { - return Collections2.transform(requiredSources, DeviceSources::toSourceId); - } - - public Collection getProvidedSources() { - return Collections2.transform(providedSources, DeviceSources::toSourceId); - } - - public SchemaSourceProvider getSourceProvider() { - return sourceProvider; - } - - private static SourceIdentifier toSourceId(final QName input) { - return RevisionSourceIdentifier.create(input.getLocalName(), input.getRevision()); - } - } - /** * Schema builder that tries to build schema context from provided sources or biggest subset of it. */ -- 2.36.6