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