From d8d9ad046e29d0c1d97e4e499b407fb64af8e18d Mon Sep 17 00:00:00 2001 From: Ryan Goulding Date: Mon, 11 Jan 2016 15:02:18 -0500 Subject: [PATCH] Bug 4577 Allow specification of a distinct schema cache directory per netconf device A leaf is added to odl-sal-netconf-connector-cfg.yang to allow specification of a schema cache directory relative to the "cache" directory. The leaf defaults to "schema", so the default directory for loaded yang files is "cache/schema". It is useful to specify a distinct cache directory per netconf mount to avoid potential model conflicts caused by revisionless import statements. Change-Id: Id930932aa4ff17a7338ddf96e87557b3949b4204 Signed-off-by: Ryan Goulding (cherry picked from commit cca187da2cfeeab02a1679657777b7c3d6f65f2c) --- .../topology/AbstractNetconfTopology.java | 169 ++++++++++++++--- .../impl/ClusteredNetconfTopology.java | 6 +- .../netconf/NetconfConnectorModule.java | 173 ++++++++++++++---- .../NetconfConnectorModuleFactory.java | 2 + .../src/main/yang/netconf-node-topology.yang | 12 ++ .../yang/odl-sal-netconf-connector-cfg.yang | 7 + 6 files changed, 306 insertions(+), 63 deletions(-) diff --git a/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java b/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java index b25a7bd6ae..de0dc69215 100644 --- a/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java +++ b/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/AbstractNetconfTopology.java @@ -9,6 +9,7 @@ package org.opendaylight.netconf.topology; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -19,8 +20,7 @@ import java.net.InetSocketAddress; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; +import java.util.Map; import org.opendaylight.controller.config.threadpool.ScheduledThreadPool; import org.opendaylight.controller.config.threadpool.ThreadPool; import org.opendaylight.controller.md.sal.binding.api.DataBroker; @@ -75,7 +75,7 @@ import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public abstract class AbstractNetconfTopology implements NetconfTopology, BindingAwareProvider, Provider{ +public abstract class AbstractNetconfTopology implements NetconfTopology, BindingAwareProvider, Provider { private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class); @@ -87,9 +87,67 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L; private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5); - private static FilesystemSchemaSourceCache CACHE = null; - //keep track of already initialized repositories to avoid adding redundant listeners - private static final Set INITIALIZED_SCHEMA_REPOSITORIES = new HashSet<>(); + // constants related to Schema Cache(s) + /** + * Filesystem based caches are stored relative to the cache directory. + */ + private static final String CACHE_DIRECTORY = "cache"; + + /** + * The default cache directory relative to CACHE_DIRECTORY + */ + private static final String DEFAULT_CACHE_DIRECTORY = "schema"; + + /** + * The qualified schema cache directory cache/schema + */ + private static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY = CACHE_DIRECTORY + File.separator+ DEFAULT_CACHE_DIRECTORY; + + /** + * The name for the default schema repository + */ + private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector"; + + /** + * The default schema repository in the case that one is not specified. + */ + private static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY = + new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME); + + /** + * The default FilesystemSchemaSourceCache, which stores cached files in cache/schema. + */ + private static final FilesystemSchemaSourceCache DEFAULT_CACHE = + new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class, + new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY)); + + /** + * The default factory for creating SchemaContext instances. + */ + private static final SchemaContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY = + DEFAULT_SCHEMA_REPOSITORY.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + + /** + * Keeps track of initialized Schema resources. A Map is maintained in which the key represents the name + * of the schema cache directory, and the value is a corresponding SchemaResourcesDTO. The + * SchemaResourcesDTO is essentially a container that allows for the extraction of the + * SchemaRegistry and SchemaContextFactory which should be used for a particular + * Netconf mount. Access to schemaResourcesDTOs should be surrounded by appropriate + * synchronization locks. + */ + private static volatile Map schemaResourcesDTOs = new HashMap<>(); + + // Initializes default constant instances for the case when the default schema repository + // directory cache/schema is used. + static { + schemaResourcesDTOs.put(DEFAULT_CACHE_DIRECTORY, + new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, + DEFAULT_SCHEMA_CONTEXT_FACTORY, + new NetconfStateSchemas.NetconfStateSchemasResolverImpl())); + DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE); + DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener( + TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY)); + } protected final String topologyId; private final NetconfClientDispatcher clientDispatcher; @@ -100,8 +158,8 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin protected final ThreadPool processingExecutor; protected final SharedSchemaRepository sharedSchemaRepository; - protected SchemaSourceRegistry schemaRegistry = null; - protected SchemaContextFactory schemaContextFactory = null; + protected SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY; + protected SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY; protected DOMMountPointService mountPointService = null; protected DataBroker dataBroker = null; @@ -119,8 +177,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin this.keepaliveExecutor = keepaliveExecutor; this.processingExecutor = processingExecutor; this.sharedSchemaRepository = schemaRepositoryProvider.getSharedSchemaRepository(); - - initFilesystemSchemaSourceCache(sharedSchemaRepository); } protected void registerToSal(BindingAwareProvider baProvider, Provider provider) { @@ -128,20 +184,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin bindingAwareBroker.registerProvider(baProvider); } - private void initFilesystemSchemaSourceCache(SharedSchemaRepository repository) { - LOG.warn("Schema repository used: {}", repository.getIdentifier()); - if (CACHE == null) { - CACHE = new FilesystemSchemaSourceCache<>(repository, YangTextSchemaSource.class, new File("cache/schema")); - } - if (!INITIALIZED_SCHEMA_REPOSITORIES.contains(repository)) { - repository.registerSchemaSourceListener(CACHE); - repository.registerSchemaSourceListener(TextToASTTransformer.create(repository, repository)); - INITIALIZED_SCHEMA_REPOSITORIES.add(repository); - } - setSchemaRegistry(repository); - setSchemaContextFactory(repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT)); - } - public void setSchemaRegistry(final SchemaSourceRegistry schemaRegistry) { this.schemaRegistry = schemaRegistry; } @@ -237,15 +279,88 @@ public abstract class AbstractNetconfTopology implements NetconfTopology, Bindin salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay); } - NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = - new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory, new NetconfStateSchemas.NetconfStateSchemasResolverImpl()); + final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node); - NetconfDevice device = new NetconfDevice(schemaResourcesDTO, remoteDeviceId, salFacade, + final NetconfDevice device = new NetconfDevice(schemaResourcesDTO, remoteDeviceId, salFacade, processingExecutor.getExecutor(), reconnectOnChangedSchema); return new NetconfConnectorDTO(new NetconfDeviceCommunicator(remoteDeviceId, device), salFacade); } + protected NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) { + // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc. + NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null; + final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory(); + // Only checks to ensure the String is not empty or null; further checks related to directory accessibility and file permissions + // are handled during the FilesystemScehamSourceCache initialization. + if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) { + // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry and + // SchemaContextFactory remain the default values. + if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) { + // Multiple modules may be created at once; synchronize to avoid issues with data consistency among threads. + synchronized(schemaResourcesDTOs) { + // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if they already exist + final NetconfDevice.SchemaResourcesDTO dto = + schemaResourcesDTOs.get(moduleSchemaCacheDirectory); + if (dto == null) { + schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory, nodeId.getValue()); + schemaRegistry.registerSchemaSourceListener( + TextToASTTransformer.create((SchemaRepository) schemaRegistry, schemaRegistry)); + schemaResourcesDTOs.put(moduleSchemaCacheDirectory, schemaResourcesDTO); + } else { + setSchemaContextFactory(dto.getSchemaContextFactory()); + setSchemaRegistry(dto.getSchemaRegistry()); + schemaResourcesDTO = dto; + } + } + LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}", + nodeId.getValue(), moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY); + } + } else { + LOG.warn("schema-cache-directory for {} is null or empty; using the default {}", + nodeId.getValue(), QUALIFIED_DEFAULT_CACHE_DIRECTORY); + } + + if (schemaResourcesDTO == null) { + schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory, + new NetconfStateSchemas.NetconfStateSchemasResolverImpl()); + } + + return schemaResourcesDTO; + } + + /** + * Creates the backing Schema classes for a particular directory. + * + * @param moduleSchemaCacheDirectory The string directory relative to "cache" + * @return A DTO containing the Schema classes for the Netconf mount. + */ + private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory, + final String instanceName) { + + final SharedSchemaRepository repository = new SharedSchemaRepository(instanceName); + final SchemaContextFactory schemaContextFactory + = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + setSchemaRegistry(repository); + setSchemaContextFactory(schemaContextFactory); + final FilesystemSchemaSourceCache deviceCache = + createDeviceFilesystemCache(moduleSchemaCacheDirectory); + repository.registerSchemaSourceListener(deviceCache); + return new NetconfDevice.SchemaResourcesDTO(repository, schemaContextFactory, + new NetconfStateSchemas.NetconfStateSchemasResolverImpl()); + } + + /** + * Creates a FilesystemSchemaSourceCache for the custom schema cache directory. + * + * @param schemaCacheDirectory The custom cache directory relative to "cache" + * @return A FilesystemSchemaSourceCache for the custom schema cache directory + */ + private FilesystemSchemaSourceCache createDeviceFilesystemCache(final String schemaCacheDirectory) { + final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory; + return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class, new File(relativeSchemaCacheDirectory)); + } + public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener, NetconfNode node) { //setup default values since default value is not supported yet in mdsal diff --git a/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java b/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java index 275a2e1d86..7387284061 100644 --- a/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java +++ b/opendaylight/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/impl/ClusteredNetconfTopology.java @@ -33,7 +33,6 @@ import org.opendaylight.netconf.client.NetconfClientDispatcher; import org.opendaylight.netconf.client.NetconfClientSessionListener; import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler; import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice; -import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemas; import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences; import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade; import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; @@ -158,10 +157,9 @@ public class ClusteredNetconfTopology extends AbstractNetconfTopology implements salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay); } - NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = - new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory, new NetconfStateSchemas.NetconfStateSchemasResolverImpl()); + final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node); - NetconfDevice device = new ClusteredNetconfDevice(schemaResourcesDTO, remoteDeviceId, salFacade, + final NetconfDevice device = new ClusteredNetconfDevice(schemaResourcesDTO, remoteDeviceId, salFacade, processingExecutor.getExecutor(), sharedSchemaRepository, actorSystem, topologyId, nodeId.getValue(), TypedActor.context()); return new NetconfConnectorDTO(new ClusteredNetconfDeviceCommunicator(remoteDeviceId, device, entityOwnershipService), salFacade); diff --git a/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java b/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java index dffd7f249e..9feae9a6d2 100644 --- a/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java +++ b/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java @@ -11,13 +11,14 @@ import static org.opendaylight.controller.config.api.JmxAttributeValidationExcep import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkNotNull; import com.google.common.base.Optional; +import com.google.common.base.Strings; import io.netty.util.concurrent.EventExecutor; import java.io.File; import java.math.BigDecimal; import java.net.InetSocketAddress; -import java.util.HashSet; +import java.util.HashMap; import java.util.List; -import java.util.Set; +import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -64,26 +65,84 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co { private static final Logger LOG = LoggerFactory.getLogger(NetconfConnectorModule.class); - private static FilesystemSchemaSourceCache CACHE = null; - //when no topology is defined in connector config, we need to add a default schema repository to mantain backwards compatibility - private static SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY = null; - - //keep track of already initialized repositories to avoid adding redundant listeners - private static final Set INITIALIZED_SCHEMA_REPOSITORIES = new HashSet<>(); + /** + * Filesystem based caches are stored relative to the cache directory. + */ + private static final String CACHE_DIRECTORY = "cache"; + + /** + * The default cache directory relative to CACHE_DIRECTORY + */ + private static final String DEFAULT_CACHE_DIRECTORY = "schema"; + + /** + * The qualified schema cache directory cache/schema + */ + private static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY = CACHE_DIRECTORY + File.separator+ DEFAULT_CACHE_DIRECTORY; + + /** + * The name for the default schema repository + */ + private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector"; + + /** + * The default schema repository in the case that one is not specified. + */ + private static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY = + new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME); + + /** + * The default FilesystemSchemaSourceCache, which stores cached files in cache/schema. + */ + private static final FilesystemSchemaSourceCache DEFAULT_CACHE = + new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class, + new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY)); + + /** + * The default factory for creating SchemaContext instances. + */ + private static final SchemaContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY = + DEFAULT_SCHEMA_REPOSITORY.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + + /** + * Keeps track of initialized Schema resources. A Map is maintained in which the key represents the name + * of the schema cache directory, and the value is a corresponding SchemaResourcesDTO. The + * SchemaResourcesDTO is essentially a container that allows for the extraction of the + * SchemaRegistry and SchemaContextFactory which should be used for a particular + * Netconf mount. Access to schemaResourcesDTOs should be surrounded by appropriate + * synchronization locks. + */ + private static volatile Map schemaResourcesDTOs = new HashMap<>(); + + // Initializes default constant instances for the case when the default schema repository + // directory cache/schema is used. + static { + schemaResourcesDTOs.put(DEFAULT_CACHE_DIRECTORY, + new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, + DEFAULT_SCHEMA_CONTEXT_FACTORY, + new NetconfStateSchemas.NetconfStateSchemasResolverImpl())); + DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE); + DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener( + TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY)); + } private BundleContext bundleContext; private Optional userCapabilities; - private SchemaSourceRegistry schemaRegistry; - private SchemaContextFactory schemaContextFactory; + private SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY; + private SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY; private Broker domRegistry; private NetconfClientDispatcher clientDispatcher; private BindingAwareBroker bindingRegistry; private ThreadPool processingExecutor; private ScheduledThreadPool keepaliveExecutor; - private SharedSchemaRepository sharedSchemaRepository; private EventExecutor eventExecutor; + /** + * The name associated with the Netconf mount point. This value is passed from NetconfConnectorModuleFactory. + */ + private String instanceName; + public NetconfConnectorModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); } @@ -142,8 +201,43 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co salFacade = new KeepaliveSalFacade(id, salFacade, executor, keepaliveDelay); } - final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = - new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory, new NetconfStateSchemas.NetconfStateSchemasResolverImpl()); + // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc. + NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null; + final String moduleSchemaCacheDirectory = getSchemaCacheDirectory(); + // Only checks to ensure the String is not empty or null; further checks related to directory accessibility and file permissions + // are handled during the FilesystemScehamSourceCache initialization. + if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) { + // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry and + // SchemaContextFactory remain the default values. + if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) { + // Multiple modules may be created at once; synchronize to avoid issues with data consistency among threads. + synchronized(schemaResourcesDTOs) { + // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if they already exist + final NetconfDevice.SchemaResourcesDTO dto = + schemaResourcesDTOs.get(moduleSchemaCacheDirectory); + if (dto == null) { + schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory); + schemaRegistry.registerSchemaSourceListener( + TextToASTTransformer.create((SchemaRepository) schemaRegistry, schemaRegistry)); + schemaResourcesDTOs.put(moduleSchemaCacheDirectory, schemaResourcesDTO); + } else { + setSchemaContextFactory(dto.getSchemaContextFactory()); + setSchemaRegistry(dto.getSchemaRegistry()); + schemaResourcesDTO = dto; + } + } + LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}", + instanceName, moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY); + } + } else { + LOG.warn("schema-cache-directory for {} is null or empty; using the default {}", + instanceName, QUALIFIED_DEFAULT_CACHE_DIRECTORY); + } + + if (schemaResourcesDTO == null) { + schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory, + new NetconfStateSchemas.NetconfStateSchemasResolverImpl()); + } final NetconfDevice device = new NetconfDevice(schemaResourcesDTO, id, salFacade, globalProcessingExecutor, getReconnectOnChangedSchema()); @@ -161,6 +255,36 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co return new SalConnectorCloseable(listener, salFacade); } + /** + * Creates the backing Schema classes for a particular directory. + * + * @param moduleSchemaCacheDirectory The string directory relative to "cache" + * @return A DTO containing the Schema classes for the Netconf mount. + */ + private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) { + final SharedSchemaRepository repository = new SharedSchemaRepository(instanceName); + final SchemaContextFactory schemaContextFactory + = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + setSchemaRegistry(repository); + setSchemaContextFactory(schemaContextFactory); + final FilesystemSchemaSourceCache deviceCache = + createDeviceFilesystemCache(moduleSchemaCacheDirectory); + repository.registerSchemaSourceListener(deviceCache); + return new NetconfDevice.SchemaResourcesDTO(repository, schemaContextFactory, + new NetconfStateSchemas.NetconfStateSchemasResolverImpl()); + } + + /** + * Creates a FilesystemSchemaSourceCache for the custom schema cache directory. + * + * @param schemaCacheDirectory The custom cache directory relative to "cache" + * @return A FilesystemSchemaSourceCache for the custom schema cache directory + */ + private FilesystemSchemaSourceCache createDeviceFilesystemCache(final String schemaCacheDirectory) { + final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory; + return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class, new File(relativeSchemaCacheDirectory)); + } + private void initDependencies() { domRegistry = getDomRegistryDependency(); clientDispatcher = getClientDispatcherDependency(); @@ -186,25 +310,6 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co } else { keepaliveExecutor = getKeepaliveExecutorDependency(); } - - if (DEFAULT_SCHEMA_REPOSITORY == null) { - DEFAULT_SCHEMA_REPOSITORY = new SharedSchemaRepository("default shared schema repo"); - } - initFilesystemSchemaSourceCache(DEFAULT_SCHEMA_REPOSITORY); - } - - private void initFilesystemSchemaSourceCache(SharedSchemaRepository repository) { - LOG.warn("Schema repository used: {}", repository.getIdentifier()); - if (CACHE == null) { - CACHE = new FilesystemSchemaSourceCache<>(repository, YangTextSchemaSource.class, new File("cache/schema")); - } - if (!INITIALIZED_SCHEMA_REPOSITORIES.contains(repository)) { - repository.registerSchemaSourceListener(CACHE); - repository.registerSchemaSourceListener(TextToASTTransformer.create(repository, repository)); - INITIALIZED_SCHEMA_REPOSITORIES.add(repository); - } - setSchemaRegistry(repository); - setSchemaContextFactory(repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT)); } private boolean shouldSendKeepalive() { @@ -315,4 +420,8 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co public void setSchemaContextFactory(final SchemaContextFactory schemaContextFactory) { this.schemaContextFactory = schemaContextFactory; } + + public void setInstanceName(final String instanceName) { + this.instanceName = instanceName; + } } diff --git a/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModuleFactory.java b/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModuleFactory.java index 2b31fe05d0..4132e1cd89 100644 --- a/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModuleFactory.java +++ b/opendaylight/netconf/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModuleFactory.java @@ -23,6 +23,7 @@ public class NetconfConnectorModuleFactory extends final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception { final NetconfConnectorModule module = (NetconfConnectorModule) super.createModule(instanceName, dependencyResolver, old, bundleContext); + module.setInstanceName(instanceName); return module; } @@ -30,6 +31,7 @@ public class NetconfConnectorModuleFactory extends public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) { final NetconfConnectorModule module = (NetconfConnectorModule) super.createModule(instanceName, dependencyResolver, bundleContext); + module.setInstanceName(instanceName); return module; } } diff --git a/opendaylight/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang b/opendaylight/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang index ca3b81d0a7..bc0983dea1 100644 --- a/opendaylight/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang +++ b/opendaylight/netconf/sal-netconf-connector/src/main/yang/netconf-node-topology.yang @@ -174,6 +174,16 @@ module netconf-node-topology { } + grouping netconf-schema-storage { + leaf schema-cache-directory { + config true; + type string; + default "schema"; + description "The destination schema repository for yang files relative to the cache directory. This may be specified per netconf mount + so that the loaded yang files are stored to a distinct directory to avoid potential conflict."; + } + } + grouping netconf-node-fields { uses netconf-node-credentials; @@ -182,6 +192,8 @@ module netconf-node-topology { uses netconf-node-connection-status; + uses netconf-schema-storage; + } augment "/nt:network-topology/nt:topology/nt:node" { diff --git a/opendaylight/netconf/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang b/opendaylight/netconf/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang index da197e31cf..b195970528 100644 --- a/opendaylight/netconf/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang +++ b/opendaylight/netconf/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang @@ -63,6 +63,13 @@ module odl-sal-netconf-connector-cfg { type string; } + leaf schema-cache-directory { + type string; + default "schema"; + description "The destination schema repository for yang files relative to the cache directory. This may be specified per netconf mount + so that the loaded yang files are stored to a distinct directory to avoid potential conflict."; + } + container yang-module-capabilities { leaf-list capability { type string; -- 2.36.6