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