Bug 5403 - Support yang-library schema resolution
[netconf.git] / netconf / sal-netconf-connector / src / main / java / org / opendaylight / controller / config / yang / md / sal / connector / netconf / NetconfConnectorModule.java
index bbf55f9d378aad8c784195e0a89ff81ed2f1b086..96cb688e45b55b4a2e2279e579e03b60a5bf8fe5 100644 (file)
@@ -7,15 +7,18 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.connector.netconf;
 
+import static com.google.common.base.Preconditions.checkArgument;
 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 com.google.common.base.Strings;
+import com.google.common.collect.Lists;
 import io.netty.util.concurrent.EventExecutor;
 import java.io.File;
 import java.math.BigDecimal;
 import java.net.InetSocketAddress;
+import java.net.URL;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,27 +37,31 @@ import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurati
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemas;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
 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.listener.UserPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yangtools.yang.common.QName;
+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.SchemaSourceFilter;
 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.SchemaSourceRegistration;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
 import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
@@ -127,7 +134,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         schemaResourcesDTOs.put(DEFAULT_CACHE_DIRECTORY,
                 new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY,
                         DEFAULT_SCHEMA_CONTEXT_FACTORY,
-                        new NetconfStateSchemas.NetconfStateSchemasResolverImpl()));
+                        new NetconfStateSchemasResolverImpl()));
         DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE);
         DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
                 TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
@@ -212,7 +219,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         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.
+        // are handled during the FilesystemSchemaSourceCache 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.
@@ -234,8 +241,10 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
                     }
                     if (userCapabilities.isPresent()) {
                         for (QName qname : userCapabilities.get().getModuleBasedCaps()) {
-                            final SourceIdentifier sourceIdentifier = new SourceIdentifier(qname.getLocalName(), qname.getFormattedRevision());
-                            dto.getSchemaRegistry().registerSchemaSource(DEFAULT_CACHE, PotentialSchemaSource.create(sourceIdentifier, YangTextSchemaSource.class, LOCAL_IO_FALLBACK_COST));
+                            final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier
+                                    .create(qname.getLocalName(), qname.getFormattedRevision());
+                            dto.getSchemaRegistry().registerSchemaSource(DEFAULT_CACHE, PotentialSchemaSource
+                                    .create(sourceIdentifier, YangTextSchemaSource.class, LOCAL_IO_FALLBACK_COST));
                         }
                     }
                 }
@@ -247,9 +256,35 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
                     instanceName, QUALIFIED_DEFAULT_CACHE_DIRECTORY);
         }
 
+        // pre register yang library sources as fallback schemas to schema registry
+        List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
+        if (getYangLibrary() != null) {
+            final String yangLibURL = getYangLibrary().getYangLibraryUrl().getValue();
+            final String yangLibUsername = getYangLibrary().getUsername();
+            final String yangLigPassword = getYangLibrary().getPassword();
+
+            LibraryModulesSchemas libraryModulesSchemas;
+            if(yangLibURL != null) {
+                if(yangLibUsername != null && yangLigPassword != null) {
+                    libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
+                } else {
+                    libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
+                }
+
+                for (Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry : libraryModulesSchemas.getAvailableModels().entrySet()) {
+                    registeredYangLibSources.
+                            add(schemaRegistry.registerSchemaSource(
+                                    new YangLibrarySchemaYangSourceProvider(id, libraryModulesSchemas.getAvailableModels()),
+                                    PotentialSchemaSource
+                                            .create(sourceIdentifierURLEntry.getKey(), YangTextSchemaSource.class,
+                                                    PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
+                }
+            }
+        }
+
         if (schemaResourcesDTO == null) {
             schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaContextFactory,
-                    new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+                    new NetconfStateSchemasResolverImpl());
         }
 
         final NetconfDevice device = new NetconfDeviceBuilder()
@@ -260,10 +295,14 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
                 .setSalFacade(salFacade)
                 .build();
 
+        if (getConcurrentRpcLimit() < 1) {
+            LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", id);
+        }
+
         final NetconfDeviceCommunicator listener = userCapabilities.isPresent() ?
                 new NetconfDeviceCommunicator(id, device,
-                        new UserPreferences(userCapabilities.get(), getYangModuleCapabilities().getOverride())):
-                new NetconfDeviceCommunicator(id, device);
+                        new UserPreferences(userCapabilities.get(), getYangModuleCapabilities().getOverride()), getConcurrentRpcLimit()):
+                new NetconfDeviceCommunicator(id, device, getConcurrentRpcLimit());
 
         if (shouldSendKeepalive()) {
             ((KeepaliveSalFacade) salFacade).setListener(listener);
@@ -272,7 +311,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
         final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(listener);
         listener.initializeRemoteConnection(clientDispatcher, clientConfig);
 
-        return new SalConnectorCloseable(listener, salFacade);
+        return new SalConnectorCloseable(listener, salFacade, registeredYangLibSources);
     }
 
     /**
@@ -291,7 +330,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
                 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
         repository.registerSchemaSourceListener(deviceCache);
         return new NetconfDevice.SchemaResourcesDTO(repository, schemaContextFactory,
-                new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+                new NetconfStateSchemasResolverImpl());
     }
 
     /**
@@ -379,16 +418,22 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
 
     private static final class SalConnectorCloseable implements AutoCloseable {
         private final RemoteDeviceHandler<NetconfSessionPreferences> salFacade;
+        private final List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources;
         private final NetconfDeviceCommunicator listener;
 
         public SalConnectorCloseable(final NetconfDeviceCommunicator listener,
-                                     final RemoteDeviceHandler<NetconfSessionPreferences> salFacade) {
+                                     final RemoteDeviceHandler<NetconfSessionPreferences> salFacade,
+                                     final List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources) {
             this.listener = listener;
             this.salFacade = salFacade;
+            this.registeredYangLibSources = registeredYangLibSources;
         }
 
         @Override
         public void close() {
+            for (SchemaSourceRegistration<YangTextSchemaSource> registeredYangLibSource : registeredYangLibSources) {
+                registeredYangLibSource.close();
+            }
             listener.close();
             salFacade.close();
         }