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