2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netconf.test.tool;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.util.concurrent.MoreExecutors;
13 import java.util.EnumMap;
14 import java.util.HashMap;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.ExecutorService;
19 import java.util.function.Consumer;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
22 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
23 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
24 import org.opendaylight.mdsal.dom.api.DOMSchemaService.YangTextSourceExtension;
25 import org.opendaylight.mdsal.dom.broker.SerializedDOMDataBroker;
26 import org.opendaylight.mdsal.dom.spi.store.DOMStore;
27 import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataStoreFactory;
28 import org.opendaylight.netconf.server.api.SessionIdProvider;
29 import org.opendaylight.netconf.server.api.monitoring.Capability;
30 import org.opendaylight.netconf.server.api.monitoring.CapabilityListener;
31 import org.opendaylight.netconf.server.api.operations.NetconfOperation;
32 import org.opendaylight.netconf.server.api.operations.NetconfOperationService;
33 import org.opendaylight.netconf.server.api.operations.NetconfOperationServiceFactory;
34 import org.opendaylight.netconf.server.mdsal.CurrentSchemaContext;
35 import org.opendaylight.netconf.server.mdsal.TransactionProvider;
36 import org.opendaylight.netconf.server.mdsal.operations.Commit;
37 import org.opendaylight.netconf.server.mdsal.operations.DiscardChanges;
38 import org.opendaylight.netconf.server.mdsal.operations.EditConfig;
39 import org.opendaylight.netconf.server.mdsal.operations.Get;
40 import org.opendaylight.netconf.server.mdsal.operations.GetConfig;
41 import org.opendaylight.netconf.server.mdsal.operations.Lock;
42 import org.opendaylight.netconf.server.mdsal.operations.Unlock;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.SessionIdType;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
48 import org.opendaylight.yangtools.concepts.Registration;
49 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
50 import org.opendaylight.yangtools.yang.common.QName;
51 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
53 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
54 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
55 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
56 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
57 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
58 import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode;
59 import org.opendaylight.yangtools.yang.data.api.schema.builder.CollectionNodeBuilder;
60 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
61 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
62 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
66 class MdsalOperationProvider implements NetconfOperationServiceFactory {
67 private static final Logger LOG = LoggerFactory.getLogger(MdsalOperationProvider.class);
69 private final Set<Capability> caps;
70 private final EffectiveModelContext schemaContext;
71 private final YangTextSourceExtension sourceProvider;
73 MdsalOperationProvider(final SessionIdProvider idProvider,
74 final Set<Capability> caps,
75 final EffectiveModelContext schemaContext,
76 final YangTextSourceExtension sourceProvider) {
78 this.schemaContext = schemaContext;
79 this.sourceProvider = sourceProvider;
83 public Set<Capability> getCapabilities() {
88 public Registration registerCapabilityListener(final CapabilityListener listener) {
89 listener.onCapabilitiesChanged(caps, Set.of());
94 public NetconfOperationService createService(final SessionIdType sessionId) {
95 return new MdsalOperationService(sessionId, schemaContext, caps, sourceProvider);
98 static class MdsalOperationService implements NetconfOperationService {
99 private final SessionIdType currentSessionId;
100 private final EffectiveModelContext schemaContext;
101 private final Set<Capability> caps;
102 private final DOMSchemaService schemaService;
103 private final DOMDataBroker dataBroker;
104 private final YangTextSourceExtension sourceProvider;
106 MdsalOperationService(final SessionIdType currentSessionId, final EffectiveModelContext schemaContext,
107 final Set<Capability> caps, final YangTextSourceExtension sourceProvider) {
108 this.currentSessionId = requireNonNull(currentSessionId);
109 this.schemaContext = schemaContext;
111 this.sourceProvider = sourceProvider;
112 schemaService = createSchemaService();
114 dataBroker = createDataStore(schemaService, currentSessionId);
118 public Set<NetconfOperation> getNetconfOperations() {
119 ContainerNode netconf = createNetconfState();
121 final DOMDataTreeWriteTransaction tx = dataBroker.newWriteOnlyTransaction();
122 tx.put(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.of(NetconfState.QNAME), netconf);
126 LOG.debug("Netconf state updated successfully");
127 } catch (InterruptedException | ExecutionException e) {
128 LOG.warn("Unable to update netconf state", e);
131 TransactionProvider transactionProvider = new TransactionProvider(dataBroker, currentSessionId);
132 CurrentSchemaContext currentSchemaContext = CurrentSchemaContext.create(schemaService, sourceProvider);
134 final Get get = new Get(currentSessionId, currentSchemaContext, transactionProvider);
135 final EditConfig editConfig = new EditConfig(currentSessionId, currentSchemaContext, transactionProvider);
136 final GetConfig getConfig = new GetConfig(currentSessionId, currentSchemaContext, transactionProvider);
137 final Commit commit = new Commit(currentSessionId, transactionProvider);
138 final Lock lock = new Lock(currentSessionId);
139 final Unlock unLock = new Unlock(currentSessionId);
140 final DiscardChanges discardChanges = new DiscardChanges(currentSessionId, transactionProvider);
142 return Set.of(get, getConfig, editConfig, commit, lock, unLock, discardChanges);
146 public void close() {
150 private ContainerNode createNetconfState() {
151 final DummyMonitoringService monitor = new DummyMonitoringService(caps);
152 final QName identifier = QName.create(Schema.QNAME, "identifier");
153 final QName version = QName.create(Schema.QNAME, "version");
154 final QName format = QName.create(Schema.QNAME, "format");
155 final QName location = QName.create(Schema.QNAME, "location");
156 final QName namespace = QName.create(Schema.QNAME, "namespace");
158 CollectionNodeBuilder<MapEntryNode, SystemMapNode> schemaMapEntryNodeMapNodeCollectionNodeBuilder =
159 Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(Schema.QNAME));
160 LeafSetNode<String> locationLeafSet = Builders.<String>leafSetBuilder()
161 .withNodeIdentifier(new NodeIdentifier(location))
162 .withChild(Builders.<String>leafSetEntryBuilder()
163 .withNodeIdentifier(new NodeWithValue<>(location, "NETCONF"))
164 .withValue("NETCONF")
168 Map<QName, Object> keyValues = new HashMap<>();
169 for (final Schema schema : monitor.getSchemas().nonnullSchema().values()) {
170 keyValues.put(identifier, schema.getIdentifier());
171 keyValues.put(version, schema.getVersion());
172 keyValues.put(format, Yang.QNAME);
174 schemaMapEntryNodeMapNodeCollectionNodeBuilder.withChild(Builders.mapEntryBuilder()
175 .withNodeIdentifier(NodeIdentifierWithPredicates.of(Schema.QNAME, keyValues))
176 .withChild(ImmutableNodes.leafNode(identifier, schema.getIdentifier()))
177 .withChild(ImmutableNodes.leafNode(version, schema.getVersion()))
178 .withChild(ImmutableNodes.leafNode(format, Yang.QNAME))
179 .withChild(ImmutableNodes.leafNode(namespace, schema.getNamespace().getValue()))
180 .withChild(locationLeafSet)
184 return Builders.containerBuilder()
185 .withNodeIdentifier(new NodeIdentifier(NetconfState.QNAME))
186 .withChild(Builders.containerBuilder()
187 .withNodeIdentifier(new NodeIdentifier(Schemas.QNAME))
188 .withChild(schemaMapEntryNodeMapNodeCollectionNodeBuilder.build())
193 private static DOMDataBroker createDataStore(final DOMSchemaService schemaService,
194 final SessionIdType sessionId) {
195 LOG.debug("Session {}: Creating data stores for simulated device", sessionId.getValue());
196 final DOMStore operStore = InMemoryDOMDataStoreFactory.create("DOM-OPER", schemaService);
197 final DOMStore configStore = InMemoryDOMDataStoreFactory.create("DOM-CFG", schemaService);
199 ExecutorService listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(16, 16,
200 "CommitFutures", MdsalOperationProvider.class);
202 final var datastores = new EnumMap<LogicalDatastoreType, DOMStore>(LogicalDatastoreType.class);
203 datastores.put(LogicalDatastoreType.CONFIGURATION, configStore);
204 datastores.put(LogicalDatastoreType.OPERATIONAL, operStore);
206 return new SerializedDOMDataBroker(datastores, MoreExecutors.listeningDecorator(listenableFutureExecutor));
209 private DOMSchemaService createSchemaService() {
210 return new DOMSchemaService() {
212 public EffectiveModelContext getGlobalContext() {
213 return schemaContext;
217 public Registration registerSchemaContextListener(final Consumer<EffectiveModelContext> listener) {
218 listener.accept(getGlobalContext());