Change ITMManagerRpcservice Test frm Mock to Guice
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / rpc / ItmManagerRpcService.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.genius.itm.rpc;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.concurrent.Future;
19 import javax.annotation.PostConstruct;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker;
27 import org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelDeleteWorker;
28 import org.opendaylight.genius.itm.globals.ITMConstants;
29 import org.opendaylight.genius.itm.impl.ItmUtils;
30 import org.opendaylight.genius.mdsalutil.MDSALUtil;
31 import org.opendaylight.genius.mdsalutil.MatchInfo;
32 import org.opendaylight.genius.mdsalutil.NwConstants;
33 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
34 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVtepsKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwMlagDeviceInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.BuildExternalTunnelFromDpnsInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwDeviceInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.DeleteL2GwMlagDeviceInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutputBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutputBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalInput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsTunnelInternalOrExternalOutputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelFromDpnsInput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
86 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
87 import org.opendaylight.yangtools.yang.common.RpcError;
88 import org.opendaylight.yangtools.yang.common.RpcResult;
89 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
90 import org.slf4j.Logger;
91 import org.slf4j.LoggerFactory;
92
93 @Singleton
94 public class ItmManagerRpcService implements ItmRpcService {
95
96     private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
97     private final DataBroker dataBroker;
98     private final IMdsalApiManager mdsalManager;
99     private final IdManagerService idManagerService;
100
101     @Inject
102     public ItmManagerRpcService(final DataBroker dataBroker,final IdManagerService idManagerService,
103                                 final IMdsalApiManager iMdsalApiManager) {
104         this.dataBroker = dataBroker;
105         this.idManagerService = idManagerService;
106         this.mdsalManager = iMdsalApiManager;
107     }
108
109     @PostConstruct
110     public void start() {
111         LOG.info("ItmManagerRpcService Started");
112     }
113
114     @PreDestroy
115     public void close() {
116         LOG.info("ItmManagerRpcService Closed");
117     }
118
119     @Override
120     public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
121         RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
122         BigInteger sourceDpn = input.getSourceDpid() ;
123         BigInteger destinationDpn = input.getDestinationDpid() ;
124         InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
125                 TunnelList.class)
126                 .child(InternalTunnel.class, new InternalTunnelKey(destinationDpn, sourceDpn, input.getTunnelType()));
127
128         Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
129
130         if( tnl != null && tnl.isPresent())
131         {
132             InternalTunnel tunnel = tnl.get();
133             GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
134             output.setInterfaceName(tunnel.getTunnelInterfaceName()) ;
135             resultBld = RpcResultBuilder.success();
136             resultBld.withResult(output.build()) ;
137         }else {
138             resultBld = RpcResultBuilder.failed();
139         }
140
141         return Futures.immediateFuture(resultBld.build());
142     }
143
144
145     @Override
146     public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
147             RemoveExternalTunnelEndpointInput input) {
148         //Ignore the Futures for now
149         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
150         List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
151         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService,meshedDpnList , input.getDestinationIp(), input.getTunnelType());
152         InstanceIdentifier<DcGatewayIp> extPath= InstanceIdentifier.builder(DcGatewayIpList.class).child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
153         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
154         t.delete(LogicalDatastoreType.CONFIGURATION, extPath);
155         ListenableFuture<Void> futureCheck = t.submit();
156         Futures.addCallback(futureCheck, new FutureCallback<Void>() {
157
158             @Override public void onSuccess(Void aVoid) {
159                 result.set(RpcResultBuilder.<Void>success().build());
160             }
161
162             @Override public void onFailure(Throwable error) {
163                 String msg =
164                         "Unable to delete DcGatewayIp " + input.getDestinationIp() + " in datastore and tunnel type " + input.getTunnelType();
165                 LOG.error(msg);
166                 result.set(RpcResultBuilder.<Void>failed()
167                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
168             }
169         });
170         return result;
171     }
172
173     @Override
174     public Future<RpcResult<Void>> removeExternalTunnelFromDpns(
175             RemoveExternalTunnelFromDpnsInput input) {
176         //Ignore the Futures for now
177         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
178         List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDPNTEPListFromDPNId(dataBroker, input.getDpnId()) ;
179         ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService, cfgDpnList, input.getDestinationIp(), input.getTunnelType());
180         result.set(RpcResultBuilder.<Void>success().build());
181         return result;
182     }
183
184     @Override
185     public Future<RpcResult<Void>> buildExternalTunnelFromDpns(
186             BuildExternalTunnelFromDpnsInput input) {
187         //Ignore the Futures for now
188         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
189         List<ListenableFuture<Void>> extTunnelResultList = ItmExternalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, idManagerService,input.getDpnId(), input.getDestinationIp(), input.getTunnelType());
190         for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
191             Futures.addCallback(extTunnelResult, new FutureCallback<Void>(){
192
193                 @Override
194                 public void onSuccess(Void aVoid) {
195                     result.set(RpcResultBuilder.<Void>success().build());
196                 }
197
198                 @Override
199                 public void onFailure(Throwable error) {
200                     String msg = "Unable to create ext tunnel";
201                     LOG.error("create ext tunnel failed. {}. {}", msg, error);
202                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
203                 }
204             });
205         }
206         return result;
207     }
208
209     @Override
210     public Future<RpcResult<Void>> addExternalTunnelEndpoint(
211             AddExternalTunnelEndpointInput input) {
212         // TODO Auto-generated method stub
213
214         //Ignore the Futures for now
215         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
216         List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
217         ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, idManagerService,meshedDpnList, input.getDestinationIp(), input.getTunnelType()) ;InstanceIdentifier<DcGatewayIp> extPath= InstanceIdentifier.builder(DcGatewayIpList.class).child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
218         DcGatewayIp dcGatewayIp = new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp()).setTunnnelType(input.getTunnelType()).build();
219         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
220         t.put(LogicalDatastoreType.CONFIGURATION, extPath,dcGatewayIp, true);
221         ListenableFuture<Void> futureCheck = t.submit();
222         Futures.addCallback(futureCheck, new FutureCallback<Void>() {
223
224             @Override public void onSuccess(Void aVoid) {
225                 result.set(RpcResultBuilder.<Void>success().build());
226             }
227
228             @Override public void onFailure(Throwable error) {
229                 String msg =
230                         "Unable to create DcGatewayIp {} in datastore for ip "+ input.getDestinationIp() + "and tunnel type " + input.getTunnelType();
231                 LOG.error(msg);
232                 result.set(RpcResultBuilder.<Void>failed()
233                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
234             }
235         });
236         return result;
237     }
238
239     @Override
240     public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
241             GetExternalTunnelInterfaceNameInput input) {
242         SettableFuture.create();
243         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
244         String sourceNode = input.getSourceNode();
245         String dstNode = input.getDestinationNode();
246         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
247                 ExternalTunnelList.class)
248                 .child(ExternalTunnel.class, new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType()));
249
250         Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
251
252         if( ext != null && ext.isPresent())
253         {
254             ExternalTunnel exTunnel = ext.get();
255             GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ;
256             output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ;
257             resultBld = RpcResultBuilder.success();
258             resultBld.withResult(output.build()) ;
259         }else {
260             resultBld = RpcResultBuilder.failed();
261         }
262
263         return Futures.immediateFuture(resultBld.build());
264     }
265
266     @Override
267     public Future<RpcResult<java.lang.Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
268         LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction());
269         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
270         int serviceId = input.getServiceId() ;
271         List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
272         byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
273         // Flags Byte
274         byte Flags = (byte) 0x08;
275         vxLANHeader[0] = Flags;
276
277         // Extract the serviceId details and imprint on the VxLAN Header
278         vxLANHeader[4] = (byte) (serviceId >> 16);
279         vxLANHeader[5] = (byte) (serviceId >> 8);
280         vxLANHeader[6] = (byte) (serviceId >> 0);
281
282         // Matching metadata
283 //        mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
284 //                new BigInteger(1, vxLANHeader),
285 //                MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
286
287         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
288                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId),
289                 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
290
291         ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
292         Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
293
294             @Override
295             public void onSuccess(Void aVoid) {
296                 result.set(RpcResultBuilder.<Void>success().build());
297             }
298
299             @Override
300             public void onFailure(Throwable error) {
301                 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
302                 LOG.error("create terminating service actions failed. {}. {}", msg, error);
303                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
304             }
305         });
306         // result.set(RpcResultBuilder.<Void>success().build());
307         return result;
308     }
309
310     @Override
311     public Future<RpcResult<java.lang.Void>> removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
312         LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}", input.getDpnId(), input.getServiceId());
313         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
314         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
315                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5, String.format("%s:%d","ITM Flow Entry ",input.getServiceId()),
316                 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),getTunnelMatchesForServiceId(input.getServiceId()), null );
317
318         ListenableFuture<Void> installFlowResult = mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
319         Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
320
321             @Override
322             public void onSuccess(Void aVoid) {
323                 result.set(RpcResultBuilder.<Void>success().build());
324             }
325
326             @Override
327             public void onFailure(Throwable error) {
328                 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
329                 LOG.error("remove terminating service actions failed. {}. {}", msg, error);
330                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
331             }
332         });
333         //result.set(RpcResultBuilder.<Void>success().build());
334
335         return result ;
336     }
337
338
339     public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
340         List<MatchInfo> mkMatches = new ArrayList<>();
341         byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
342
343         // Flags Byte
344         byte Flags = (byte) 0x08;
345         vxLANHeader[0] = Flags;
346
347         // Extract the serviceId details and imprint on the VxLAN Header
348         vxLANHeader[4] = (byte) (serviceId >> 16);
349         vxLANHeader[5] = (byte) (serviceId >> 8);
350         vxLANHeader[6] = (byte) (serviceId >> 0);
351
352         // Matching metadata
353         mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
354
355         return mkMatches;
356     }
357
358     private String getFlowRef(long termSvcTable, int svcId) {
359         return String.valueOf(termSvcTable) + svcId;
360     }
361
362     @Override
363     public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
364             GetInternalOrExternalInterfaceNameInput input) {
365         RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
366         BigInteger srcDpn = input.getSourceDpid() ;
367         srcDpn.toString();
368         IpAddress dstIp = input.getDestinationIp() ;
369         InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(
370                 ExternalTunnelList.class)
371                 .child(ExternalTunnel.class, new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString(), TunnelTypeMplsOverGre.class));
372
373         Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
374
375         if( ext != null && ext.isPresent())
376         {
377             ExternalTunnel extTunnel = ext.get();
378             GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() );
379             resultBld = RpcResultBuilder.success();
380             resultBld.withResult(output.build()) ;
381         } else {
382             List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker);
383             if(meshedDpnList == null){
384                 LOG.error("There are no tunnel mesh info in config DS");
385                 return Futures.immediateFuture(resultBld.build());
386             }
387             // Look for external tunnels if not look for internal tunnel
388             for (DPNTEPsInfo teps : meshedDpnList) {
389                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
390                 if (dstIp.equals(firstEndPt.getIpAddress())) {
391                     InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
392                             TunnelList.class)
393                             .child(InternalTunnel.class, new InternalTunnelKey(teps.getDPNID(), srcDpn, input.getTunnelType()));
394
395                     Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
396                     if (tnl != null && tnl.isPresent()) {
397                         InternalTunnel tunnel = tnl.get();
398                         GetInternalOrExternalInterfaceNameOutputBuilder
399                                 output =
400                                 new GetInternalOrExternalInterfaceNameOutputBuilder()
401                                         .setInterfaceName(tunnel.getTunnelInterfaceName());
402                         resultBld = RpcResultBuilder.success();
403                         resultBld.withResult(output.build());
404                         break;
405                     }else{
406                         LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
407                     }
408                 }
409             }
410         }
411         return Futures.immediateFuture(resultBld.build());
412     }
413
414     @Override
415     public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
416         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
417         boolean foundVxlanTzone = false;
418         try {
419             final IpAddress hwIp = input.getIpAddress();
420             final String node_id = input.getNodeId();
421             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
422             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
423             if (tZonesOptional.isPresent()) {
424                 TransportZones tZones = tZonesOptional.get();
425                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
426                     LOG.error("No teps configured");
427                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
428                     return result;
429                 }
430                 for (TransportZone tzone : tZones.getTransportZone()) {
431                     if (!(tzone.getTunnelType().equals(TunnelTypeVxlan.class)))
432                         continue;
433                     foundVxlanTzone = true;
434                     String transportZone = tzone.getZoneName();
435                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
436                         result.set(RpcResultBuilder.<Void>failed()
437                                 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
438                         return result;
439                     }
440                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
441                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
442                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
443                             .child(TransportZone.class, new TransportZoneKey(transportZone))
444                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
445                             .build();
446                     WriteTransaction t = dataBroker.newWriteOnlyTransaction();
447                     //TO DO: add retry if it fails
448
449                     t.delete(LogicalDatastoreType.CONFIGURATION, path);
450
451                     ListenableFuture<Void> futureCheck = t.submit();
452                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
453
454                         @Override public void onSuccess(Void aVoid) {
455                             result.set(RpcResultBuilder.<Void>success().build());
456                         }
457
458                         @Override public void onFailure(Throwable error) {
459                             String msg = String.format("Unable to delete HwVtep {} from datastore", node_id);
460                             LOG.error("Unable to delete HwVtep {}, {} from datastore", node_id, hwIp);
461                             result.set(RpcResultBuilder.<Void>failed()
462                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
463                         }
464                     });
465
466                 }
467             }
468             else {
469                 result.set(RpcResultBuilder.<Void>failed()
470                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
471                 return result;
472             }
473
474             if (!foundVxlanTzone) {
475                 result.set(RpcResultBuilder.<Void>failed()
476                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
477                         .build());
478             }
479
480             return result;
481         } catch (Exception e) {
482             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
483                     withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
484             return Futures.immediateFuture(resultBuilder.build());
485         }
486     }
487
488     @Override
489     public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
490
491         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
492         boolean foundVxlanTzone = false;
493         try {
494             final IpAddress hwIp = input.getIpAddress();
495             final String node_id = input.getNodeId();
496             //iterate through all transport zones and put TORs under vxlan
497             //if no vxlan tzone is cnfigured, return an error.
498             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
499             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath,
500                     dataBroker);
501             if (tZonesOptional.isPresent()) {
502                 TransportZones tZones = tZonesOptional.get();
503                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
504                     LOG.error("No transportZone configured");
505                     result.set(RpcResultBuilder.<Void>failed()
506                             .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
507                     return result;
508                 }
509                 for (TransportZone tzone : tZones.getTransportZone()) {
510                     if (!(tzone.getTunnelType().equals(TunnelTypeVxlan.class)))
511                         continue;
512                     String transportZone = tzone.getZoneName();
513                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
514                         continue;
515                     }
516                     foundVxlanTzone = true;
517                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
518                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
519                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
520                             .child(TransportZone.class, new TransportZoneKey(transportZone))
521                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
522                             .build();
523                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
524                             .setNodeId(node_id).setTopologyId(input.getTopologyId()).build();
525                     WriteTransaction t = dataBroker.newWriteOnlyTransaction();
526                     //TO DO: add retry if it fails
527                     t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
528
529                     ListenableFuture<Void> futureCheck = t.submit();
530                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
531
532                         @Override public void onSuccess(Void aVoid) {
533                             result.set(RpcResultBuilder.<Void>success().build());
534                         }
535
536                         @Override public void onFailure(Throwable error) {
537                             String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
538                             LOG.error("Unable to write HwVtep {}, {} to datastore", node_id, hwIp);
539                             result.set(RpcResultBuilder.<Void>failed()
540                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
541                         }
542                     });
543
544                 }
545             }
546             else {
547                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
548                 return result;
549             }
550
551             if (!foundVxlanTzone) {
552                 result.set(RpcResultBuilder.<Void>failed()
553                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
554                         .build());
555             }
556
557             return result;
558         } catch (Exception e) {
559             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
560                     withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
561             return Futures.immediateFuture(resultBuilder.build());
562         }
563     }
564
565     @Override
566     public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input)
567     {
568
569         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
570         try {
571             final IpAddress hwIp = input.getIpAddress();
572             final List<String> node_id = input.getNodeId();
573             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
574             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
575             if (tZonesOptional.isPresent()) {
576                 TransportZones tZones = tZonesOptional.get();
577                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
578                     LOG.error("No teps configured");
579                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
580                     return result;
581                 }
582                 String transportZone = tZones.getTransportZone().get(0).getZoneName();
583                 if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
584                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
585                     return result;
586                 }
587                 SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
588                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
589                 InstanceIdentifier<DeviceVteps> path =
590                         InstanceIdentifier.builder(TransportZones.class)
591                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
592                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
593                 DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp).setNodeId(node_id.get(0)).setTopologyId(input.getTopologyId()).build();
594                 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
595                 //TO DO: add retry if it fails
596                 LOG.trace("writing hWvtep{}",deviceVtep);
597                 t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
598
599                 if(node_id.size() == 2) {
600                     LOG.trace("second node-id {}",node_id.get(1));
601                     DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
602                     InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
603                             .child(TransportZone.class, new TransportZoneKey(transportZone))
604                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
605                     DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().setKey(deviceVtepKey2).setIpAddress(hwIp).setNodeId(node_id.get(1))
606                             .setTopologyId(input.getTopologyId()).build();
607                     //TO DO: add retry if it fails
608                     LOG.trace("writing {}",deviceVtep2);
609                     t.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
610                 }ListenableFuture<Void> futureCheck = t.submit();
611                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
612
613                     @Override
614                     public void onSuccess(Void aVoid) {
615                         result.set(RpcResultBuilder.<Void>success().build());
616                     }
617
618                     @Override
619                     public void onFailure(Throwable error) {
620                         String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
621                         LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
622                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
623                     }
624                 });
625             }
626             return result;
627         } catch (Exception e) {
628             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
629                     withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
630             return Futures.immediateFuture(resultBuilder.build());
631         }
632     }
633     @Override
634     public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
635
636         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
637         try {
638             final IpAddress hwIp = input.getIpAddress();
639             final List<String> node_id = input.getNodeId();
640             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
641             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
642             if (tZonesOptional.isPresent()) {
643                 TransportZones tZones = tZonesOptional.get();
644                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
645                     LOG.error("No teps configured");
646                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
647                     return result;
648                 }
649                 String transportZone = tZones.getTransportZone().get(0).getZoneName();
650                 if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
651                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
652                     return result;
653                 }
654                 SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
655                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
656                 InstanceIdentifier<DeviceVteps> path =
657                         InstanceIdentifier.builder(TransportZones.class)
658                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
659                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
660                                 deviceVtepKey).build();
661                 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
662                 //TO DO: add retry if it fails
663                 t.delete(LogicalDatastoreType.CONFIGURATION, path);
664
665                 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
666                 InstanceIdentifier<DeviceVteps> path2 =
667                         InstanceIdentifier.builder(TransportZones.class)
668                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
669                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
670                                 deviceVtepKey2).build();
671                 //TO DO: add retry if it fails
672                 t.delete(LogicalDatastoreType.CONFIGURATION, path2);
673
674                 ListenableFuture<Void> futureCheck = t.submit();
675                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
676
677                     @Override
678                     public void onSuccess(Void aVoid) {
679                         result.set(RpcResultBuilder.<Void>success().build());
680                     }
681
682                     @Override
683                     public void onFailure(Throwable error) {
684                         String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
685                         LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
686                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
687                     }
688                 });
689             }
690             return result;
691         } catch (Exception e) {
692             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
693                     withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
694             return Futures.immediateFuture(resultBuilder.build());
695         }
696     }
697
698     @Override
699     public Future<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
700             IsTunnelInternalOrExternalInput input) {
701         RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
702         String tunIfName = input.getTunnelInterfaceName();
703         long tunVal = 0;
704         IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder().setTunnelType(tunVal);
705
706         if(ItmUtils.itmCache.getInternalTunnel(tunIfName) != null) {
707             tunVal = 1;
708         } else if (ItmUtils.itmCache.getExternalTunnel(tunIfName) != null) {
709             tunVal = 2;
710         }
711         output.setTunnelType(tunVal);
712         resultBld = RpcResultBuilder.success();
713         resultBld.withResult(output.build());
714         return Futures.immediateFuture(resultBld.build());
715     }
716
717     @Override
718     public Future<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
719         RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
720
721         List<DcGatewayIp> dcGatewayIpList = ItmUtils.getDcGatewayIpList(dataBroker);
722         String dcgwIpStr = input.getDcgwIp();
723         IpAddress dcgwIpAddr = new IpAddress(dcgwIpStr.toCharArray());
724         long retVal;
725
726         if((dcGatewayIpList != null) &&
727                 (!dcGatewayIpList.isEmpty()) &&
728                 (dcGatewayIpList.contains(dcgwIpAddr))) {
729             //Match found
730             retVal = 1;
731             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
732             resultBld.withResult(output.build());
733         } else {
734             //Match not found
735             retVal = 2;
736             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
737             resultBld.withResult(output.build());
738         }
739         return Futures.immediateFuture(resultBld.build());
740     }
741
742 }