import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.Collection;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@Override
public DeviceSources call() throws Exception {
-
- final Set<SourceIdentifier> requiredSources = Sets.newHashSet(Collections2.transform(
- remoteSessionCapabilities.getModuleBasedCaps(), QNAME_TO_SOURCE_ID_FUNCTION));
-
- // If monitoring is not supported, we will still attempt to create schema, sources might be already provided
final NetconfStateSchemas availableSchemas = stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id);
logger.debug("{}: Schemas exposed by ietf-netconf-monitoring: {}", id, availableSchemas.getAvailableYangSchemasQNames());
- final Set<SourceIdentifier> providedSources = Sets.newHashSet(Collections2.transform(
- availableSchemas.getAvailableYangSchemasQNames(), QNAME_TO_SOURCE_ID_FUNCTION));
-
- final Set<SourceIdentifier> requiredSourcesNotProvided = Sets.difference(requiredSources, providedSources);
+ final Set<QName> requiredSources = Sets.newHashSet(remoteSessionCapabilities.getModuleBasedCaps());
+ final Set<QName> providedSources = availableSchemas.getAvailableYangSchemasQNames();
+ final Set<QName> requiredSourcesNotProvided = Sets.difference(requiredSources, providedSources);
if (!requiredSourcesNotProvided.isEmpty()) {
logger.warn("{}: Netconf device does not provide all yang models reported in hello message capabilities, required but not provided: {}",
id, requiredSourcesNotProvided);
logger.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<SourceIdentifier> providedSourcesNotRequired = Sets.difference(providedSources, requiredSources);
+ final Set<QName> providedSourcesNotRequired = Sets.difference(providedSources, requiredSources);
if (!providedSourcesNotRequired.isEmpty()) {
logger.warn("{}: Netconf device provides additional yang models not reported in hello message capabilities: {}",
id, providedSourcesNotRequired);
* Contains RequiredSources - sources from capabilities.
*/
private static final class DeviceSources {
- private final Collection<SourceIdentifier> requiredSources;
- private final Collection<SourceIdentifier> providedSources;
+ private final Set<QName> requiredSources;
+ private final Set<QName> providedSources;
- public DeviceSources(final Collection<SourceIdentifier> requiredSources, final Collection<SourceIdentifier> providedSources) {
+ public DeviceSources(final Set<QName> requiredSources, final Set<QName> providedSources) {
this.requiredSources = requiredSources;
this.providedSources = providedSources;
}
- public Collection<SourceIdentifier> getRequiredSources() {
+ public Set<QName> getRequiredSourcesQName() {
return requiredSources;
}
- public Collection<SourceIdentifier> getProvidedSources() {
+ public Set<QName> getProvidedSourcesQName() {
return providedSources;
}
+ public Collection<SourceIdentifier> getRequiredSources() {
+ return Collections2.transform(requiredSources, QNAME_TO_SOURCE_ID_FUNCTION);
+ }
+
+ public Collection<SourceIdentifier> getProvidedSources() {
+ return Collections2.transform(providedSources, QNAME_TO_SOURCE_ID_FUNCTION);
+ }
+
}
/**
@Override
public void onSuccess(final SchemaContext result) {
logger.debug("{}: Schema context built successfully from {}", id, requiredSources);
- final Collection<QName> filteredQNames = Sets.difference(remoteSessionCapabilities.getModuleBasedCaps(), capabilities.getUnresolvedCapabilites().keySet());
+ final Collection<QName> filteredQNames = Sets.difference(deviceSources.getProvidedSourcesQName(), capabilities.getUnresolvedCapabilites().keySet());
capabilities.addCapabilities(filteredQNames);
capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps());
handleSalInitializationSuccess(result, remoteSessionCapabilities, getDeviceSpecificRpc(result));
}
private Collection<QName> getQNameFromSourceIdentifiers(final Collection<SourceIdentifier> identifiers) {
- final Collection<QName> qNames = new HashSet<>();
- for (final SourceIdentifier source : identifiers) {
- final Optional<QName> qname = getQNameFromSourceIdentifier(source);
- if (qname.isPresent()) {
- qNames.add(qname.get());
+ final Collection<QName> qNames = Collections2.transform(identifiers, new Function<SourceIdentifier, QName>() {
+ @Override
+ public QName apply(final SourceIdentifier sourceIdentifier) {
+ return getQNameFromSourceIdentifier(sourceIdentifier);
}
- }
+ });
+
if (qNames.isEmpty()) {
logger.debug("Unable to map any source identfiers to a capability reported by device : " + identifiers);
}
return qNames;
}
- private Optional<QName> getQNameFromSourceIdentifier(final SourceIdentifier identifier) {
- for (final QName qname : remoteSessionCapabilities.getModuleBasedCaps()) {
- if (qname.getLocalName().equals(identifier.getName())
- && qname.getFormattedRevision().equals(identifier.getRevision())) {
- return Optional.of(qname);
+ private QName getQNameFromSourceIdentifier(final SourceIdentifier identifier) {
+ // Required sources are all required and provided merged in DeviceSourcesResolver
+ for (final QName qname : deviceSources.getRequiredSourcesQName()) {
+ if(qname.getLocalName().equals(identifier.getName()) == false) {
+ continue;
+ }
+
+ if(identifier.getRevision().equals(SourceIdentifier.NOT_PRESENT_FORMATTED_REVISION) &&
+ qname.getRevision() == null) {
+ return qname;
+ }
+
+ if (qname.getFormattedRevision().equals(identifier.getRevision())) {
+ return qname;
}
}
- throw new IllegalArgumentException("Unable to map identifier to a devices reported capability: " + identifier);
+ throw new IllegalArgumentException("Unable to map identifier to a devices reported capability: " + identifier + " Available: " + deviceSources.getRequiredSourcesQName());
}
}
}
import com.google.common.base.Optional;
import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
import java.io.InputStream;
import java.util.ArrayList;
import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceRpc;
import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.Module;
public void testNetconfDeviceMissingSource() throws Exception {
final RemoteDeviceHandler<NetconfSessionPreferences> facade = getFacade();
final NetconfDeviceCommunicator listener = getListener();
+ final SchemaContext schema = getSchema();
final SchemaContextFactory schemaFactory = getSchemaFactory();
if(((Collection<?>) invocation.getArguments()[0]).size() == 2) {
return Futures.immediateFailedCheckedFuture(schemaResolutionException);
} else {
- return Futures.immediateCheckedFuture(getSchema());
+ return Futures.immediateCheckedFuture(schema);
}
}
}).when(schemaFactory).createSchemaContext(anyCollectionOf(SourceIdentifier.class));
final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO
- = new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), schemaFactory, stateSchemasResolver);
+ = new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), schemaFactory, new NetconfStateSchemas.NetconfStateSchemasResolver() {
+ @Override
+ public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionPreferences remoteSessionCapabilities, final RemoteDeviceId id) {
+ final Module first = Iterables.getFirst(schema.getModules(), null);
+ final QName qName = QName.create(first.getQNameModule(), first.getName());
+ final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
+ final NetconfStateSchemas.RemoteYangSchema source2 = new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
+ return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
+ }
+ });
+
final NetconfDevice device = new NetconfDevice(schemaResourcesDTO, getId(), facade, getExecutor(), true);
// Monitoring supported
final NetconfSessionPreferences sessionCaps = getSessionCaps(true, Lists.newArrayList(TEST_CAPABILITY, TEST_CAPABILITY2));