@Override
public java.lang.AutoCloseable createInstance() {
final MdsalNetconfOperationServiceFactory mdsalNetconfOperationServiceFactory =
- new MdsalNetconfOperationServiceFactory(getRootSchemaServiceDependency()) {
+ new MdsalNetconfOperationServiceFactory(getRootSchemaServiceDependency(), getRootSchemaSourceProviderDependency()) {
@Override
public void close() throws Exception {
super.close();
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
public class CurrentSchemaContext implements SchemaContextListener, AutoCloseable {
final AtomicReference<SchemaContext> currentContext = new AtomicReference<SchemaContext>();
private final ListenerRegistration<SchemaContextListener> schemaContextListenerListenerRegistration;
private final Set<CapabilityListener> listeners1 = Collections.synchronizedSet(Sets.<CapabilityListener>newHashSet());
+ private SchemaSourceProvider<YangTextSchemaSource> rootSchemaSourceProvider;
public SchemaContext getCurrentContext() {
Preconditions.checkState(currentContext.get() != null, "Current context not received");
return currentContext.get();
}
- public CurrentSchemaContext(final SchemaService schemaService) {
+ public CurrentSchemaContext(final SchemaService schemaService, final SchemaSourceProvider<YangTextSchemaSource> rootSchemaSourceProvider) {
+ this.rootSchemaSourceProvider = rootSchemaSourceProvider;
schemaContextListenerListenerRegistration = schemaService.registerSchemaContextListener(this);
}
public void onGlobalContextUpdated(final SchemaContext schemaContext) {
currentContext.set(schemaContext);
// FIXME is notifying all the listeners from this callback wise ?
- final Set<Capability> addedCaps = MdsalNetconfOperationServiceFactory.transformCapabilities(currentContext.get());
+ final Set<Capability> addedCaps = MdsalNetconfOperationServiceFactory.transformCapabilities(currentContext.get(), rootSchemaSourceProvider);
for (final CapabilityListener listener : listeners1) {
listener.onCapabilitiesChanged(addedCaps, Collections.<Capability>emptySet());
}
}
public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
- listener.onCapabilitiesChanged(MdsalNetconfOperationServiceFactory.transformCapabilities(currentContext.get()), Collections.<Capability>emptySet());
+ listener.onCapabilitiesChanged(MdsalNetconfOperationServiceFactory.transformCapabilities(currentContext.get(), rootSchemaSourceProvider), Collections.<Capability>emptySet());
listeners1.add(listener);
return new AutoCloseable() {
@Override
package org.opendaylight.netconf.mdsal.connector;
+import com.google.common.base.Charsets;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.io.CharStreams;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import org.opendaylight.controller.config.util.capability.YangModuleCapability;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.api.monitoring.CapabilityListener;
-import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
import org.opendaylight.controller.sal.core.api.Consumer;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private DOMDataBroker dataBroker = null;
private DOMRpcService rpcService = null;
private final CurrentSchemaContext currentSchemaContext;
+ private final SchemaSourceProvider<YangTextSchemaSource> rootSchemaSourceProviderDependency;
- public MdsalNetconfOperationServiceFactory(final SchemaService schemaService) {
- this.currentSchemaContext = new CurrentSchemaContext(Preconditions.checkNotNull(schemaService));
+ public MdsalNetconfOperationServiceFactory(final SchemaService schemaService, final SchemaSourceProvider<YangTextSchemaSource> rootSchemaSourceProviderDependency) {
+ this.rootSchemaSourceProviderDependency = rootSchemaSourceProviderDependency;
+ this.currentSchemaContext = new CurrentSchemaContext(Preconditions.checkNotNull(schemaService), rootSchemaSourceProviderDependency);
}
@Override
@Override
public Set<Capability> getCapabilities() {
- return transformCapabilities(currentSchemaContext.getCurrentContext());
+ return transformCapabilities(currentSchemaContext.getCurrentContext(), rootSchemaSourceProviderDependency);
}
- static Set<Capability> transformCapabilities(final SchemaContext currentContext) {
+ static Set<Capability> transformCapabilities(final SchemaContext currentContext, final SchemaSourceProvider<YangTextSchemaSource> rootSchemaSourceProviderDependency) {
final Set<Capability> capabilities = new HashSet<>();
// Added by netconf-impl by default
final Set<Module> modules = currentContext.getModules();
for (final Module module : modules) {
- Optional<YangModuleCapability> cap = moduleToCapability(module);
+ Optional<YangModuleCapability> cap = moduleToCapability(module, rootSchemaSourceProviderDependency);
if(cap.isPresent()) {
capabilities.add(cap.get());
}
for (final Module submodule : module.getSubmodules()) {
- cap = moduleToCapability(submodule);
+ cap = moduleToCapability(submodule, rootSchemaSourceProviderDependency);
if(cap.isPresent()) {
capabilities.add(cap.get());
}
return capabilities;
}
- private static Optional<YangModuleCapability> moduleToCapability(final Module module) {
- final String source = module.getSource();
+ private static Optional<YangModuleCapability> moduleToCapability(
+ final Module module, final SchemaSourceProvider<YangTextSchemaSource> rootSchemaSourceProviderDependency) {
+
+ final SourceIdentifier moduleSourceIdentifier = SourceIdentifier.create(module.getName(),
+ (SimpleDateFormatUtil.DEFAULT_DATE_REV == module.getRevision() ? Optional.<String>absent() :
+ Optional.of(SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()))));
+
+ InputStream sourceStream = null;
+ String source;
+ try {
+ sourceStream = rootSchemaSourceProviderDependency.getSource(moduleSourceIdentifier).checkedGet().openStream();
+ source = CharStreams.toString(new InputStreamReader(sourceStream, Charsets.UTF_8));
+ } catch (IOException | SchemaSourceException e) {
+ LOG.warn("Ignoring source for module {}. Unable to read content", moduleSourceIdentifier, e);
+ source = null;
+ }
+
+ try {
+ if (sourceStream != null) {
+ sourceStream.close();
+ }
+ } catch (IOException e) {
+ LOG.warn("Error closing yang source stream {}. Ignoring", moduleSourceIdentifier, e);
+ }
+
if(source !=null) {
return Optional.of(new YangModuleCapability(module, source));
} else {
LOG.warn("Missing source for module {}. This module will not be available from netconf server",
- module);
+ moduleSourceIdentifier);
}
return Optional.absent();
}
}
}
+ container root-schema-source-provider {
+ uses config:service-ref {
+ refine type {
+ mandatory false;
+ config:required-identity md-sal-dom:yang-text-source-provider;
+ }
+ }
+ }
+
container dom-broker {
uses config:service-ref {
refine type {
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import com.google.common.util.concurrent.Futures;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import org.custommonkey.xmlunit.XMLUnit;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import org.opendaylight.controller.cluster.datastore.ConcurrentDOMDataBroker;
import org.opendaylight.controller.config.util.xml.DocumentedException;
import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorSeverity;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+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;
import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
import org.slf4j.Logger;
private TransactionProvider transactionProvider = null;
+ @Mock
+ private SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
+
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreAttributeOrder(true);
final ConcurrentDOMDataBroker cdb = new ConcurrentDOMDataBroker(datastores, listenableFutureExecutor);
this.transactionProvider = new TransactionProvider(cdb, sessionIdForReporting);
- this.currentSchemaContext = new CurrentSchemaContext(schemaService);
+
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ final SourceIdentifier sId = (SourceIdentifier) invocationOnMock.getArguments()[0];
+ final YangTextSchemaSource yangTextSchemaSource =
+ YangTextSchemaSource.delegateForByteSource(sId, ByteSource.wrap("module test".getBytes()));
+ return Futures.immediateCheckedFuture(yangTextSchemaSource);
+
+ }
+ }).when(sourceProvider).getSource(any(SourceIdentifier.class));
+
+ this.currentSchemaContext = new CurrentSchemaContext(schemaService, sourceProvider);
}
import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.netconf.mapping.api.HandlingPriority;
import org.opendaylight.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.netconf.mdsal.connector.CurrentSchemaContext;
import org.opendaylight.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+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;
import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
import org.slf4j.Logger;
private SchemaContextListener listener;
@Mock
private ListenerRegistration registration;
+ @Mock
+ private SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
@Before
public void setUp() throws Exception {
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreAttributeOrder(true);
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ final SourceIdentifier sId = (SourceIdentifier) invocationOnMock.getArguments()[0];
+ final YangTextSchemaSource yangTextSchemaSource =
+ YangTextSchemaSource.delegateForByteSource(sId, ByteSource.wrap("module test".getBytes()));
+ return Futures.immediateCheckedFuture(yangTextSchemaSource);
+
+ }
+ }).when(sourceProvider).getSource(any(SourceIdentifier.class));
+
this.schemaContext = parseSchemas(getYangSchemas());
- this.currentSchemaContext = new CurrentSchemaContext(schemaService);
+ this.currentSchemaContext = new CurrentSchemaContext(schemaService, sourceProvider);
}
@Test
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
<name>yang-schema-service</name>
</root-schema-service>
+ <root-schema-source-provider>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:yang-text-source-provider</type>
+ <name>yang-text-source-provider</name>
+ </root-schema-source-provider>
<dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:mapper">
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
<name>dom-broker</name>
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final Set<Capability> caps;
private final SchemaContext schemaContext;
+ private SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
public MdsalOperationProvider(final SessionIdProvider idProvider,
final Set<Capability> caps,
- final SchemaContext schemaContext) {
+ final SchemaContext schemaContext, final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
this.caps = caps;
this.schemaContext = schemaContext;
+ this.sourceProvider = sourceProvider;
}
@Override
@Override
public NetconfOperationService createService(String netconfSessionIdForReporting) {
- return new MdsalOperationService(Long.parseLong(netconfSessionIdForReporting), schemaContext, caps);
+ return new MdsalOperationService(Long.parseLong(netconfSessionIdForReporting), schemaContext, caps, sourceProvider);
}
static class MdsalOperationService implements NetconfOperationService {
private final Set<Capability> caps;
private final SchemaService schemaService;
private final DOMDataBroker dataBroker;
+ private SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
public MdsalOperationService(final long currentSessionId,
final SchemaContext schemaContext,
- final Set<Capability> caps) {
+ final Set<Capability> caps, final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
this.currentSessionId = currentSessionId;
this.schemaContext = schemaContext;
this.caps = caps;
+ this.sourceProvider = sourceProvider;
this.schemaService = createSchemaService();
this.dataBroker = createDataStore(schemaService);
@Override
public Set<NetconfOperation> getNetconfOperations() {
TransactionProvider transactionProvider = new TransactionProvider(dataBroker, String.valueOf(currentSessionId));
- CurrentSchemaContext currentSchemaContext = new CurrentSchemaContext(schemaService);
+ CurrentSchemaContext currentSchemaContext = new CurrentSchemaContext(schemaService, sourceProvider);
ContainerNode netconf = createNetconfState();
this.nioExecutor = nioExecutor;
}
- private NetconfServerDispatcherImpl createDispatcher(final Set<Capability> capabilities, final boolean exi, final int generateConfigsTimeout, final Optional<File> notificationsFile, final boolean mdSal, final Optional<File> initialConfigXMLFile) {
+ private NetconfServerDispatcherImpl createDispatcher(final Set<Capability> capabilities, final boolean exi, final int generateConfigsTimeout,
+ final Optional<File> notificationsFile, final boolean mdSal, final Optional<File> initialConfigXMLFile,
+ final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
final Set<Capability> transformedCapabilities = Sets.newHashSet(Collections2.transform(capabilities, new Function<Capability, Capability>() {
@Override
final SessionIdProvider idProvider = new SessionIdProvider();
final AggregatedNetconfOperationServiceFactory aggregatedNetconfOperationServiceFactory = new AggregatedNetconfOperationServiceFactory();
- final NetconfOperationServiceFactory operationProvider = mdSal ? new MdsalOperationProvider(idProvider, transformedCapabilities, schemaContext) :
+ final NetconfOperationServiceFactory operationProvider = mdSal ? new MdsalOperationProvider(idProvider, transformedCapabilities, schemaContext, sourceProvider) :
new SimulatedOperationProvider(idProvider, transformedCapabilities, notificationsFile, initialConfigXMLFile);
transformedCapabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0"));
public List<Integer> start(final Main.Params params) {
LOG.info("Starting {}, {} simulated devices starting on port {}", params.deviceCount, params.ssh ? "SSH" : "TCP", params.startingPort);
- final Set<Capability> capabilities = parseSchemasToModuleCapabilities(params);
+ final SharedSchemaRepository schemaRepo = new SharedSchemaRepository("netconf-simulator");
+ final Set<Capability> capabilities = parseSchemasToModuleCapabilities(params, schemaRepo);
final NetconfServerDispatcherImpl dispatcher = createDispatcher(capabilities, params.exi, params.generateConfigsTimeout,
- Optional.fromNullable(params.notificationFile), params.mdSal, Optional.fromNullable(params.initialConfigXMLFile));
+ Optional.fromNullable(params.notificationFile), params.mdSal, Optional.fromNullable(params.initialConfigXMLFile),
+ new SchemaSourceProvider<YangTextSchemaSource>() {
+ @Override
+ public CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> getSource(final SourceIdentifier sourceIdentifier) {
+ return schemaRepo.getSchemaSource(sourceIdentifier, YangTextSchemaSource.class);
+ }
+ });
int currentPort = params.startingPort;
}
}
- private Set<Capability> parseSchemasToModuleCapabilities(final Main.Params params) {
- final SharedSchemaRepository consumer = new SharedSchemaRepository("netconf-simulator");
+ private Set<Capability> parseSchemasToModuleCapabilities(final Main.Params params, final SharedSchemaRepository consumer) {
final Set<SourceIdentifier> loadedSources = Sets.newHashSet();
consumer.registerSchemaSourceListener(TextToASTTransformer.create(consumer, consumer));