Updated implementation of Netconf, fixed DOM Mountpoint
[controller.git] / opendaylight / md-sal / sal-netconf-connector / src / main / java / org / opendaylight / controller / sal / connect / netconf / NetconfDeviceTwoPhaseCommitTransaction.java
1 package org.opendaylight.controller.sal.connect.netconf;
2
3 import java.util.List;
4 import java.util.Map.Entry;
5 import java.util.Set;
6
7 import org.eclipse.xtext.xbase.lib.IterableExtensions;
8 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
9 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
10 import org.opendaylight.yangtools.yang.common.QName;
11 import org.opendaylight.yangtools.yang.common.RpcResult;
12 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
13 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
14 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
15 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
16 import org.opendaylight.yangtools.yang.data.api.Node;
17 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
18 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
19
20 import com.google.common.base.Optional;
21 import com.google.common.base.Preconditions;
22 import com.google.common.collect.Collections2;
23 import com.google.common.collect.ImmutableList;
24 import com.google.common.collect.Iterables;
25 import com.google.common.collect.Lists;
26
27 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.*;
28
29 public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<InstanceIdentifier, CompositeNode> {
30
31     private NetconfDevice device;
32     private final DataModification<InstanceIdentifier, CompositeNode> modification;
33     private boolean candidateSupported = true;
34
35     public NetconfDeviceTwoPhaseCommitTransaction(NetconfDevice device,
36             DataModification<InstanceIdentifier, CompositeNode> modification) {
37         super();
38         this.device = device;
39         this.modification = modification;
40     }
41
42     public void prepare() {
43         for (InstanceIdentifier toRemove : modification.getRemovedConfigurationData()) {
44             sendRemove(toRemove);
45         }
46         for(Entry<InstanceIdentifier, CompositeNode> toUpdate : modification.getUpdatedConfigurationData().entrySet()) {
47             sendMerge(toUpdate.getKey(),toUpdate.getValue());
48         }
49
50     }
51
52     private void sendMerge(InstanceIdentifier key, CompositeNode value) {
53         sendEditRpc(createEditStructure(key, Optional.<String>absent(), Optional.of(value)));
54     }
55
56     private void sendRemove(InstanceIdentifier toRemove) {
57         sendEditRpc(createEditStructure(toRemove, Optional.of("remove"), Optional.<CompositeNode> absent()));
58     }
59
60     private void sendEditRpc(CompositeNode editStructure) {
61         CompositeNodeBuilder<ImmutableCompositeNode> builder = configurationRpcBuilder();
62         builder.setQName(NETCONF_EDIT_CONFIG_QNAME);
63         builder.add(editStructure);
64         
65         RpcResult<CompositeNode> rpcResult = device.invokeRpc(NETCONF_EDIT_CONFIG_QNAME, builder.toInstance());
66         Preconditions.checkState(rpcResult.isSuccessful(),"Rpc Result was unsuccessful");
67         
68     }
69
70     private CompositeNodeBuilder<ImmutableCompositeNode> configurationRpcBuilder() {
71         CompositeNodeBuilder<ImmutableCompositeNode> ret = ImmutableCompositeNode.builder();
72         
73         Node<?> targetNode;
74         if(candidateSupported) {
75             targetNode = ImmutableCompositeNode.create(NETCONF_CANDIDATE_QNAME, ImmutableList.<Node<?>>of());
76         } else {
77             targetNode = ImmutableCompositeNode.create(NETCONF_RUNNING_QNAME, ImmutableList.<Node<?>>of());
78         }
79         Node<?> targetWrapperNode = ImmutableCompositeNode.create(NETCONF_TARGET_QNAME, ImmutableList.<Node<?>>of(targetNode));
80         ret.add(targetWrapperNode);
81         return ret;
82     }
83
84     private CompositeNode createEditStructure(InstanceIdentifier dataPath, Optional<String> action,
85             Optional<CompositeNode> lastChildOverride) {
86         List<PathArgument> path = dataPath.getPath();
87         List<PathArgument> reversed = Lists.reverse(path);
88         CompositeNode previous = null;
89         boolean isLast = true;
90         for (PathArgument arg : reversed) {
91             CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
92             builder.setQName(arg.getNodeType());
93
94             if (arg instanceof NodeIdentifierWithPredicates) {
95                 for (Entry<QName, Object> entry : ((NodeIdentifierWithPredicates) arg).getKeyValues().entrySet()) {
96                     builder.addLeaf(entry.getKey(), entry.getValue());
97                 }
98             }
99             if (isLast) {
100                 if (action.isPresent()) {
101                     builder.setAttribute(NETCONF_ACTION_QNAME, action.get());
102                 }
103                 if (lastChildOverride.isPresent()) {
104                     List<Node<?>> children = lastChildOverride.get().getChildren();
105                     builder.addAll(children);
106                 }
107             } else {
108                 builder.add(previous);
109             }
110             previous = builder.toInstance();
111             isLast = false;
112         }
113         return ImmutableCompositeNode.create(NETCONF_CONFIG_QNAME, ImmutableList.<Node<?>>of(previous));
114     }
115
116     @Override
117     public RpcResult<Void> finish() throws IllegalStateException {
118         CompositeNodeBuilder<ImmutableCompositeNode> commitInput = ImmutableCompositeNode.builder();
119         commitInput.setQName(NETCONF_COMMIT_QNAME);
120         RpcResult<?> rpcResult = device.invokeRpc(NetconfMapping.NETCONF_COMMIT_QNAME, commitInput.toInstance());
121         return (RpcResult<Void>) rpcResult;
122     }
123
124     @Override
125     public DataModification<InstanceIdentifier, CompositeNode> getModification() {
126         return this.modification;
127     }
128
129     @Override
130     public RpcResult<Void> rollback() throws IllegalStateException {
131         // TODO Auto-generated method stub
132         return null;
133     }
134 }