bd2fc17e4476e917c1b1a0f14141b545ccab8b18
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / rpc / ItmManagerRpcService.java
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. 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 package org.opendaylight.genius.itm.rpc;
9
10 import com.google.common.base.Objects;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import com.google.common.util.concurrent.SettableFuture;
17 import java.math.BigInteger;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.concurrent.Future;
25 import java.util.stream.Collectors;
26 import javax.annotation.PostConstruct;
27 import javax.annotation.PreDestroy;
28 import javax.inject.Inject;
29 import javax.inject.Singleton;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
34 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
35 import org.opendaylight.genius.infra.FutureRpcResults;
36 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
37 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
38 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
39 import org.opendaylight.genius.itm.globals.ITMConstants;
40 import org.opendaylight.genius.itm.impl.ItmUtils;
41 import org.opendaylight.genius.mdsalutil.MDSALUtil;
42 import org.opendaylight.genius.mdsalutil.MatchInfo;
43 import org.opendaylight.genius.mdsalutil.NwConstants;
44 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
45 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoInput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutput;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutputBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdEnableOnTunnelInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.Computes;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.ComputesBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
117 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
118 import org.opendaylight.yangtools.yang.common.RpcError;
119 import org.opendaylight.yangtools.yang.common.RpcResult;
120 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
121 import org.slf4j.Logger;
122 import org.slf4j.LoggerFactory;
123
124 @Singleton
125 public class ItmManagerRpcService implements ItmRpcService {
126
127     private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
128     private final DataBroker dataBroker;
129     private final IMdsalApiManager mdsalManager;
130     private final DPNTEPsInfoCache dpnTEPsInfoCache;
131     private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
132     private final ItmConfig itmConfig;
133     private final SingleTransactionDataBroker singleTransactionDataBroker;
134
135     @Inject
136     public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
137             final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache) {
138         this.dataBroker = dataBroker;
139         this.mdsalManager = mdsalManager;
140         this.dpnTEPsInfoCache = dpnTEPsInfoCache;
141         this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(dataBroker, itmConfig, dpnTEPsInfoCache);
142         this.itmConfig = itmConfig;
143         this.singleTransactionDataBroker = new SingleTransactionDataBroker(dataBroker);
144     }
145
146     @PostConstruct
147     public void start() {
148         LOG.info("ItmManagerRpcService Started");
149     }
150
151     @PreDestroy
152     public void close() {
153         LOG.info("ItmManagerRpcService Closed");
154     }
155
156     @Override
157     public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
158         RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
159         BigInteger sourceDpn = input.getSourceDpid();
160         BigInteger destinationDpn = input.getDestinationDpid();
161         Optional<InternalTunnel> optTunnel = Optional.absent();
162
163         if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
164             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
165                                                          TunnelTypeLogicalGroup.class, dataBroker);
166             LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
167         }
168         if (!optTunnel.isPresent()) {
169             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
170         }
171         if (optTunnel.isPresent()) {
172             InternalTunnel tunnel = optTunnel.get();
173             GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
174             List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
175             if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
176                 output.setInterfaceName(tunnelInterfaces.get(0));
177                 resultBld = RpcResultBuilder.success();
178                 resultBld.withResult(output.build());
179             } else {
180                 resultBld = RpcResultBuilder.failed();
181             }
182
183         } else {
184             resultBld = RpcResultBuilder.failed();
185         }
186         return Futures.immediateFuture(resultBld.build());
187     }
188
189     @Override
190     public Future<RpcResult<GetEgressActionsForTunnelOutput>> getEgressActionsForTunnel(
191             GetEgressActionsForTunnelInput input) {
192         //TODO
193         return null;
194     }
195
196     @Override
197     public Future<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
198         //TODO
199         return null;
200     }
201
202     @Override
203     public Future<RpcResult<Void>> setBfdEnableOnTunnel(SetBfdEnableOnTunnelInput input) {
204         //TODO
205         return null;
206     }
207
208
209     @Override
210     public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
211             RemoveExternalTunnelEndpointInput input) {
212         //Ignore the Futures for now
213         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
214         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
215         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, meshedDpnList,
216                 input.getDestinationIp(), input.getTunnelType());
217         InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
218                 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
219         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
220         transaction.delete(LogicalDatastoreType.CONFIGURATION, extPath);
221         ListenableFuture<Void> futureCheck = transaction.submit();
222         Futures.addCallback(futureCheck, new FutureCallback<Void>() {
223
224             @Override public void onSuccess(Void voidInstance) {
225                 result.set(RpcResultBuilder.<Void>success().build());
226             }
227
228             @Override public void onFailure(Throwable error) {
229                 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
230                         + " in datastore and tunnel type " + input.getTunnelType();
231                 LOG.error("Unable to delete DcGatewayIp {} in datastore and tunnel type {}", input.getDestinationIp(),
232                         input.getTunnelType());
233                 result.set(RpcResultBuilder.<Void>failed()
234                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
235             }
236         });
237         return result;
238     }
239
240     @Override
241     public Future<RpcResult<Void>> removeExternalTunnelFromDpns(
242             RemoveExternalTunnelFromDpnsInput input) {
243         //Ignore the Futures for now
244         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
245         List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId()) ;
246         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, cfgDpnList,
247                 input.getDestinationIp(), input.getTunnelType());
248         result.set(RpcResultBuilder.<Void>success().build());
249         return result;
250     }
251
252     @Override
253     public Future<RpcResult<Void>> buildExternalTunnelFromDpns(
254             BuildExternalTunnelFromDpnsInput input) {
255         //Ignore the Futures for now
256         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
257         List<ListenableFuture<Void>> extTunnelResultList = externalTunnelAddWorker
258             .buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(), input.getDestinationIp(),input.getTunnelType());
259         for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
260             Futures.addCallback(extTunnelResult, new FutureCallback<Void>() {
261
262                 @Override
263                 public void onSuccess(Void voidInstance) {
264                     result.set(RpcResultBuilder.<Void>success().build());
265                 }
266
267                 @Override
268                 public void onFailure(Throwable error) {
269                     String msg = "Unable to create ext tunnel";
270                     LOG.error("create ext tunnel failed. {}.", msg, error);
271                     result.set(RpcResultBuilder.<Void>failed()
272                             .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
273                 }
274             });
275         }
276         return result;
277     }
278
279     @Override
280     public Future<RpcResult<Void>> addExternalTunnelEndpoint(
281             AddExternalTunnelEndpointInput input) {
282         // TODO Auto-generated method stub
283
284         //Ignore the Futures for now
285         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
286         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
287         externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList,
288                 input.getDestinationIp(), input.getTunnelType());
289         InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
290                 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
291         DcGatewayIp dcGatewayIp =
292                 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
293                         .setTunnnelType(input.getTunnelType()).build();
294         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
295         writeTransaction.put(LogicalDatastoreType.CONFIGURATION, extPath,dcGatewayIp, true);
296         ListenableFuture<Void> futureCheck = writeTransaction.submit();
297         Futures.addCallback(futureCheck, new FutureCallback<Void>() {
298
299             @Override public void onSuccess(Void voidInstance) {
300                 result.set(RpcResultBuilder.<Void>success().build());
301             }
302
303             @Override public void onFailure(Throwable error) {
304                 String msg =
305                         "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
306                                 + "tunnel type " + input.getTunnelType();
307
308                 LOG.error("Unable to create DcGatewayIp in datastore for ip {} and tunnel type {}",
309                         input.getDestinationIp() , input.getTunnelType());
310                 result.set(RpcResultBuilder.<Void>failed()
311                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
312             }
313         });
314         return result;
315     }
316
317     @Override
318     public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
319             GetExternalTunnelInterfaceNameInput input) {
320         SettableFuture.create();
321         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
322         String sourceNode = input.getSourceNode();
323         String dstNode = input.getDestinationNode();
324         ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
325         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
326                 ExternalTunnelList.class)
327                 .child(ExternalTunnel.class, externalTunnelKey);
328         ExternalTunnel exTunnel =
329                 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
330         if (exTunnel != null) {
331             GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
332             output.setInterfaceName(exTunnel.getTunnelInterfaceName());
333             resultBld = RpcResultBuilder.success();
334             resultBld.withResult(output.build());
335         } else {
336             resultBld = RpcResultBuilder.failed();
337         }
338
339         return Futures.immediateFuture(resultBld.build());
340     }
341
342     @Override
343     public Future<RpcResult<java.lang.Void>>
344         createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
345         LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
346                 input.getDpnId() , input.getServiceId(), input.getInstruction());
347         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
348         int serviceId = input.getServiceId() ;
349         final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
350
351         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
352                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5,
353                 String.format("%s:%d","ITM Flow Entry ",serviceId), 0, 0,
354                 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
355
356         ListenableFuture<Void> installFlowResult =
357                 mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
358         Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
359
360             @Override
361             public void onSuccess(Void voidInstance) {
362                 result.set(RpcResultBuilder.<Void>success().build());
363             }
364
365             @Override
366             public void onFailure(Throwable error) {
367                 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
368                 LOG.error("create terminating service actions failed. {}", msg, error);
369                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
370                         .build());
371             }
372         }, MoreExecutors.directExecutor());
373         // result.set(RpcResultBuilder.<Void>success().build());
374         return result;
375     }
376
377     @Override
378     public Future<RpcResult<java.lang.Void>>
379         removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
380         LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
381                 input.getDpnId(), input.getServiceId());
382         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
383         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
384                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5,
385                 String.format("%s:%d","ITM Flow Entry ",input.getServiceId()), 0, 0,
386                 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),
387                 getTunnelMatchesForServiceId(input.getServiceId()), null);
388
389         ListenableFuture<Void> installFlowResult =
390                 mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
391         Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
392
393             @Override
394             public void onSuccess(Void voidInstance) {
395                 result.set(RpcResultBuilder.<Void>success().build());
396             }
397
398             @Override
399             public void onFailure(Throwable error) {
400                 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
401                 LOG.error("remove terminating service actions failed. {}", msg, error);
402                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
403                         .build());
404             }
405         }, MoreExecutors.directExecutor());
406         //result.set(RpcResultBuilder.<Void>success().build());
407
408         return result ;
409     }
410
411
412     public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
413         final List<MatchInfo> mkMatches = new ArrayList<>();
414
415         // Matching metadata
416         mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
417
418         return mkMatches;
419     }
420
421     private String getFlowRef(long termSvcTable, int svcId) {
422         return String.valueOf(termSvcTable) + svcId;
423     }
424
425     @Override
426     public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
427             GetInternalOrExternalInterfaceNameInput input) {
428         RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
429         BigInteger srcDpn = input.getSourceDpid() ;
430         IpAddress dstIp = input.getDestinationIp() ;
431         InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
432                 .child(ExternalTunnel.class,
433                         new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString(), input.getTunnelType()));
434
435         Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
436
437         if (optExtTunnel != null && optExtTunnel.isPresent()) {
438             ExternalTunnel extTunnel = optExtTunnel.get();
439             GetInternalOrExternalInterfaceNameOutputBuilder output =
440                     new GetInternalOrExternalInterfaceNameOutputBuilder()
441                             .setInterfaceName(extTunnel.getTunnelInterfaceName());
442             resultBld = RpcResultBuilder.success();
443             resultBld.withResult(output.build()) ;
444         } else {
445             Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
446
447             // Look for external tunnels if not look for internal tunnel
448             for (DPNTEPsInfo teps : meshedDpnList) {
449                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
450                 if (dstIp.equals(firstEndPt.getIpAddress())) {
451                     Optional<InternalTunnel> optTunnel = Optional.absent();
452                     if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
453                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
454                                                                      TunnelTypeLogicalGroup.class, dataBroker);
455                         LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
456                     }
457                     if (!optTunnel.isPresent()) {
458                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
459                                                                      input.getTunnelType(), dataBroker);
460                     }
461                     if (optTunnel.isPresent()) {
462                         InternalTunnel tunnel = optTunnel.get();
463                         List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
464                         if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
465                             GetInternalOrExternalInterfaceNameOutputBuilder
466                                     output =
467                                     new GetInternalOrExternalInterfaceNameOutputBuilder()
468                                             .setInterfaceName(tunnelInterfaces.get(0));
469                             resultBld = RpcResultBuilder.success();
470                             resultBld.withResult(output.build());
471                         } else {
472                             LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
473                                     dstIp);
474                         }
475                         break;
476                     } else {
477                         LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
478                     }
479                 }
480             }
481         }
482         return Futures.immediateFuture(resultBld.build());
483     }
484
485     @SuppressWarnings("checkstyle:IllegalCatch")
486     @Override
487     public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
488         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
489         boolean foundVxlanTzone = false;
490         try {
491             final IpAddress hwIp = input.getIpAddress();
492             final String nodeId = input.getNodeId();
493             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
494             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
495                     containerPath, dataBroker);
496             if (transportZonesOptional.isPresent()) {
497                 TransportZones transportZones = transportZonesOptional.get();
498                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
499                     LOG.error("No teps configured");
500                     result.set(RpcResultBuilder.<Void>failed()
501                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
502                     return result;
503                 }
504                 for (TransportZone tzone : transportZones.getTransportZone()) {
505                     if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
506                         continue;
507                     }
508                     foundVxlanTzone = true;
509                     String transportZone = tzone.getZoneName();
510                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
511                         result.set(RpcResultBuilder.<Void>failed()
512                                 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
513                         return result;
514                     }
515                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
516                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
517                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
518                             .child(TransportZone.class, new TransportZoneKey(transportZone))
519                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
520                             .build();
521                     WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
522                     //TO DO: add retry if it fails
523
524                     transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
525
526                     ListenableFuture<Void> futureCheck = transaction.submit();
527                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
528
529                         @Override public void onSuccess(Void voidInstance) {
530                             result.set(RpcResultBuilder.<Void>success().build());
531                         }
532
533                         @Override public void onFailure(Throwable error) {
534                             String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
535                             LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
536                             result.set(RpcResultBuilder.<Void>failed()
537                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
538                         }
539                     });
540
541                 }
542             } else {
543                 result.set(RpcResultBuilder.<Void>failed()
544                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
545                 return result;
546             }
547
548             if (!foundVxlanTzone) {
549                 result.set(RpcResultBuilder.<Void>failed()
550                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
551                         .build());
552             }
553
554             return result;
555         } catch (Exception e) {
556             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
557                     .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
558             return Futures.immediateFuture(resultBuilder.build());
559         }
560     }
561
562     @SuppressWarnings("checkstyle:IllegalCatch")
563     @Override
564     public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
565
566         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
567         boolean foundVxlanTzone = false;
568         try {
569             final IpAddress hwIp = input.getIpAddress();
570             final String nodeId = input.getNodeId();
571             //iterate through all transport zones and put TORs under vxlan
572             //if no vxlan tzone is cnfigured, return an error.
573             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
574             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
575                     containerPath, dataBroker);
576             if (transportZonesOptional.isPresent()) {
577                 TransportZones transportZones = transportZonesOptional.get();
578                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
579                     LOG.error("No transportZone configured");
580                     result.set(RpcResultBuilder.<Void>failed()
581                             .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
582                     return result;
583                 }
584                 for (TransportZone tzone : transportZones.getTransportZone()) {
585                     if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
586                         continue;
587                     }
588                     String transportZone = tzone.getZoneName();
589                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
590                         continue;
591                     }
592                     foundVxlanTzone = true;
593                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
594                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
595                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
596                             .child(TransportZone.class, new TransportZoneKey(transportZone))
597                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
598                             .build();
599                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
600                             .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
601                     WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
602                     //TO DO: add retry if it fails
603                     transaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
604
605                     ListenableFuture<Void> futureCheck = transaction.submit();
606                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
607
608                         @Override public void onSuccess(Void voidInstance) {
609                             result.set(RpcResultBuilder.<Void>success().build());
610                         }
611
612                         @Override public void onFailure(Throwable error) {
613                             String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
614                             LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
615                             result.set(RpcResultBuilder.<Void>failed()
616                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
617                         }
618                     });
619
620                 }
621             } else {
622                 result.set(RpcResultBuilder.<Void>failed()
623                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
624                 return result;
625             }
626
627             if (!foundVxlanTzone) {
628                 result.set(RpcResultBuilder.<Void>failed()
629                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
630                         .build());
631             }
632
633             return result;
634         } catch (Exception e) {
635             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
636                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
637             return Futures.immediateFuture(resultBuilder.build());
638         }
639     }
640
641     @SuppressWarnings("checkstyle:IllegalCatch")
642     @Override
643     public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
644
645         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
646         try {
647             final IpAddress hwIp = input.getIpAddress();
648             final List<String> nodeId = input.getNodeId();
649             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
650             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
651                     containerPath, dataBroker);
652             if (transportZonesOptional.isPresent()) {
653                 TransportZones transportZones = transportZonesOptional.get();
654                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
655                     LOG.error("No teps configured");
656                     result.set(RpcResultBuilder.<Void>failed()
657                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
658                     return result;
659                 }
660                 String transportZone = transportZones.getTransportZone().get(0).getZoneName();
661                 if (transportZones.getTransportZone().get(0).getSubnets() == null
662                         || transportZones.getTransportZone().get(0).getSubnets().isEmpty()) {
663                     result.set(RpcResultBuilder.<Void>failed()
664                             .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
665                     return result;
666                 }
667                 SubnetsKey subnetsKey = transportZones.getTransportZone().get(0).getSubnets().get(0).getKey();
668                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
669                 InstanceIdentifier<DeviceVteps> path =
670                         InstanceIdentifier.builder(TransportZones.class)
671                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
672                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
673                 DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
674                         .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
675                 WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
676                 //TO DO: add retry if it fails
677                 LOG.trace("writing hWvtep{}",deviceVtep);
678                 writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
679
680                 if (nodeId.size() == 2) {
681                     LOG.trace("second node-id {}",nodeId.get(1));
682                     DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
683                     InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
684                             .child(TransportZone.class, new TransportZoneKey(transportZone))
685                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
686                     DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().setKey(deviceVtepKey2).setIpAddress(hwIp)
687                             .setNodeId(nodeId.get(1))
688                             .setTopologyId(input.getTopologyId()).build();
689                     //TO DO: add retry if it fails
690                     LOG.trace("writing {}",deviceVtep2);
691                     writeTransaction.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
692                 }
693                 ListenableFuture<Void> futureCheck = writeTransaction.submit();
694                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
695
696                     @Override
697                     public void onSuccess(Void voidInstance) {
698                         result.set(RpcResultBuilder.<Void>success().build());
699                     }
700
701                     @Override
702                     public void onFailure(Throwable error) {
703                         String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
704                         LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
705                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
706                                 .build());
707                     }
708                 }, MoreExecutors.directExecutor());
709             }
710             return result;
711         } catch (RuntimeException e) {
712             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
713                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
714             return Futures.immediateFuture(resultBuilder.build());
715         }
716     }
717
718     @SuppressWarnings("checkstyle:IllegalCatch")
719     @Override
720     public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
721
722         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
723         try {
724             final IpAddress hwIp = input.getIpAddress();
725             final List<String> nodeId = input.getNodeId();
726             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
727             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
728                     containerPath, dataBroker);
729             if (transportZonesOptional.isPresent()) {
730                 TransportZones tzones = transportZonesOptional.get();
731                 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
732                     LOG.error("No teps configured");
733                     result.set(RpcResultBuilder.<Void>failed()
734                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
735                     return result;
736                 }
737                 String transportZone = tzones.getTransportZone().get(0).getZoneName();
738                 if (tzones.getTransportZone().get(0).getSubnets() == null || tzones.getTransportZone()
739                         .get(0).getSubnets().isEmpty()) {
740                     result.set(RpcResultBuilder.<Void>failed()
741                             .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
742                     return result;
743                 }
744                 SubnetsKey subnetsKey = tzones.getTransportZone().get(0).getSubnets().get(0).getKey();
745                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
746                 InstanceIdentifier<DeviceVteps> path =
747                         InstanceIdentifier.builder(TransportZones.class)
748                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
749                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
750                                 deviceVtepKey).build();
751                 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
752                 //TO DO: add retry if it fails
753                 transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
754
755                 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
756                 InstanceIdentifier<DeviceVteps> path2 =
757                         InstanceIdentifier.builder(TransportZones.class)
758                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
759                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
760                                 deviceVtepKey2).build();
761                 //TO DO: add retry if it fails
762                 transaction.delete(LogicalDatastoreType.CONFIGURATION, path2);
763
764                 ListenableFuture<Void> futureCheck = transaction.submit();
765                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
766
767                     @Override
768                     public void onSuccess(Void voidInstance) {
769                         result.set(RpcResultBuilder.<Void>success().build());
770                     }
771
772                     @Override
773                     public void onFailure(Throwable error) {
774                         String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
775                         LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
776                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error)
777                                 .build());
778                     }
779                 });
780             }
781             return result;
782         } catch (Exception e) {
783             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed()
784                     .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
785             return Futures.immediateFuture(resultBuilder.build());
786         }
787     }
788
789     @Override
790     public Future<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
791             IsTunnelInternalOrExternalInput input) {
792         RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
793         String tunIfName = input.getTunnelInterfaceName();
794         long tunVal = 0;
795         IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
796                         .setTunnelType(tunVal);
797
798         if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
799             tunVal = 1;
800         } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
801             tunVal = 2;
802         }
803         output.setTunnelType(tunVal);
804         resultBld = RpcResultBuilder.success();
805         resultBld.withResult(output.build());
806         return Futures.immediateFuture(resultBld.build());
807     }
808
809     @Override
810     public Future<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
811         RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
812
813         List<DcGatewayIp> dcGatewayIpList = ItmUtils.getDcGatewayIpList(dataBroker);
814         String dcgwIpStr = input.getDcgwIp();
815         IpAddress dcgwIpAddr = new IpAddress(dcgwIpStr.toCharArray());
816         long retVal;
817
818         if (dcGatewayIpList != null && !dcGatewayIpList.isEmpty()
819                 && dcGatewayIpList.stream().anyMatch(gwIp -> Objects.equal(gwIp.getIpAddress(), dcgwIpAddr))) {
820             //Match found
821             retVal = 1;
822             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
823             resultBld.withResult(output.build());
824         } else {
825             //Match not found
826             retVal = 2;
827             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
828             resultBld.withResult(output.build());
829         }
830         return Futures.immediateFuture(resultBld.build());
831     }
832
833     @Override
834     public Future<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
835         BigInteger srcDpn = input.getSourceDpid() ;
836         RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = RpcResultBuilder.failed();
837         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
838                 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
839                         new DPNTEPsInfoKey(srcDpn)).build();
840         Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
841         if (!tunnelInfo.isPresent()) {
842             LOG.error("tunnelInfo is not present");
843             return Futures.immediateFuture(resultBld.build());
844         }
845
846         List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
847         if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
848             LOG.error("tunnelEndPointList is null or empty");
849             return Futures.immediateFuture(resultBld.build());
850         }
851
852         List<IpAddress> nexthopIpList = new ArrayList<>();
853         tunnelEndPointList.forEach(tunnelEndPoint -> {
854             nexthopIpList.add(tunnelEndPoint.getIpAddress());
855         });
856
857         GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
858         resultBld = RpcResultBuilder.success();
859         resultBld.withResult(output.build()) ;
860         return Futures.immediateFuture(resultBld.build());
861     }
862
863     @Override
864     public Future<RpcResult<GetDpnInfoOutput>> getDpnInfo(GetDpnInfoInput input) {
865         return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input, () -> {
866             return Futures.immediateFuture(getDpnInfoInternal(input));
867         }).build();
868     }
869
870     private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException {
871         Map<String, BigInteger> computeNamesVsDpnIds
872                 = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames());
873         Map<BigInteger, ComputesBuilder> dpnIdVsVtepsComputes
874                 = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values());
875         List<Computes> computes = computeNamesVsDpnIds.entrySet().stream()
876                 .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build())
877                 .collect(Collectors.toList());
878         return new GetDpnInfoOutputBuilder().setComputes(computes).build();
879     }
880
881     private Map<BigInteger, ComputesBuilder> getTunnelEndPointByDpnIdFromTranPortZone(Collection<BigInteger> dpnIds)
882             throws ReadFailedException {
883         TransportZones transportZones = singleTransactionDataBroker.syncRead(
884                 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build());
885         if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
886             throw new IllegalStateException("Failed to find transport zones in config datastore");
887         }
888         Map<BigInteger, ComputesBuilder> result = new HashMap<>();
889         for (TransportZone transportZone : transportZones.getTransportZone()) {
890             if (transportZone.getSubnets() == null || transportZone.getSubnets().isEmpty()) {
891                 LOG.debug("Transport Zone {} has no subnets", transportZone.getZoneName());
892                 continue;
893             }
894             for (Subnets sub : transportZone.getSubnets()) {
895                 if (sub.getVteps() == null || sub.getVteps().isEmpty()) {
896                     LOG.debug("Transport Zone {} subnet {} has no vteps configured",
897                             transportZone.getZoneName(), sub.getPrefix());
898                     continue;
899                 }
900                 for (Vteps vtep : sub.getVteps()) {
901                     if (dpnIds.contains(vtep.getDpnId())) {
902                         result.putIfAbsent(vtep.getDpnId(),
903                             new ComputesBuilder()
904                                 .setZoneName(transportZone.getZoneName())
905                                 .setPrefix(sub.getPrefix())
906                                 .setDpnId(vtep.getDpnId())
907                                 .setPortName(vtep.getPortname())
908                                 .setNodeId(getNodeId(vtep.getDpnId()))
909                                 .setTepIp(Collections.singletonList(vtep.getIpAddress())));
910                     }
911                 }
912             }
913         }
914         for (BigInteger dpnId : dpnIds) {
915             if (!result.containsKey(dpnId)) {
916                 throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone");
917             }
918         }
919         return result;
920     }
921
922     private Map<String, BigInteger> getDpnIdByComputeNodeNameFromOpInventoryNodes(List<String> nodeNames)
923             throws ReadFailedException {
924         Nodes operInventoryNodes = singleTransactionDataBroker.syncRead(
925                 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build());
926         if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) {
927             throw new IllegalStateException("Failed to find operational inventory nodes datastore");
928         }
929         Map<String, BigInteger> result = new HashMap<>();
930         for (Node node : operInventoryNodes.getNode()) {
931             String name = node.<FlowCapableNode>getAugmentation(FlowCapableNode.class).getDescription();
932             if (nodeNames.contains(name)) {
933                 String[] nodeId = node.getId().getValue().split(":");
934                 result.put(name, new BigInteger(nodeId[1]));
935             }
936         }
937         for (String nodeName : nodeNames) {
938             if (!result.containsKey(nodeName)) {
939                 throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory "
940                         + nodeName);
941             }
942         }
943         return result;
944     }
945
946     private String getNodeId(BigInteger dpnId) throws ReadFailedException {
947         InstanceIdentifier<BridgeRefEntry> path = InstanceIdentifier
948                 .builder(BridgeRefInfo.class)
949                 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build();
950         BridgeRefEntry bridgeRefEntry =
951                 singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path);
952         return ((InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology
953                 .rev131021.network.topology.topology.Node>)bridgeRefEntry.getBridgeReference().getValue())
954                 .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
955                         .network.topology.topology.Node.class).getNodeId().getValue();
956     }
957 }