8118c6aafcf516810fd8eee52d915e3b68fab8d7
[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 static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
11 import static org.opendaylight.serviceutils.tools.rpc.FutureRpcResults.fromListenableFuture;
12 import static org.opendaylight.yangtools.yang.common.RpcResultBuilder.failed;
13
14 import com.google.common.base.Objects;
15 import com.google.common.util.concurrent.FluentFuture;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Optional;
28 import java.util.concurrent.ExecutionException;
29 import java.util.stream.Collectors;
30 import javax.annotation.PostConstruct;
31 import javax.annotation.PreDestroy;
32 import javax.inject.Inject;
33 import javax.inject.Singleton;
34 import org.eclipse.jdt.annotation.NonNull;
35 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
36 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
37 import org.opendaylight.genius.interfacemanager.interfaces.InterfaceManagerService;
38 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
39 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
40 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
41 import org.opendaylight.genius.itm.cache.TunnelStateCache;
42 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
43 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
44 import org.opendaylight.genius.itm.globals.ITMConstants;
45 import org.opendaylight.genius.itm.impl.ItmUtils;
46 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
47 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
48 import org.opendaylight.genius.mdsalutil.ActionInfo;
49 import org.opendaylight.genius.mdsalutil.MDSALUtil;
50 import org.opendaylight.genius.mdsalutil.MatchInfo;
51 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
52 import org.opendaylight.genius.mdsalutil.NwConstants;
53 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
54 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
55 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
56 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
57 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
58 import org.opendaylight.mdsal.binding.api.DataBroker;
59 import org.opendaylight.mdsal.binding.util.Datastore;
60 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
61 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
62 import org.opendaylight.mdsal.binding.util.RetryingManagedNewTransactionRunner;
63 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
64 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
65 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
66 import org.opendaylight.mdsal.common.api.ReadFailedException;
67 import org.opendaylight.serviceutils.tools.rpc.FutureRpcResults;
68 import org.opendaylight.serviceutils.tools.rpc.FutureRpcResults.LogLevel;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVteps;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVtepsBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.DeviceVtepsKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Vteps;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnEndpointIpsOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetDpnInfoOutputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutputBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTepIpInput;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTepIpOutput;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeInput;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutput;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelTypeOutputBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelInput;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetWatchPortForTunnelOutput;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointOutput;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsOutput;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsOutput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelInput;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.SetBfdParamOnTunnelOutput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.Computes;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.ComputesBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
164 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
165 import org.opendaylight.yangtools.yang.common.OperationFailedException;
166 import org.opendaylight.yangtools.yang.common.RpcError;
167 import org.opendaylight.yangtools.yang.common.RpcResult;
168 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
169 import org.opendaylight.yangtools.yang.common.Uint16;
170 import org.opendaylight.yangtools.yang.common.Uint64;
171 import org.slf4j.Logger;
172 import org.slf4j.LoggerFactory;
173
174 @Singleton
175 public class ItmManagerRpcService implements ItmRpcService {
176
177     private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
178
179     private final DataBroker dataBroker;
180     private final IMdsalApiManager mdsalManager;
181     private final DPNTEPsInfoCache dpnTEPsInfoCache;
182     private final ItmExternalTunnelAddWorker externalTunnelAddWorker;
183     private final SingleTransactionDataBroker singleTransactionDataBroker;
184     private final IInterfaceManager interfaceManager;
185     private final InterfaceManagerService interfaceManagerService;
186     private final DpnTepStateCache dpnTepStateCache;
187     private final TunnelStateCache tunnelStateCache;
188     private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
189     private final DirectTunnelUtils directTunnelUtils;
190     private final ManagedNewTransactionRunner txRunner;
191     private final RetryingManagedNewTransactionRunner retryingTxRunner;
192     private final ItmConfig itmConfig;
193
194     @Inject
195     public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
196                                 final ItmConfig itmConfig, final DPNTEPsInfoCache dpnTEPsInfoCache,
197                                 final IInterfaceManager interfaceManager, final DpnTepStateCache dpnTepStateCache,
198                                 final TunnelStateCache tunnelStateCache,
199                                 final InterfaceManagerService interfaceManagerService,
200                                 final OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
201                                 final DirectTunnelUtils directTunnelUtils) {
202         this.dataBroker = dataBroker;
203         this.mdsalManager = mdsalManager;
204         this.dpnTEPsInfoCache = dpnTEPsInfoCache;
205         this.externalTunnelAddWorker = new ItmExternalTunnelAddWorker(itmConfig, dpnTEPsInfoCache);
206         this.singleTransactionDataBroker = new SingleTransactionDataBroker(dataBroker);
207         this.interfaceManager = interfaceManager;
208         this.interfaceManagerService = interfaceManagerService;
209         this.dpnTepStateCache = dpnTepStateCache;
210         this.tunnelStateCache = tunnelStateCache;
211         this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
212         this.directTunnelUtils = directTunnelUtils;
213         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
214         this.retryingTxRunner = new RetryingManagedNewTransactionRunner(dataBroker);
215         this.itmConfig = itmConfig;
216     }
217
218     @PostConstruct
219     public void start() {
220         LOG.info("ItmManagerRpcService Started");
221     }
222
223     @PreDestroy
224     public void close() {
225         LOG.info("ItmManagerRpcService Closed");
226     }
227
228     @Override
229     public ListenableFuture<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(
230             GetTunnelInterfaceNameInput input) {
231         RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
232         Uint64 sourceDpn = input.getSourceDpid();
233         Uint64 destinationDpn = input.getDestinationDpid();
234         Optional<InternalTunnel> optTunnel = Optional.empty();
235
236         if (interfaceManager.isItmDirectTunnelsEnabled()) {
237             DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getDpnTepInterface(sourceDpn, destinationDpn);
238             if (interfaceInfo != null) {
239                 resultBld = RpcResultBuilder.success();
240                 resultBld.withResult(new GetTunnelInterfaceNameOutputBuilder()
241                         .setInterfaceName(interfaceInfo.getTunnelName())).build();
242                 return Futures.immediateFuture(resultBld.build());
243             }
244         }
245         if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
246             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
247                     TunnelTypeLogicalGroup.class, dataBroker);
248             LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
249         }
250         if (!optTunnel.isPresent()) {
251             optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
252         }
253         if (optTunnel.isPresent()) {
254             InternalTunnel tunnel = optTunnel.get();
255             GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
256             List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
257             if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
258                 output.setInterfaceName(tunnelInterfaces.get(0));
259                 resultBld = RpcResultBuilder.success();
260                 resultBld.withResult(output.build());
261             } else {
262                 resultBld = failed();
263             }
264
265         } else {
266             resultBld = failed();
267         }
268         return Futures.immediateFuture(resultBld.build());
269     }
270
271     @Override
272     public ListenableFuture<RpcResult<GetEgressActionsForTunnelOutput>>
273         getEgressActionsForTunnel(GetEgressActionsForTunnelInput input) {
274         String tunnelName = input.getIntfName();
275         if (tunnelName == null) {
276             return Futures.immediateFuture(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
277                     .withError(RpcError.ErrorType.APPLICATION,
278                             "tunnel name not set for GetEgressActionsForTunnel call").build());
279         }
280         if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
281             // Re-direct the RPC to Interface Manager
282             // From the rpc input and get the output and copy to output
283             org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
284                     .GetEgressActionsForInterfaceInputBuilder inputIfmBuilder =
285                     new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
286                             .GetEgressActionsForInterfaceInputBuilder().setIntfName(input.getIntfName())
287                             .setTunnelKey(input.getTunnelKey()).setActionKey(input.getActionKey());
288             SettableFuture<RpcResult<GetEgressActionsForTunnelOutput>> settableFuture = SettableFuture.create();
289             Futures.addCallback(interfaceManagerService.getEgressActionsForInterface(inputIfmBuilder.build()),
290                     new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
291                             .interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput>() {
292                         @Override
293                         public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
294                                                       .rev160406.@NonNull GetEgressActionsForInterfaceOutput result) {
295                             GetEgressActionsForTunnelOutputBuilder output =
296                                     new GetEgressActionsForTunnelOutputBuilder().setAction(result.getAction());
297                             settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>success()
298                                     .withResult(output.build()).build());
299                         }
300
301                         @Override
302                         public void onFailure(Throwable throwable) {
303                             LOG.debug("RPC Call to Get egress actions failed for interface {}", tunnelName);
304                             String errMsg = String.format("RPC call to get egress actions failed for interface %s",
305                                     tunnelName);
306                             settableFuture.set(RpcResultBuilder.<GetEgressActionsForTunnelOutput>failed()
307                                     .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
308                         }
309                     } ,MoreExecutors.directExecutor());
310             return  settableFuture;
311         } else {
312             return fromListenableFuture(LOG, input, () -> getEgressActionsForInternalTunnels(input.getIntfName(),
313                     input.getTunnelKey() != null ? input.getTunnelKey().toJava() : null,
314                     input.getActionKey())).onFailureLogLevel(LogLevel.ERROR).build();
315         }
316     }
317
318     @Override
319     public ListenableFuture<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
320         String tunnelName = input.getIntfName();
321         if (tunnelName == null) {
322             return Futures.immediateFuture(RpcResultBuilder.<GetTunnelTypeOutput>failed()
323                     .withError(RpcError.ErrorType.APPLICATION,
324                             "tunnel name not set for getTunnelType call").build());
325         }
326
327         if (!dpnTepStateCache.isInternal(tunnelName) || !interfaceManager.isItmDirectTunnelsEnabled()) {
328             org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406
329                     .GetTunnelTypeInputBuilder inputBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight
330                     .genius.interfacemanager.rpcs.rev160406.GetTunnelTypeInputBuilder()
331                     .setIntfName(input.getIntfName());
332             SettableFuture<RpcResult<GetTunnelTypeOutput>> settableFuture = SettableFuture.create();
333             Futures.addCallback(interfaceManagerService.getTunnelType(inputBuilder.build()),
334                     new FutureCallback<org.opendaylight.yang.gen.v1.urn.opendaylight.genius
335                             .interfacemanager.rpcs.rev160406.GetTunnelTypeOutput>() {
336                         @Override
337                         public void onSuccess(org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs
338                                                       .rev160406.@NonNull GetTunnelTypeOutput result) {
339                             GetTunnelTypeOutputBuilder output = new GetTunnelTypeOutputBuilder()
340                                     .setTunnelType(result.getTunnelType());
341                             settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>success()
342                                     .withResult(output.build()).build());
343                         }
344
345                         @Override
346                         public void onFailure(Throwable throwable) {
347                             LOG.debug("RPC Call to Get tunnel type failed for interface {}", tunnelName);
348                             String errMsg = String.format("RPC to Get tunnel type failed for interface %s",
349                                     tunnelName);
350                             settableFuture.set(RpcResultBuilder.<GetTunnelTypeOutput>failed()
351                                     .withError(RpcError.ErrorType.APPLICATION, errMsg, throwable).build());
352                         }
353                     },MoreExecutors.directExecutor());
354             return settableFuture;
355         } else {
356             LOG.debug("get tunnel type from ITM for interface name {}", input.getIntfName());
357             return FutureRpcResults.fromBuilder(LOG, input, () -> {
358                 DpnTepInterfaceInfo ifInfo = dpnTepStateCache.getTunnelFromCache(input.getIntfName());
359                 return new GetTunnelTypeOutputBuilder().setTunnelType(ifInfo.getTunnelType());
360             }).build();
361         }
362     }
363
364     @Override
365     public ListenableFuture<RpcResult<SetBfdParamOnTunnelOutput>> setBfdParamOnTunnel(
366             SetBfdParamOnTunnelInput input) {
367         final Uint64 srcDpnId = Uint64.valueOf(input.getSourceNode());
368         final Uint64 destDpnId = Uint64.valueOf(input.getDestinationNode());
369         LOG.debug("setBfdParamOnTunnel srcDpnId: {}, destDpnId: {}", srcDpnId, destDpnId);
370         final SettableFuture<RpcResult<SetBfdParamOnTunnelOutput>> result = SettableFuture.create();
371         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
372             enableBFD(tx, srcDpnId, destDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
373             enableBFD(tx, destDpnId, srcDpnId, input.isMonitoringEnabled(), input.getMonitoringInterval().toJava());
374         });
375
376         future.addCallback(new FutureCallback<Object>() {
377             @Override
378             public void onSuccess(Object voidInstance) {
379                 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>success().build());
380             }
381
382             @Override
383             public void onFailure(Throwable error) {
384                 String msg = "Unable to remove external tunnel from DPN";
385                 LOG.error("remove ext tunnel failed. {}.", msg, error);
386                 result.set(RpcResultBuilder.<SetBfdParamOnTunnelOutput>failed()
387                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
388             }
389         }, MoreExecutors.directExecutor());
390         return result;
391     }
392
393     private void enableBFD(TypedWriteTransaction<Datastore.Configuration> tx, Uint64 srcDpnId, Uint64 destDpnId,
394                            final Boolean enabled, final Integer interval) throws ReadFailedException {
395         DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, destDpnId);
396         RemoteDpnsBuilder remoteDpnsBuilder = new RemoteDpnsBuilder();
397         remoteDpnsBuilder.withKey(new RemoteDpnsKey(destDpnId)).setDestinationDpnId(destDpnId)
398                 .setTunnelName(dpnTepInterfaceInfo.getTunnelName()).setInternal(dpnTepInterfaceInfo.isInternal())
399                 .setMonitoringEnabled(enabled);
400         if (enabled && interval != null) {
401             remoteDpnsBuilder.setMonitoringInterval(interval);
402         }
403         RemoteDpns remoteDpn = remoteDpnsBuilder.build();
404         Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(srcDpnId);
405         LOG.debug("setBfdParamOnTunnel TunnelName: {}, ovsBridgeRefEntry: {}", dpnTepInterfaceInfo.getTunnelName(),
406                 ovsBridgeRefEntry);
407         directTunnelUtils.updateBfdConfiguration(srcDpnId, remoteDpn, ovsBridgeRefEntry);
408         InstanceIdentifier<RemoteDpns> iid = InstanceIdentifier.builder(DpnTepsState.class)
409                 .child(DpnsTeps.class, new DpnsTepsKey(srcDpnId))
410                 .child(RemoteDpns.class,
411                         new RemoteDpnsKey(destDpnId)).build();
412         tx.mergeParentStructureMerge(iid, remoteDpn);
413     }
414
415     @Override
416     public ListenableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> removeExternalTunnelEndpoint(
417             RemoveExternalTunnelEndpointInput input) {
418         //Ignore the Futures for now
419         final SettableFuture<RpcResult<RemoveExternalTunnelEndpointOutput>> result = SettableFuture.create();
420         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
421         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
422             tx -> {
423                 ItmExternalTunnelDeleteWorker.deleteTunnels(meshedDpnList, input.getDestinationIp(),
424                         input.getTunnelType(), tx);
425                 InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
426                         .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
427                 tx.delete(extPath);
428             }
429         );
430         future.addCallback(new FutureCallback<Object>() {
431             @Override public void onSuccess(Object voidInstance) {
432                 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>success().build());
433             }
434
435             @Override public void onFailure(Throwable error) {
436                 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
437                         + " in datastore and tunnel type " + input.getTunnelType();
438                 LOG.error("Unable to delete DcGatewayIp {} in datastore and tunnel type {}", input.getDestinationIp(),
439                         input.getTunnelType());
440                 result.set(RpcResultBuilder.<RemoveExternalTunnelEndpointOutput>failed()
441                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
442             }
443         }, MoreExecutors.directExecutor());
444         return result;
445     }
446
447     @Override
448     public ListenableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> removeExternalTunnelFromDpns(
449             RemoveExternalTunnelFromDpnsInput input) {
450         //Ignore the Futures for now
451         final SettableFuture<RpcResult<RemoveExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
452         List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDpnTepListFromDpnId(dpnTEPsInfoCache, input.getDpnId());
453         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
454             tx -> ItmExternalTunnelDeleteWorker.deleteTunnels(cfgDpnList, input.getDestinationIp(),
455                     input.getTunnelType(), tx));
456
457         future.addCallback(new FutureCallback<Object>() {
458             @Override
459             public void onSuccess(Object voidInstance) {
460                 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>success().build());
461             }
462
463             @Override
464             public void onFailure(Throwable error) {
465                 String msg = "Unable to remove external tunnel from DPN";
466                 LOG.error("remove ext tunnel failed. {}.", msg, error);
467                 result.set(RpcResultBuilder.<RemoveExternalTunnelFromDpnsOutput>failed()
468                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
469             }
470         }, MoreExecutors.directExecutor());
471         return result;
472     }
473
474     @Override
475     public ListenableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> buildExternalTunnelFromDpns(
476             BuildExternalTunnelFromDpnsInput input) {
477         //Ignore the Futures for now
478         final SettableFuture<RpcResult<BuildExternalTunnelFromDpnsOutput>> result = SettableFuture.create();
479         FluentFuture<?> extTunnelResultList =
480             txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
481                 tx -> externalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(input.getDpnId(),
482                     input.getDestinationIp(),input.getTunnelType(), tx));
483
484         extTunnelResultList.addCallback(new FutureCallback<Object>() {
485             @Override
486             public void onSuccess(Object voidInstance) {
487                 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>success().build());
488             }
489
490             @Override
491             public void onFailure(Throwable error) {
492                 String msg = "Unable to create ext tunnel";
493                 LOG.error("create ext tunnel failed. {}.", msg, error);
494                 result.set(RpcResultBuilder.<BuildExternalTunnelFromDpnsOutput>failed()
495                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
496             }
497         }, MoreExecutors.directExecutor());
498         return result;
499     }
500
501     @Override
502     public ListenableFuture<RpcResult<AddExternalTunnelEndpointOutput>> addExternalTunnelEndpoint(
503             AddExternalTunnelEndpointInput input) {
504         // TODO Auto-generated method stub
505
506         //Ignore the Futures for now
507         final SettableFuture<RpcResult<AddExternalTunnelEndpointOutput>> result = SettableFuture.create();
508         Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
509         InstanceIdentifier<DcGatewayIp> extPath = InstanceIdentifier.builder(DcGatewayIpList.class)
510                 .child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
511         DcGatewayIp dcGatewayIp =
512                 new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp())
513                         .setTunnnelType(input.getTunnelType()).build();
514
515         FluentFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
516             tx -> {
517                 externalTunnelAddWorker.buildTunnelsToExternalEndPoint(meshedDpnList, input.getDestinationIp(),
518                     input.getTunnelType(), tx);
519                 tx.mergeParentStructurePut(extPath, dcGatewayIp);
520             }
521         );
522         future.addCallback(new FutureCallback<Object>() {
523             @Override public void onSuccess(Object voidInstance) {
524                 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>success().build());
525             }
526
527             @Override public void onFailure(Throwable error) {
528                 String msg =
529                         "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
530                                 + "tunnel type " + input.getTunnelType();
531
532                 LOG.error("Unable to create DcGatewayIp in datastore for ip {} and tunnel type {}",
533                         input.getDestinationIp() , input.getTunnelType());
534                 result.set(RpcResultBuilder.<AddExternalTunnelEndpointOutput>failed()
535                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
536             }
537         }, MoreExecutors.directExecutor());
538         return result;
539     }
540
541     @Override
542     public ListenableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
543             GetExternalTunnelInterfaceNameInput input) {
544         SettableFuture.create();
545         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
546         String sourceNode = input.getSourceNode();
547         String dstNode = input.getDestinationNode();
548         ExternalTunnelKey externalTunnelKey = new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType());
549         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
550                 ExternalTunnelList.class)
551                 .child(ExternalTunnel.class, externalTunnelKey);
552         ExternalTunnel exTunnel =
553                 ItmUtils.getExternalTunnelbyExternalTunnelKey(externalTunnelKey, path, this.dataBroker);
554         if (exTunnel != null) {
555             GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder();
556             output.setInterfaceName(exTunnel.getTunnelInterfaceName());
557             resultBld = RpcResultBuilder.success();
558             resultBld.withResult(output.build());
559         } else {
560             resultBld = failed();
561         }
562
563         return Futures.immediateFuture(resultBld.build());
564     }
565
566     @Override
567     public ListenableFuture<RpcResult<CreateTerminatingServiceActionsOutput>>
568         createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
569         LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}",
570                 input.getDpnId() , input.getServiceId(), input.getInstruction());
571         final SettableFuture<RpcResult<CreateTerminatingServiceActionsOutput>> result = SettableFuture.create();
572         Uint16 serviceId = input.getServiceId();
573         final List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
574
575         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
576                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, serviceId), 5,
577                 "ITM Flow Entry :" + serviceId, 0, 0,
578                 Uint64.fromLongBits(ITMConstants.COOKIE_ITM.longValue() + serviceId.toJava()), mkMatches,
579                 input.getInstruction());
580
581         ListenableFuture<?> installFlowResult = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
582             tx -> mdsalManager.addFlow(tx, input.getDpnId(), terminatingServiceTableFlow));
583         Futures.addCallback(installFlowResult, new FutureCallback<Object>() {
584
585             @Override
586             public void onSuccess(Object voidInstance) {
587                 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>success().build());
588             }
589
590             @Override
591             public void onFailure(Throwable error) {
592                 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
593                 LOG.error("create terminating service actions failed. {}", msg, error);
594                 result.set(RpcResultBuilder.<CreateTerminatingServiceActionsOutput>failed()
595                         .withError(RpcError.ErrorType.APPLICATION, msg, error)
596                         .build());
597             }
598         }, MoreExecutors.directExecutor());
599         // result.set(RpcResultBuilder.<Void>success().build());
600         return result;
601     }
602
603     @Override
604     public ListenableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>>
605         removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
606         LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}",
607                 input.getDpnId(), input.getServiceId());
608         final SettableFuture<RpcResult<RemoveTerminatingServiceActionsOutput>> result = SettableFuture.create();
609
610         ListenableFuture<?> removeFlowResult = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
611             tx -> mdsalManager.removeFlow(tx, input.getDpnId(),
612                         getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, input.getServiceId()),
613                         NwConstants.INTERNAL_TUNNEL_TABLE));
614         Futures.addCallback(removeFlowResult, new FutureCallback<Object>() {
615
616             @Override
617             public void onSuccess(Object voidInstance) {
618                 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>success().build());
619             }
620
621             @Override
622             public void onFailure(Throwable error) {
623                 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
624                 LOG.error("remove terminating service actions failed. {}", msg, error);
625                 result.set(RpcResultBuilder.<RemoveTerminatingServiceActionsOutput>failed()
626                         .withError(RpcError.ErrorType.APPLICATION, msg, error)
627                         .build());
628             }
629         }, MoreExecutors.directExecutor());
630         //result.set(RpcResultBuilder.<Void>success().build());
631
632         return result ;
633     }
634
635     public List<MatchInfo> getTunnelMatchesForServiceId(Uint16 serviceId) {
636         final List<MatchInfo> mkMatches = new ArrayList<>();
637
638         // Matching metadata
639         mkMatches.add(new MatchTunnelId(Uint64.valueOf(serviceId)));
640
641         return mkMatches;
642     }
643
644     private String getFlowRef(long termSvcTable, Uint16 svcId) {
645         return String.valueOf(termSvcTable) + svcId;
646     }
647
648     @Override
649     public ListenableFuture<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
650             GetInternalOrExternalInterfaceNameInput input) {
651         RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = failed();
652         Uint64 srcDpn = input.getSourceDpid();
653         IpAddress dstIp = input.getDestinationIp() ;
654         InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(ExternalTunnelList.class)
655                 .child(ExternalTunnel.class,
656                         new ExternalTunnelKey(dstIp.stringValue(), srcDpn.toString(), input.getTunnelType()));
657
658         Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
659
660         if (optExtTunnel != null && optExtTunnel.isPresent()) {
661             ExternalTunnel extTunnel = optExtTunnel.get();
662             GetInternalOrExternalInterfaceNameOutputBuilder output =
663                     new GetInternalOrExternalInterfaceNameOutputBuilder()
664                             .setInterfaceName(extTunnel.getTunnelInterfaceName());
665             resultBld = RpcResultBuilder.success();
666             resultBld.withResult(output.build()) ;
667         } else {
668             Collection<DPNTEPsInfo> meshedDpnList = dpnTEPsInfoCache.getAllPresent();
669
670             // Look for external tunnels if not look for internal tunnel
671             for (DPNTEPsInfo teps : meshedDpnList) {
672                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
673                 if (dstIp.equals(firstEndPt.getIpAddress())) {
674                     Optional<InternalTunnel> optTunnel = Optional.empty();
675                     if (interfaceManager.isItmDirectTunnelsEnabled()) {
676                         DpnTepInterfaceInfo interfaceInfo =
677                                 dpnTepStateCache.getDpnTepInterface(srcDpn, teps.getDPNID());
678                         if (interfaceInfo != null) {
679                             resultBld = RpcResultBuilder.success();
680                             resultBld.withResult(new GetInternalOrExternalInterfaceNameOutputBuilder()
681                                     .setInterfaceName(interfaceInfo.getTunnelName())).build();
682                             return Futures.immediateFuture(resultBld.build());
683                         }
684                     }
685
686                     if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
687                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
688                                 TunnelTypeLogicalGroup.class, dataBroker);
689                         LOG.debug("MULTIPLE_VxLAN_TUNNELS: getInternalOrExternalInterfaceName {}", optTunnel);
690                     }
691                     if (!optTunnel.isPresent()) {
692                         optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
693                                 input.getTunnelType(), dataBroker);
694                     }
695                     if (optTunnel.isPresent()) {
696                         InternalTunnel tunnel = optTunnel.get();
697                         List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
698                         if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
699                             GetInternalOrExternalInterfaceNameOutputBuilder
700                                     output =
701                                     new GetInternalOrExternalInterfaceNameOutputBuilder()
702                                             .setInterfaceName(tunnelInterfaces.get(0));
703                             resultBld = RpcResultBuilder.success();
704                             resultBld.withResult(output.build());
705                         } else {
706                             LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
707                                     dstIp);
708                         }
709                         break;
710                     } else {
711                         LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
712                     }
713                 }
714             }
715         }
716         return Futures.immediateFuture(resultBld.build());
717     }
718
719     @SuppressWarnings("checkstyle:IllegalCatch")
720     @Override
721     public ListenableFuture<RpcResult<DeleteL2GwDeviceOutput>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
722         final SettableFuture<RpcResult<DeleteL2GwDeviceOutput>> result = SettableFuture.create();
723         boolean foundVxlanTzone = false;
724         try {
725             final IpAddress hwIp = input.getIpAddress();
726             final String nodeId = input.getNodeId();
727             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
728             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
729                     containerPath, dataBroker);
730             if (transportZonesOptional.isPresent()) {
731                 TransportZones transportZones = transportZonesOptional.get();
732                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
733                     LOG.error("No teps configured");
734                     result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
735                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
736                     return result;
737                 }
738                 for (TransportZone tzone : transportZones.getTransportZone()) {
739                     if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
740                         continue;
741                     }
742                     foundVxlanTzone = true;
743                     String transportZone = tzone.getZoneName();
744                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
745                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
746                             .builder(TransportZones.class)
747                             .child(TransportZone.class,
748                                     new TransportZoneKey(transportZone))
749                             .child(DeviceVteps.class, deviceVtepKey)
750                             .build();
751                     FluentFuture<?> future =
752                         retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> tx.delete(path));
753                     future.addCallback(new FutureCallback<Object>() {
754                         @Override public void onSuccess(Object voidInstance) {
755                             result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>success().build());
756                         }
757
758                         @Override public void onFailure(Throwable error) {
759                             String msg = String.format("Unable to delete HwVtep %s from datastore", nodeId);
760                             LOG.error("Unable to delete HwVtep {}, {} from datastore", nodeId, hwIp);
761                             result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
762                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
763                         }
764                     }, MoreExecutors.directExecutor());
765                 }
766             } else {
767                 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
768                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
769                 return result;
770             }
771
772             if (!foundVxlanTzone) {
773                 result.set(RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
774                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
775                         .build());
776             }
777
778             return result;
779         } catch (Exception e) {
780             RpcResultBuilder<DeleteL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<DeleteL2GwDeviceOutput>failed()
781                     .withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
782             return Futures.immediateFuture(resultBuilder.build());
783         }
784     }
785
786     @SuppressWarnings("checkstyle:IllegalCatch")
787     @Override
788     public ListenableFuture<RpcResult<AddL2GwDeviceOutput>> addL2GwDevice(AddL2GwDeviceInput input) {
789
790         final SettableFuture<RpcResult<AddL2GwDeviceOutput>> result = SettableFuture.create();
791         boolean foundVxlanTzone = false;
792         try {
793             final IpAddress hwIp = input.getIpAddress();
794             final String nodeId = input.getNodeId();
795             //iterate through all transport zones and put TORs under vxlan
796             //if no vxlan tzone is cnfigured, return an error.
797             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
798             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
799                     containerPath, dataBroker);
800             if (transportZonesOptional.isPresent()) {
801                 TransportZones transportZones = transportZonesOptional.get();
802                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
803                     LOG.error("No transportZone configured");
804                     result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
805                             .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
806                     return result;
807                 }
808                 for (TransportZone tzone : transportZones.getTransportZone()) {
809                     if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
810                         continue;
811                     }
812                     String transportZone = tzone.getZoneName();
813                     foundVxlanTzone = true;
814                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId);
815                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier
816                             .builder(TransportZones.class)
817                             .child(TransportZone.class,
818                                     new TransportZoneKey(transportZone))
819                             .child(DeviceVteps.class, deviceVtepKey)
820                             .build();
821                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey).setIpAddress(hwIp)
822                             .setNodeId(nodeId).setTopologyId(input.getTopologyId()).build();
823                     //TO DO: add retry if it fails
824                     FluentFuture<?> future = retryingTxRunner
825                             .callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
826                                 tx -> tx.mergeParentStructurePut(path, deviceVtep));
827
828                     future.addCallback(new FutureCallback<Object>() {
829
830                         @Override public void onSuccess(Object voidInstance) {
831                             result.set(RpcResultBuilder.<AddL2GwDeviceOutput>success().build());
832                         }
833
834                         @Override public void onFailure(Throwable error) {
835                             String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
836                             LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
837                             result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
838                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
839                         }
840                     }, MoreExecutors.directExecutor());
841
842                 }
843             } else {
844                 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
845                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
846                 return result;
847             }
848
849             if (!foundVxlanTzone) {
850                 result.set(RpcResultBuilder.<AddL2GwDeviceOutput>failed()
851                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
852                         .build());
853             }
854
855             return result;
856         } catch (Exception e) {
857             RpcResultBuilder<AddL2GwDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwDeviceOutput>failed()
858                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
859             return Futures.immediateFuture(resultBuilder.build());
860         }
861     }
862
863     @Override
864     public ListenableFuture<RpcResult<GetWatchPortForTunnelOutput>> getWatchPortForTunnel(
865             GetWatchPortForTunnelInput input) {
866         throw new UnsupportedOperationException("TODO");
867     }
868
869     public ListenableFuture<RpcResult<GetTepIpOutput>> getTepIp(GetTepIpInput input) {
870         return null;
871     }
872
873     @SuppressWarnings("checkstyle:IllegalCatch")
874     @Override
875     public ListenableFuture<RpcResult<AddL2GwMlagDeviceOutput>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
876
877         final SettableFuture<RpcResult<AddL2GwMlagDeviceOutput>> result = SettableFuture.create();
878         try {
879             final IpAddress hwIp = input.getIpAddress();
880             final List<String> nodeId = input.getNodeId();
881             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
882             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
883                     containerPath, dataBroker);
884             if (transportZonesOptional.isPresent()) {
885                 TransportZones transportZones = transportZonesOptional.get();
886                 if (transportZones.getTransportZone() == null || transportZones.getTransportZone()
887                     .isEmpty()) {
888                     LOG.error("No teps configured");
889                     result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
890                         .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
891                     return result;
892                 }
893                 for (TransportZone tzone : transportZones.getTransportZone()) {
894                     if (!TunnelTypeVxlan.class.equals(tzone.getTunnelType())) {
895                         continue;
896                     }
897                     String transportZone = tzone.getZoneName();
898                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
899                     InstanceIdentifier<DeviceVteps> path =
900                         InstanceIdentifier.builder(TransportZones.class)
901                             .child(TransportZone.class, new TransportZoneKey(transportZone))
902                             .child(DeviceVteps.class, deviceVtepKey).build();
903                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().withKey(deviceVtepKey)
904                         .setIpAddress(hwIp)
905                         .setNodeId(nodeId.get(0)).setTopologyId(input.getTopologyId()).build();
906                     LOG.trace("writing hWvtep{}", deviceVtep);
907                     FluentFuture<?> future =
908                         retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
909                             tx -> {
910                                 tx.mergeParentStructurePut(path, deviceVtep);
911                                 if (nodeId.size() == 2) {
912                                     LOG.trace("second node-id {}", nodeId.get(1));
913                                     DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp,
914                                         nodeId.get(1));
915                                     InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier
916                                         .builder(TransportZones.class)
917                                         .child(TransportZone.class, new TransportZoneKey(transportZone))
918                                         .child(DeviceVteps.class, deviceVtepKey2).build();
919                                     DeviceVteps deviceVtep2 = new DeviceVtepsBuilder()
920                                         .withKey(deviceVtepKey2)
921                                         .setIpAddress(hwIp).setNodeId(nodeId.get(1))
922                                         .setTopologyId(input.getTopologyId()).build();
923                                     LOG.trace("writing {}", deviceVtep2);
924                                     tx.mergeParentStructurePut(path2, deviceVtep2);
925                                 }
926                             });
927                     future.addCallback(new FutureCallback<Object>() {
928                         @Override
929                         public void onSuccess(Object voidInstance) {
930                             result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>success().build());
931                         }
932
933                         @Override
934                         public void onFailure(Throwable error) {
935                             String msg = String
936                                 .format("Unable to write HwVtep %s to datastore", nodeId);
937                             LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId, hwIp);
938                             result.set(RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
939                                 .withError(RpcError.ErrorType.APPLICATION, msg, error)
940                                 .build());
941                         }
942                     }, MoreExecutors.directExecutor());
943                 }
944             }
945             return result;
946         } catch (RuntimeException e) {
947             RpcResultBuilder<AddL2GwMlagDeviceOutput> resultBuilder = RpcResultBuilder.<AddL2GwMlagDeviceOutput>failed()
948                     .withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
949             return Futures.immediateFuture(resultBuilder.build());
950         }
951     }
952
953     @SuppressWarnings("checkstyle:IllegalCatch")
954     @Override
955     public ListenableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> deleteL2GwMlagDevice(
956             DeleteL2GwMlagDeviceInput input) {
957         final SettableFuture<RpcResult<DeleteL2GwMlagDeviceOutput>> result = SettableFuture.create();
958         try {
959             final IpAddress hwIp = input.getIpAddress();
960             final List<String> nodeId = input.getNodeId();
961             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
962             Optional<TransportZones> transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
963                     containerPath, dataBroker);
964             if (transportZonesOptional.isPresent()) {
965                 TransportZones tzones = transportZonesOptional.get();
966                 if (tzones.getTransportZone() == null || tzones.getTransportZone().isEmpty()) {
967                     LOG.error("No teps configured");
968                     result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
969                             .withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
970                     return result;
971                 }
972                 String transportZone = tzones.getTransportZone().get(0).getZoneName();
973                 FluentFuture<?> future =
974                     retryingTxRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
975                         tx -> {
976                             DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, nodeId.get(0));
977                             InstanceIdentifier<DeviceVteps> path =
978                                     InstanceIdentifier.builder(TransportZones.class)
979                                             .child(TransportZone.class, new TransportZoneKey(transportZone))
980                                             .child(DeviceVteps.class,
981                                                     deviceVtepKey).build();
982                             tx.delete(path);
983                             DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, nodeId.get(1));
984                             InstanceIdentifier<DeviceVteps> path2 =
985                                     InstanceIdentifier.builder(TransportZones.class)
986                                             .child(TransportZone.class, new TransportZoneKey(transportZone))
987                                             .child(DeviceVteps.class,
988                                                     deviceVtepKey2).build();
989                             tx.delete(path2);
990                         }
991                     );
992
993                 future.addCallback(new FutureCallback<Object>() {
994
995                     @Override
996                     public void onSuccess(Object voidInstance) {
997                         result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>success().build());
998                     }
999
1000                     @Override
1001                     public void onFailure(Throwable error) {
1002                         String msg = String.format("Unable to write HwVtep %s to datastore", nodeId);
1003                         LOG.error("Unable to write HwVtep {}, {} to datastore", nodeId , hwIp);
1004                         result.set(RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed()
1005                                 .withError(RpcError.ErrorType.APPLICATION, msg, error)
1006                                 .build());
1007                     }
1008                 }, MoreExecutors.directExecutor());
1009             }
1010             return result;
1011         } catch (Exception e) {
1012             RpcResultBuilder<DeleteL2GwMlagDeviceOutput> resultBuilder =
1013                     RpcResultBuilder.<DeleteL2GwMlagDeviceOutput>failed().withError(RpcError.ErrorType.APPLICATION,
1014                             "Deleting l2 Gateway to DS Failed", e);
1015             return Futures.immediateFuture(resultBuilder.build());
1016         }
1017     }
1018
1019     @Override
1020     public ListenableFuture<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
1021             IsTunnelInternalOrExternalInput input) {
1022         RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
1023         String tunIfName = input.getTunnelInterfaceName();
1024         long tunVal = 0;
1025         IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
1026                 .setTunnelType(tunVal);
1027
1028         if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
1029             tunVal = 1;
1030         } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
1031             tunVal = 2;
1032         }
1033         output.setTunnelType(tunVal);
1034         resultBld = RpcResultBuilder.success();
1035         resultBld.withResult(output.build());
1036         return Futures.immediateFuture(resultBld.build());
1037     }
1038
1039     @Override
1040     public ListenableFuture<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
1041         RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
1042
1043         Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpList = new HashMap<>();
1044         txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
1045             tx -> dcGatewayIpList.putAll(getDcGatewayIpList(tx))).isDone();
1046         String dcgwIpStr = input.getDcgwIp();
1047         IpAddress dcgwIpAddr = IpAddressBuilder.getDefaultInstance(dcgwIpStr);
1048         long retVal;
1049
1050         if (!dcGatewayIpList.isEmpty()
1051                 && dcGatewayIpList.values().stream().anyMatch(gwIp -> Objects.equal(gwIp.getIpAddress(), dcgwIpAddr))) {
1052             //Match found
1053             retVal = 1;
1054             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1055             resultBld.withResult(output.build());
1056         } else {
1057             //Match not found
1058             retVal = 2;
1059             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
1060             resultBld.withResult(output.build());
1061         }
1062         return Futures.immediateFuture(resultBld.build());
1063     }
1064
1065     @Override
1066     public ListenableFuture<RpcResult<GetDpnEndpointIpsOutput>> getDpnEndpointIps(GetDpnEndpointIpsInput input) {
1067         Uint64 srcDpn = input.getSourceDpid();
1068         RpcResultBuilder<GetDpnEndpointIpsOutput> resultBld = failed();
1069         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
1070                 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
1071                         new DPNTEPsInfoKey(srcDpn)).build();
1072         Optional<DPNTEPsInfo> tunnelInfo = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tunnelInfoId, dataBroker);
1073         if (!tunnelInfo.isPresent()) {
1074             LOG.error("tunnelInfo is not present");
1075             return Futures.immediateFuture(resultBld.build());
1076         }
1077
1078         List<TunnelEndPoints> tunnelEndPointList = tunnelInfo.get().getTunnelEndPoints();
1079         if (tunnelEndPointList == null || tunnelEndPointList.isEmpty()) {
1080             LOG.error("tunnelEndPointList is null or empty");
1081             return Futures.immediateFuture(resultBld.build());
1082         }
1083
1084         List<IpAddress> nexthopIpList = new ArrayList<>();
1085         tunnelEndPointList.forEach(tunnelEndPoint -> nexthopIpList.add(tunnelEndPoint.getIpAddress()));
1086
1087         GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
1088         resultBld = RpcResultBuilder.success();
1089         resultBld.withResult(output.build()) ;
1090         return Futures.immediateFuture(resultBld.build());
1091     }
1092
1093     @Override
1094     public ListenableFuture<RpcResult<GetDpnInfoOutput>> getDpnInfo(GetDpnInfoInput input) {
1095         return FutureRpcResults.fromListenableFuture(LOG, "getDpnInfo", input,
1096             () -> Futures.immediateFuture(getDpnInfoInternal(input))).build();
1097     }
1098
1099     private GetDpnInfoOutput getDpnInfoInternal(GetDpnInfoInput input) throws ReadFailedException {
1100         Map<String, Uint64> computeNamesVsDpnIds
1101                 = getDpnIdByComputeNodeNameFromOpInventoryNodes(input.getComputeNames());
1102         Map<Uint64, ComputesBuilder> dpnIdVsVtepsComputes
1103                 = getTunnelEndPointByDpnIdFromTranPortZone(computeNamesVsDpnIds.values());
1104         List<Computes> computes = computeNamesVsDpnIds.entrySet().stream()
1105                 .map(entry -> dpnIdVsVtepsComputes.get(entry.getValue()).setComputeName(entry.getKey()).build())
1106                 .collect(Collectors.toList());
1107         return new GetDpnInfoOutputBuilder().setComputes(computes).build();
1108     }
1109
1110     private Map<Uint64, ComputesBuilder> getTunnelEndPointByDpnIdFromTranPortZone(Collection<Uint64> dpnIds)
1111             throws ReadFailedException {
1112         TransportZones transportZones = singleTransactionDataBroker.syncRead(
1113                 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(TransportZones.class).build());
1114         if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) {
1115             throw new IllegalStateException("Failed to find transport zones in config datastore");
1116         }
1117         Map<Uint64, ComputesBuilder> result = new HashMap<>();
1118         for (TransportZone transportZone : transportZones.getTransportZone()) {
1119             for (Vteps vtep : transportZone.getVteps().values()) {
1120                 if (dpnIds.contains(vtep.getDpnId())) {
1121                     result.putIfAbsent(vtep.getDpnId(),
1122                             new ComputesBuilder()
1123                                     .setZoneName(transportZone.getZoneName())
1124                                     .setDpnId(vtep.getDpnId())
1125                                     .setNodeId(getNodeId(vtep.getDpnId()))
1126                                     .setTepIp(Collections.singletonList(vtep.getIpAddress())));
1127                 }
1128             }
1129         }
1130         for (Uint64 dpnId : dpnIds) {
1131             if (!result.containsKey(dpnId)) {
1132                 throw new IllegalStateException("Failed to find dpn id " + dpnId + " in transport zone");
1133             }
1134         }
1135         return result;
1136     }
1137
1138     private Map<String, Uint64> getDpnIdByComputeNodeNameFromOpInventoryNodes(List<String> nodeNames)
1139             throws ReadFailedException {
1140         Nodes operInventoryNodes = singleTransactionDataBroker.syncRead(
1141                 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build());
1142         if (operInventoryNodes.getNode() == null || operInventoryNodes.getNode().isEmpty()) {
1143             throw new IllegalStateException("Failed to find operational inventory nodes datastore");
1144         }
1145         Map<String, Uint64> result = new HashMap<>();
1146         for (Node node : operInventoryNodes.getNode().values()) {
1147             String name = node.augmentation(FlowCapableNode.class).getDescription();
1148             if (nodeNames.contains(name)) {
1149                 String[] nodeId = node.getId().getValue().split(":");
1150                 result.put(name, Uint64.valueOf(nodeId[1]));
1151             }
1152         }
1153         for (String nodeName : nodeNames) {
1154             if (!result.containsKey(nodeName)) {
1155                 throw new IllegalStateException("Failed to find dpn id of compute node name from oper inventory "
1156                         + nodeName);
1157             }
1158         }
1159         return result;
1160     }
1161
1162     private String getNodeId(Uint64 dpnId) throws ReadFailedException {
1163         InstanceIdentifier<BridgeRefEntry> path = InstanceIdentifier
1164                 .builder(BridgeRefInfo.class)
1165                 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId)).build();
1166         BridgeRefEntry bridgeRefEntry =
1167                 singleTransactionDataBroker.syncRead(LogicalDatastoreType.OPERATIONAL, path);
1168         return bridgeRefEntry.getBridgeReference().getValue()
1169                 .firstKeyOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
1170                         .network.topology.topology.Node.class).getNodeId().getValue();
1171     }
1172
1173     private ListenableFuture<GetEgressActionsForTunnelOutput>
1174         getEgressActionsForInternalTunnels(String interfaceName, Long tunnelKey, Integer actionKey)
1175             throws ExecutionException, InterruptedException, OperationFailedException {
1176
1177         DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
1178         if (interfaceInfo == null) {
1179             throw new IllegalStateException("Interface information not present in config DS for" + interfaceName);
1180         }
1181
1182         String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
1183         if (!tunnelType.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_VXLAN)) {
1184             throw new IllegalArgumentException(tunnelType + " tunnel not handled by ITM");
1185         }
1186
1187         Optional<DPNTEPsInfo> dpntePsInfoOptional = dpnTEPsInfoCache.get(InstanceIdentifier.builder(DpnEndpoints.class)
1188                 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(
1189                     // FIXME: the cache should be caching this value, not just as a String
1190                     Uint64.valueOf(dpnTepStateCache.getTunnelEndPointInfoFromCache(interfaceInfo.getTunnelName())
1191                         .getDstEndPointInfo())))
1192                 .build());
1193         Integer dstId;
1194         if (dpntePsInfoOptional.isPresent()) {
1195             dstId = dpntePsInfoOptional.get().getDstId();
1196         } else {
1197             dstId = directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME, interfaceInfo.getRemoteDPN().toString());
1198         }
1199
1200         List<ActionInfo> result = new ArrayList<>();
1201         long regValue = MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId);
1202         int actionKeyStart = actionKey == null ? 0 : actionKey;
1203         result.add(new ActionSetFieldTunnelId(actionKeyStart++,
1204                 Uint64.valueOf(tunnelKey != null ? tunnelKey : 0L)));
1205         result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, MetaDataUtil.REG6_START_INDEX,
1206                 MetaDataUtil.REG6_END_INDEX, regValue));
1207         result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_TUNNEL_TABLE));
1208
1209         return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder()
1210                 .setAction(result.stream().map(ActionInfo::buildAction).collect(Collectors.toList())).build());
1211     }
1212
1213     public static Map<DcGatewayIpKey, DcGatewayIp>
1214         getDcGatewayIpList(TypedReadWriteTransaction<Datastore.Configuration> tx)
1215             throws ExecutionException, InterruptedException {
1216         Map<DcGatewayIpKey, DcGatewayIp> dcGatewayIpMap = new HashMap<>();
1217         FluentFuture<Optional<DcGatewayIpList>> future =
1218                 tx.read(InstanceIdentifier.builder(DcGatewayIpList.class).build());
1219         future.addCallback(new FutureCallback<Optional<DcGatewayIpList>>() {
1220             @Override
1221             public void onSuccess(Optional<DcGatewayIpList> optional) {
1222                 try {
1223                     // FIXME: why not just use the provided optional?
1224                     Optional<DcGatewayIpList> opt = future.get();
1225                     if (opt.isPresent()) {
1226                         DcGatewayIpList list = opt.get();
1227                         if (list != null) {
1228                             dcGatewayIpMap.putAll(list.getDcGatewayIp());
1229                         }
1230                     }
1231                 } catch (ExecutionException | InterruptedException e) {
1232                     LOG.error("DcGateway IpList read failed", e);
1233                 }
1234             }
1235
1236             @Override
1237             public void onFailure(Throwable error) {
1238                 LOG.error("DcGateway IpList read failed", error);
1239             }
1240         }, MoreExecutors.directExecutor());
1241         return dcGatewayIpMap;
1242     }
1243 }