1 package org.opendaylight.controller.sal.connect.netconf;
3 import java.util.Collections;
6 import java.util.Map.Entry;
9 import org.eclipse.xtext.xbase.lib.IterableExtensions;
10 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
11 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
12 import org.opendaylight.yangtools.yang.common.QName;
13 import org.opendaylight.yangtools.yang.common.RpcResult;
14 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
15 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
16 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
17 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
18 import org.opendaylight.yangtools.yang.data.api.Node;
19 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
20 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
22 import com.google.common.base.Optional;
23 import com.google.common.base.Preconditions;
24 import com.google.common.collect.Collections2;
25 import com.google.common.collect.ImmutableList;
26 import com.google.common.collect.Iterables;
27 import com.google.common.collect.Lists;
29 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.*;
31 public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<InstanceIdentifier, CompositeNode> {
33 private NetconfDevice device;
34 private final DataModification<InstanceIdentifier, CompositeNode> modification;
35 private boolean candidateSupported = true;
37 public NetconfDeviceTwoPhaseCommitTransaction(NetconfDevice device,
38 DataModification<InstanceIdentifier, CompositeNode> modification) {
41 this.modification = modification;
44 public void prepare() {
45 for (InstanceIdentifier toRemove : modification.getRemovedConfigurationData()) {
48 for(Entry<InstanceIdentifier, CompositeNode> toUpdate : modification.getUpdatedConfigurationData().entrySet()) {
49 sendMerge(toUpdate.getKey(),toUpdate.getValue());
54 private void sendMerge(InstanceIdentifier key, CompositeNode value) {
55 sendEditRpc(createEditStructure(key, Optional.<String>absent(), Optional.of(value)));
58 private void sendRemove(InstanceIdentifier toRemove) {
59 sendEditRpc(createEditStructure(toRemove, Optional.of("remove"), Optional.<CompositeNode> absent()));
62 private void sendEditRpc(CompositeNode editStructure) {
63 CompositeNodeBuilder<ImmutableCompositeNode> builder = configurationRpcBuilder();
64 builder.setQName(NETCONF_EDIT_CONFIG_QNAME);
65 builder.add(editStructure);
67 RpcResult<CompositeNode> rpcResult = device.invokeRpc(NETCONF_EDIT_CONFIG_QNAME, builder.toInstance());
68 Preconditions.checkState(rpcResult.isSuccessful(),"Rpc Result was unsuccessful");
72 private CompositeNodeBuilder<ImmutableCompositeNode> configurationRpcBuilder() {
73 CompositeNodeBuilder<ImmutableCompositeNode> ret = ImmutableCompositeNode.builder();
76 if(candidateSupported) {
77 targetNode = ImmutableCompositeNode.create(NETCONF_CANDIDATE_QNAME, ImmutableList.<Node<?>>of());
79 targetNode = ImmutableCompositeNode.create(NETCONF_RUNNING_QNAME, ImmutableList.<Node<?>>of());
81 Node<?> targetWrapperNode = ImmutableCompositeNode.create(NETCONF_TARGET_QNAME, ImmutableList.<Node<?>>of(targetNode));
82 ret.add(targetWrapperNode);
86 private CompositeNode createEditStructure(InstanceIdentifier dataPath, Optional<String> action,
87 Optional<CompositeNode> lastChildOverride) {
88 List<PathArgument> path = dataPath.getPath();
89 List<PathArgument> reversed = Lists.reverse(path);
90 CompositeNode previous = null;
91 boolean isLast = true;
92 for (PathArgument arg : reversed) {
93 CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
94 builder.setQName(arg.getNodeType());
95 Map<QName, Object> predicates = Collections.emptyMap();
96 if (arg instanceof NodeIdentifierWithPredicates) {
97 predicates = ((NodeIdentifierWithPredicates) arg).getKeyValues();
99 for (Entry<QName, Object> entry : predicates.entrySet()) {
100 builder.addLeaf(entry.getKey(), entry.getValue());
104 if (action.isPresent()) {
105 builder.setAttribute(NETCONF_ACTION_QNAME, action.get());
107 if (lastChildOverride.isPresent()) {
108 List<Node<?>> children = lastChildOverride.get().getChildren();
109 for(Node<?> child : children) {
110 if(!predicates.containsKey(child.getKey())) {
117 builder.add(previous);
119 previous = builder.toInstance();
122 return ImmutableCompositeNode.create(NETCONF_CONFIG_QNAME, ImmutableList.<Node<?>>of(previous));
126 public RpcResult<Void> finish() throws IllegalStateException {
127 CompositeNodeBuilder<ImmutableCompositeNode> commitInput = ImmutableCompositeNode.builder();
128 commitInput.setQName(NETCONF_COMMIT_QNAME);
129 RpcResult<?> rpcResult = device.invokeRpc(NetconfMapping.NETCONF_COMMIT_QNAME, commitInput.toInstance());
130 return (RpcResult<Void>) rpcResult;
134 public DataModification<InstanceIdentifier, CompositeNode> getModification() {
135 return this.modification;
139 public RpcResult<Void> rollback() throws IllegalStateException {
140 // TODO Auto-generated method stub