From: Tony Tkacik Date: Mon, 30 Mar 2015 08:27:31 +0000 (+0000) Subject: Merge "Avoid IllegalArgument on missing source" X-Git-Tag: release/lithium~333 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=edcc020c8fda4b13f22a31d79c13feef0b53b0ee;hp=95115ca49f3b16b936e0f6c88aedfc17cd0ee92c Merge "Avoid IllegalArgument on missing source" --- diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java index 88dd0e55c5..db9b702fed 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java @@ -21,7 +21,6 @@ import com.google.common.util.concurrent.ListenableFuture; 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; @@ -325,31 +324,24 @@ public final class NetconfDevice implements RemoteDevice 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 providedSources = Sets.newHashSet(Collections2.transform( - availableSchemas.getAvailableYangSchemasQNames(), QNAME_TO_SOURCE_ID_FUNCTION)); - - final Set requiredSourcesNotProvided = Sets.difference(requiredSources, providedSources); + final Set requiredSources = Sets.newHashSet(remoteSessionCapabilities.getModuleBasedCaps()); + final Set providedSources = availableSchemas.getAvailableYangSchemasQNames(); + final Set 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 providedSourcesNotRequired = Sets.difference(providedSources, requiredSources); + final Set providedSourcesNotRequired = Sets.difference(providedSources, requiredSources); if (!providedSourcesNotRequired.isEmpty()) { logger.warn("{}: Netconf device provides additional yang models not reported in hello message capabilities: {}", id, providedSourcesNotRequired); @@ -366,22 +358,30 @@ public final class NetconfDevice implements RemoteDevice requiredSources; - private final Collection providedSources; + private final Set requiredSources; + private final Set providedSources; - public DeviceSources(final Collection requiredSources, final Collection providedSources) { + public DeviceSources(final Set requiredSources, final Set providedSources) { this.requiredSources = requiredSources; this.providedSources = providedSources; } - public Collection getRequiredSources() { + public Set getRequiredSourcesQName() { return requiredSources; } - public Collection getProvidedSources() { + public Set getProvidedSourcesQName() { return providedSources; } + public Collection getRequiredSources() { + return Collections2.transform(requiredSources, QNAME_TO_SOURCE_ID_FUNCTION); + } + + public Collection getProvidedSources() { + return Collections2.transform(providedSources, QNAME_TO_SOURCE_ID_FUNCTION); + } + } /** @@ -427,7 +427,7 @@ public final class NetconfDevice implements RemoteDevice filteredQNames = Sets.difference(remoteSessionCapabilities.getModuleBasedCaps(), capabilities.getUnresolvedCapabilites().keySet()); + final Collection filteredQNames = Sets.difference(deviceSources.getProvidedSourcesQName(), capabilities.getUnresolvedCapabilites().keySet()); capabilities.addCapabilities(filteredQNames); capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps()); handleSalInitializationSuccess(result, remoteSessionCapabilities, getDeviceSpecificRpc(result)); @@ -472,27 +472,36 @@ public final class NetconfDevice implements RemoteDevice getQNameFromSourceIdentifiers(final Collection identifiers) { - final Collection qNames = new HashSet<>(); - for (final SourceIdentifier source : identifiers) { - final Optional qname = getQNameFromSourceIdentifier(source); - if (qname.isPresent()) { - qNames.add(qname.get()); + final Collection qNames = Collections2.transform(identifiers, new Function() { + @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 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()); } } } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemas.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemas.java index 942e4bbaeb..645028b13f 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemas.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfStateSchemas.java @@ -174,7 +174,7 @@ public final class NetconfStateSchemas { public final static class RemoteYangSchema { private final QName qname; - private RemoteYangSchema(final QName qname) { + RemoteYangSchema(final QName qname) { this.qname = qname; } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java index 0f643789ec..93f4df83e4 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java @@ -19,7 +19,9 @@ import static org.mockito.Mockito.verify; 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; @@ -46,6 +48,7 @@ import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionPr 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; @@ -132,6 +135,7 @@ public class NetconfDeviceTest { public void testNetconfDeviceMissingSource() throws Exception { final RemoteDeviceHandler facade = getFacade(); final NetconfDeviceCommunicator listener = getListener(); + final SchemaContext schema = getSchema(); final SchemaContextFactory schemaFactory = getSchemaFactory(); @@ -143,13 +147,23 @@ public class NetconfDeviceTest { 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));