2 * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.restconf.nb.rfc8040.rests.transactions;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.util.concurrent.FluentFuture;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.MoreExecutors;
17 import com.google.common.util.concurrent.SettableFuture;
18 import java.util.List;
19 import java.util.Optional;
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.opendaylight.mdsal.common.api.CommitInfo;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.mdsal.common.api.ReadFailedException;
24 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
25 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
26 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
27 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
33 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * Implementation of RESTCONF operations on top of a raw NETCONF backend.
41 * @see NetconfDataTreeService
43 public final class NetconfRestconfStrategy extends RestconfStrategy {
44 private static final Logger LOG = LoggerFactory.getLogger(NetconfRestconfStrategy.class);
46 private final NetconfDataTreeService netconfService;
48 private List<ListenableFuture<? extends DOMRpcResult>> resultsFutures;
50 public NetconfRestconfStrategy(final NetconfDataTreeService netconfService) {
51 this.netconfService = requireNonNull(netconfService);
55 public void prepareReadWriteExecution() {
56 resultsFutures = netconfService.lock();
60 public void cancel() {
61 netconfService.discardChanges();
62 netconfService.unlock();
66 public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store,
67 final YangInstanceIdentifier path) {
70 return netconfService.getConfig(path);
72 return netconfService.get(path);
74 LOG.info("Unknown datastore type: {}.", store);
75 throw new IllegalArgumentException(String.format(
76 "%s, Cannot read data %s for %s datastore, unknown datastore type",
77 netconfService.getDeviceId(), path, store));
82 public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
83 return remapException(read(store, path))
84 .transform(optionalNode -> optionalNode != null && optionalNode.isPresent(),
85 MoreExecutors.directExecutor());
89 public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
90 resultsFutures.add(netconfService.delete(store, path));
94 public void remove(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
95 resultsFutures.add(netconfService.remove(store, path));
99 public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path,
100 final NormalizedNode<?, ?> data) {
101 resultsFutures.add(netconfService.merge(store, path, data, Optional.empty()));
105 public void create(final LogicalDatastoreType store, final YangInstanceIdentifier path,
106 final NormalizedNode<?, ?> data, final SchemaContext schemaContext) {
107 if (data instanceof MapNode || data instanceof LeafSetNode) {
108 final NormalizedNode<?, ?> emptySubTree = ImmutableNodes.fromInstanceId(schemaContext, path);
109 merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(emptySubTree.getIdentifier()),
112 for (final NormalizedNode<?, ?> child : ((NormalizedNodeContainer<?, ?, ?>) data).getValue()) {
113 final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
114 resultsFutures.add(netconfService.create(store, childPath, child, Optional.empty()));
117 resultsFutures.add(netconfService.create(store, path, data, Optional.empty()));
122 public void replace(final LogicalDatastoreType store, final YangInstanceIdentifier path,
123 final NormalizedNode<?, ?> data, final SchemaContext schemaContext) {
124 if (data instanceof MapNode || data instanceof LeafSetNode) {
125 final NormalizedNode<?, ?> emptySubTree = ImmutableNodes.fromInstanceId(schemaContext, path);
126 merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(emptySubTree.getIdentifier()),
129 for (final NormalizedNode<?, ?> child : ((NormalizedNodeContainer<?, ?, ?>) data).getValue()) {
130 final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
131 resultsFutures.add(netconfService.replace(store, childPath, child, Optional.empty()));
134 resultsFutures.add(netconfService.replace(store, path, data, Optional.empty()));
139 public FluentFuture<? extends @NonNull CommitInfo> commit() {
140 return FluentFuture.from(netconfService.commit(resultsFutures));
144 * As we are not using any transactions here, always return null.
147 public DOMTransactionChain getTransactionChain() {
152 * As we are not using any transactions here, always return null.
155 public TransactionChainHandler getTransactionChainHandler() {
159 private static <T> FluentFuture<T> remapException(final ListenableFuture<T> input) {
160 final SettableFuture<T> ret = SettableFuture.create();
161 Futures.addCallback(input, new FutureCallback<T>() {
164 public void onSuccess(final T result) {
169 public void onFailure(final Throwable cause) {
170 ret.setException(cause instanceof ReadFailedException ? cause
171 : new ReadFailedException("NETCONF operation failed", cause));
173 }, MoreExecutors.directExecutor());
174 return FluentFuture.from(ret);