HoneyNode Java 11 support for 221 devices
[transportpce.git] / tests / honeynode / 1.2.1 / honeynode-plugin-impl / src / main / java / io / fd / honeycomb / transportpce / device / read / NetconfStateReaderFactory.java
1 /*
2  * Copyright (c) 2018 Orange and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package io.fd.honeycomb.transportpce.device.read;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Set;
23 import java.util.concurrent.ExecutionException;
24
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.opendaylight.mdsal.binding.api.DataBroker;
27 import org.opendaylight.mdsal.binding.api.WriteTransaction;
28 import org.opendaylight.mdsal.common.api.CommitInfo;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.netconf.api.capability.Capability;
31 import org.opendaylight.netconf.api.capability.YangModuleCapability;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfStateBuilder;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema.Location;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema.Location.Enumeration;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.SchemaBuilder;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.model.api.Module;
43 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
44 import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
45 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
46 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
47 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
48 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
49 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
50 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceListener;
51 import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
52 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
53 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import com.google.common.collect.Sets;
58 import com.google.common.util.concurrent.FluentFuture;
59 import com.google.common.util.concurrent.Futures;
60 import com.google.inject.Inject;
61 import com.google.inject.name.Named;
62
63 import io.fd.honeycomb.translate.read.ReaderFactory;
64 import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
65
66 /**
67  * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
68  *
69  */
70 public class NetconfStateReaderFactory implements ReaderFactory {
71     private static final Logger LOG = LoggerFactory.getLogger(NetconfStateReaderFactory.class);
72     public static final InstanceIdentifier<NetconfState> NETCONF_STATE_ID = InstanceIdentifier
73             .create(NetconfState.class);
74     private static final String YANG_MODELS = "yang";
75
76     @Inject
77     @Named("device-databroker")
78     private DataBroker dataBroker;
79
80     @Override
81     public void init(ModifiableReaderRegistryBuilder registry) {
82         writeNetconfState();
83     }
84
85     /**
86      * Write {@link NetconfState} data to operational device datastore.
87      *
88      * @return result {@link Boolean}
89      */
90     public boolean writeNetconfState() {
91         Boolean res = false;
92         LOG.info("writting netconf state to oper datastore");
93         final SharedSchemaRepository schemaRepo = new SharedSchemaRepository("honeynode-simulator");
94         final Set<Capability> capabilities = parseSchemasToModuleCapabilities(schemaRepo);
95         final Set<Capability> transformedCapabilities = Sets.newHashSet(capabilities);
96         DummyMonitoringService monitor = new DummyMonitoringService(transformedCapabilities);
97         List<Schema> schemaList = new ArrayList<Schema>();
98         List<Location> locationList = new ArrayList<Location>();
99         Location location = new Location(Enumeration.NETCONF);
100         locationList.add(location);
101         Schema schematobuild = null;
102         for (final Schema schema : monitor.getSchemas().getSchema()) {
103             schematobuild = new SchemaBuilder().setIdentifier(schema.getIdentifier())
104                     .setNamespace(schema.getNamespace()).setVersion(schema.getVersion()).setFormat(Yang.class)
105                     .setLocation(locationList).build();
106             schemaList.add(schematobuild);
107         }
108         Schemas schemas = new SchemasBuilder().setSchema(schemaList).build();
109         NetconfState netconfState = new NetconfStateBuilder().setSchemas(schemas).build();
110         if (netconfState != null) {
111             WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction();
112             if (writeTx != null) {
113                 LOG.info("WriteTransaction is ok, copy device info to oper datastore");
114                 writeTx.put(LogicalDatastoreType.OPERATIONAL, NETCONF_STATE_ID, netconfState);
115                  @NonNull
116                  FluentFuture<? extends @NonNull CommitInfo> future = writeTx.commit();
117                 try {
118                     Futures.getChecked(future, ExecutionException.class);
119                     LOG.info("netconf state writed to oper datastore");
120                     res = true;
121                 } catch (ExecutionException e) {
122                     LOG.error("Failed to write netconf state to oper datastore");
123                 }
124             } else {
125                 LOG.error("WriteTransaction object is null");
126             }
127         } else {
128             LOG.error("device data operation gets from xml file is null !");
129         }
130         return res;
131     }
132
133     private Set<Capability> parseSchemasToModuleCapabilities(final SharedSchemaRepository consumer) {
134         final Set<SourceIdentifier> loadedSources = Sets.newHashSet();
135         consumer.registerSchemaSourceListener(TextToASTTransformer.create(consumer, consumer));
136         consumer.registerSchemaSourceListener(new SchemaSourceListener() {
137             @Override
138             public void schemaSourceEncountered(final SchemaSourceRepresentation schemaSourceRepresentation) {
139             }
140
141             @Override
142             public void schemaSourceRegistered(final Iterable<PotentialSchemaSource<?>> potentialSchemaSources) {
143                 for (final PotentialSchemaSource<?> potentialSchemaSource : potentialSchemaSources) {
144                     loadedSources.add(potentialSchemaSource.getSourceIdentifier());
145                 }
146             }
147
148             @Override
149             public void schemaSourceUnregistered(final PotentialSchemaSource<?> potentialSchemaSource) {
150             }
151         });
152         LOG.info("Loading models from directory.");
153         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
154         File models = new File(classLoader.getResource(YANG_MODELS).getFile());
155         if (models.exists() && models.isDirectory()) {
156             LOG.info("folder '{}' exists !", models.getAbsolutePath());
157             final FilesystemSchemaSourceCache<YangTextSchemaSource> cache = new FilesystemSchemaSourceCache<>(consumer,
158                     YangTextSchemaSource.class, models);
159             consumer.registerSchemaSourceListener(cache);
160         } else {
161             LOG.warn("folder '{}' not exists !", models.getAbsolutePath());
162             LOG.info("Custom module loading skipped.");
163         }
164         SchemaContext schemaContext;
165         try {
166             // necessary for creating mdsal data stores and operations
167             schemaContext = consumer.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT)
168                     .createSchemaContext(loadedSources).get();
169         } catch (final InterruptedException | ExecutionException e) {
170             throw new RuntimeException("Cannot parse schema context", e);
171         }
172
173         final Set<Capability> capabilities = Sets.newHashSet();
174
175         for (final Module module : schemaContext.getModules()) {
176             for (final Module subModule : module.getSubmodules()) {
177                 addModuleCapability(consumer, capabilities, subModule);
178             }
179             addModuleCapability(consumer, capabilities, module);
180         }
181         return capabilities;
182     }
183
184     private static void addModuleCapability(final SharedSchemaRepository consumer, final Set<Capability> capabilities,
185             final Module module) {
186         final SourceIdentifier moduleSourceIdentifier = RevisionSourceIdentifier.create(module.getName(),
187                 module.getRevision());
188         try {
189             final String moduleContent = new String(
190                     consumer.getSchemaSource(moduleSourceIdentifier, YangTextSchemaSource.class).get().read());
191             capabilities.add(new YangModuleCapability(module, moduleContent));
192             // IOException would be thrown in creating SchemaContext already
193         } catch (ExecutionException | InterruptedException | IOException e) {
194             LOG.warn("Cannot retrieve schema source for module {} from schema repository",
195                     moduleSourceIdentifier.toString(), e);
196         }
197     }
198
199 }