update deprecated transform and addCallback methods
[groupbasedpolicy.git] / sxp-integration / ip-sgt-distribution-service / src / main / java / org / opendaylight / groupbasedpolicy / ip / sgt / distribution / service / impl / IpSgtDistributionServiceImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.ip.sgt.distribution.service.impl;
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ArrayListMultimap;
13 import com.google.common.collect.Multimap;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import com.google.common.util.concurrent.SettableFuture;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import java.util.concurrent.Future;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.sxp.util.time.TimeConv;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.IpSgtDistributionService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.RemoveIpSgtBindingFromPeerInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.SendIpSgtBindingToPeerInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.Binding;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.binding.PeerNode;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeInputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.SxpControllerService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.peer.sequence.fields.PeerSequenceBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.protocol.rev141002.NodeId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
56 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
57 import org.opendaylight.yangtools.yang.common.RpcResult;
58 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 public class IpSgtDistributionServiceImpl implements AutoCloseable, IpSgtDistributionService {
63
64     private static final Logger LOG = LoggerFactory.getLogger(IpSgtDistributionServiceImpl.class);
65     public static final String SXP_NODE_DESCRIPTION = "ODL-GBP SXP node";
66     public static final String SXP_TOPOLOGY_ID = "sxp";
67     private final String SXP_NODE_ID;
68     private DataBroker dataBroker;
69     private IpAddress sourceIp;
70     private SxpCapableNodeListener nodeCollector;
71
72     public IpSgtDistributionServiceImpl(DataBroker dataBroker, SxpControllerService sxpService, IpAddress sourceIp) {
73         this.dataBroker = Preconditions.checkNotNull(dataBroker);
74         this.sourceIp = Preconditions.checkNotNull(sourceIp);
75         Preconditions.checkNotNull(sxpService);
76
77         if (sourceIp.getIpv4Address() != null) {
78             SXP_NODE_ID = sourceIp.getIpv4Address().getValue();
79         } else {
80             SXP_NODE_ID = sourceIp.getIpv6Address().getValue();
81         }
82         createSxpNode(sxpService);
83         nodeCollector = new SxpCapableNodeListener(dataBroker, SXP_NODE_ID);
84
85     }
86
87     private void createSxpNode(SxpControllerService sxpService) {
88         AddNodeInput addNodeInput = new AddNodeInputBuilder().setNodeId(new NodeId(SXP_NODE_ID))
89                 .setSourceIp(sourceIp)
90                 .setDescription(SXP_NODE_DESCRIPTION)
91                 .build();
92         Future<RpcResult<AddNodeOutput>> addNodeResult = sxpService.addNode(addNodeInput);
93         try {
94             if (! addNodeResult.get().getResult().isResult()) {
95                 LOG.error("RPC add-node wasn't successfull");
96             }
97         } catch (Exception e) {
98             LOG.error("RPC add-node wasn't successfull");
99         }
100     }
101
102     @Override
103     public Future<RpcResult<Void>> sendIpSgtBindingToPeer(SendIpSgtBindingToPeerInput input) {
104         Map<String, Multimap<Sgt, IpPrefix>> bindingsMap = new HashMap<>();
105         boolean success = true;
106         for (Binding binding : input.getBinding()) {
107             success = transformChanges(binding, bindingsMap);
108             if (! success) {
109                 break;
110             }
111         }
112         if (! success) {
113             return Futures.immediateCheckedFuture(RpcResultBuilder.<Void>failed().build());
114         }
115         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
116         bindingsMap.entrySet().forEach(bindingEntries -> {
117             String domainId = bindingEntries.getKey();
118             bindingEntries.getValue().entries().forEach(binding -> writeBinding(binding, domainId, wtx));
119         });
120         ListenableFuture<Void> submit = wtx.submit();
121         SettableFuture<RpcResult<Void>> future = SettableFuture.create();
122         Futures.addCallback(submit, new FutureCallback<Void>() {
123
124             @Override
125             public void onSuccess(Void result) {
126                 future.set(RpcResultBuilder.<Void>success().build());
127             }
128
129             @Override
130             public void onFailure(Throwable t) {
131                 future.set(RpcResultBuilder.<Void>failed().build());
132
133             }
134
135         }, MoreExecutors.directExecutor());
136         return future;
137     }
138
139     private boolean transformChanges(Binding binding, Map<String, Multimap<Sgt, IpPrefix>> bindingsMap) {
140         Sgt sgt = binding.getSgt();
141         IpPrefix addr = binding.getIpPrefix();
142         for (PeerNode peer : binding.getPeerNode()) {
143             String domainId = nodeCollector.getDomainIdForPeer((InstanceIdentifier<Node>) peer.getNodeIid());
144             if (domainId == null) {
145                 LOG.debug("Node {} is not SXP capable", peer.getNodeIid());
146                 return false;
147             }
148             Multimap<Sgt, IpPrefix> domainBindingMap = bindingsMap.get(domainId);
149             if (domainBindingMap == null) {
150                 domainBindingMap = ArrayListMultimap.create();
151                 bindingsMap.put(domainId, domainBindingMap);
152             }
153             domainBindingMap.get(sgt).add(addr);
154         }
155         return true;
156     }
157
158     private void writeBinding(Entry<Sgt, IpPrefix> binding, String domainId, WriteTransaction wtx) {
159         IpPrefix addr = binding.getValue();
160         InstanceIdentifier<MasterDatabaseBinding> iid = bindingIid(domainId, addr);
161         MasterDatabaseBinding newBinding = createBinding(binding);
162         wtx.put(LogicalDatastoreType.CONFIGURATION, iid, newBinding);
163     }
164
165     private InstanceIdentifier<MasterDatabaseBinding> bindingIid(String domainId, IpPrefix prefix) {
166         return InstanceIdentifier.builder(NetworkTopology.class)
167                 .child(Topology.class, new TopologyKey(new TopologyId(SXP_TOPOLOGY_ID)))
168                 .child(Node.class,
169                         new NodeKey(
170                                 new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId(
171                                         SXP_NODE_ID)))
172                 .augmentation(SxpNodeIdentity.class)
173                 .child(SxpDomains.class)
174                 .child(SxpDomain.class, new SxpDomainKey(domainId))
175                 .child(MasterDatabase.class)
176                 .child(MasterDatabaseBinding.class, new MasterDatabaseBindingKey(prefix))
177                 .build();
178     }
179
180     private MasterDatabaseBinding createBinding(Entry<Sgt, IpPrefix> binding) {
181         final DateAndTime nowDateTime = TimeConv.toDt(System.currentTimeMillis());
182         return new MasterDatabaseBindingBuilder()
183                 .setIpPrefix(binding.getValue())
184                 .setSecurityGroupTag(binding.getKey())
185                 .setPeerSequence(new PeerSequenceBuilder().build())
186                 .setTimestamp(nowDateTime)
187                 .build();
188     }
189
190     @Override
191     public Future<RpcResult<Void>> removeIpSgtBindingFromPeer(RemoveIpSgtBindingFromPeerInput input) {
192         Map<String, Multimap<Sgt, IpPrefix>> bindingsMap = new HashMap<>();
193         boolean success = true;
194         for (Binding binding : input.getBinding()) {
195             success = transformChanges(binding, bindingsMap);
196             if (! success) {
197                 break;
198             }
199         }
200         if (! success) {
201             return Futures.immediateCheckedFuture(RpcResultBuilder.<Void>failed().build());
202         }
203         WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
204         bindingsMap.entrySet().forEach(bindingEntries -> {
205             String domainId = bindingEntries.getKey();
206             bindingEntries.getValue().entries().forEach(binding -> removeBinding(binding, domainId, wtx));
207         });
208         ListenableFuture<Void> submit = wtx.submit();
209         SettableFuture<RpcResult<Void>> future = SettableFuture.create();
210         Futures.addCallback(submit, new FutureCallback<Void>() {
211
212             @Override
213             public void onSuccess(Void result) {
214                 future.set(RpcResultBuilder.<Void>success().build());
215             }
216
217             @Override
218             public void onFailure(Throwable t) {
219                 future.set(RpcResultBuilder.<Void>failed().build());
220
221             }
222
223         }, MoreExecutors.directExecutor());
224         return future;
225     }
226
227     private void removeBinding(Entry<Sgt, IpPrefix> binding, String domainId, WriteTransaction wtx) {
228         IpPrefix addr = binding.getValue();
229         InstanceIdentifier<MasterDatabaseBinding> iid = bindingIid(domainId, addr);
230         wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
231     }
232
233     @Override
234     public void close() throws Exception {
235         nodeCollector.close();
236     }
237
238 }