98521c1bb1478f2d37e833a03a07a59006c98416
[netconf.git] / plugins / netconf-client-mdsal / src / main / java / org / opendaylight / netconf / client / mdsal / DeviceSourcesResolver.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netconf.client.mdsal;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.Sets;
13 import java.util.HashSet;
14 import java.util.concurrent.Callable;
15 import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
16 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
17 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
18 import org.opendaylight.netconf.client.mdsal.impl.BaseSchema;
19 import org.opendaylight.netconf.client.mdsal.spi.NetconfDeviceRpc;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 /**
24  * Schema building callable.
25  */
26 final class DeviceSourcesResolver implements Callable<DeviceSources> {
27     private static final Logger LOG = LoggerFactory.getLogger(DeviceSourcesResolver.class);
28
29     private final NetconfSessionPreferences remoteSessionCapabilities;
30     private final NetconfDeviceSchemasResolver stateSchemasResolver;
31     private final NetconfDeviceRpc deviceRpc;
32     private final BaseSchema baseSchema;
33     private final RemoteDeviceId id;
34
35     DeviceSourcesResolver(final RemoteDeviceId id, final BaseSchema baseSchema, final NetconfDeviceRpc deviceRpc,
36             final NetconfSessionPreferences remoteSessionCapabilities,
37             final NetconfDeviceSchemasResolver stateSchemasResolver) {
38         this.id = requireNonNull(id);
39         this.baseSchema = requireNonNull(baseSchema);
40         this.deviceRpc = requireNonNull(deviceRpc);
41         this.remoteSessionCapabilities = requireNonNull(remoteSessionCapabilities);
42         this.stateSchemasResolver = requireNonNull(stateSchemasResolver);
43     }
44
45     @Override
46     public DeviceSources call() {
47         final var availableSchemas = stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id,
48             baseSchema.modelContext());
49         LOG.debug("{}: Schemas exposed by ietf-netconf-monitoring: {}", id,
50             availableSchemas.getAvailableYangSchemasQNames());
51
52         final var requiredSources = new HashSet<>(remoteSessionCapabilities.moduleBasedCaps().keySet());
53         final var providedSources = availableSchemas.getAvailableYangSchemasQNames();
54         final var requiredSourcesNotProvided = Sets.difference(requiredSources, providedSources);
55         if (!requiredSourcesNotProvided.isEmpty()) {
56             LOG.warn("{}: Netconf device does not provide all yang models reported in hello message capabilities,"
57                     + " required but not provided: {}", id, requiredSourcesNotProvided);
58             LOG.warn("{}: Attempting to build schema context from required sources", id);
59         }
60
61         // Here all the sources reported in netconf monitoring are merged with those reported in hello.
62         // It is necessary to perform this since submodules are not mentioned in hello but still required.
63         // This clashes with the option of a user to specify supported yang models manually in configuration
64         // for netconf-connector and as a result one is not able to fully override yang models of a device.
65         // It is only possible to add additional models.
66         final var providedSourcesNotRequired = Sets.difference(providedSources, requiredSources);
67         if (!providedSourcesNotRequired.isEmpty()) {
68             LOG.warn("{}: Netconf device provides additional yang models not reported in "
69                     + "hello message capabilities: {}", id, providedSourcesNotRequired);
70             LOG.warn("{}: Adding provided but not required sources as required to prevent failures", id);
71             LOG.debug("{}: Netconf device reported in hello: {}", id, requiredSources);
72             requiredSources.addAll(providedSourcesNotRequired);
73         }
74
75         final var sourceProvider = availableSchemas instanceof LibraryModulesSchemas libraryModule
76             ? new LibrarySchemaSourceProvider(id, libraryModule.getAvailableModels())
77                 : new MonitoringSchemaSourceProvider(id, deviceRpc.domRpcService());
78         return new DeviceSources(requiredSources, providedSources, sourceProvider);
79     }
80 }