Merge "ITM new style component test (empty)"
[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.MatchFieldType;
32 import org.opendaylight.genius.mdsalutil.MatchInfo;
33 import org.opendaylight.genius.mdsalutil.NwConstants;
34 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
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() throws Exception {
111         LOG.info("ItmManagerRpcService Started");
112     }
113
114     @PreDestroy
115     public void close() throws Exception {
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         result.set(RpcResultBuilder.<Void>success().build());
207         return result;
208     }
209
210     @Override
211     public Future<RpcResult<Void>> addExternalTunnelEndpoint(
212             AddExternalTunnelEndpointInput input) {
213         // TODO Auto-generated method stub
214
215         //Ignore the Futures for now
216         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
217         List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
218         ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, idManagerService,meshedDpnList, input.getDestinationIp(), input.getTunnelType()) ;InstanceIdentifier<DcGatewayIp> extPath= InstanceIdentifier.builder(DcGatewayIpList.class).child(DcGatewayIp.class, new DcGatewayIpKey(input.getDestinationIp())).build();
219         DcGatewayIp dcGatewayIp = new DcGatewayIpBuilder().setIpAddress(input.getDestinationIp()).setTunnnelType(input.getTunnelType()).build();
220         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
221         t.put(LogicalDatastoreType.CONFIGURATION, extPath,dcGatewayIp, true);
222         ListenableFuture<Void> futureCheck = t.submit();
223         Futures.addCallback(futureCheck, new FutureCallback<Void>() {
224
225             @Override public void onSuccess(Void aVoid) {
226                 result.set(RpcResultBuilder.<Void>success().build());
227             }
228
229             @Override public void onFailure(Throwable error) {
230                 String msg =
231                         "Unable to create DcGatewayIp {} in datastore for ip "+ input.getDestinationIp() + "and tunnel type " + input.getTunnelType();
232                 LOG.error(msg);
233                 result.set(RpcResultBuilder.<Void>failed()
234                         .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
235             }
236         });
237         return result;
238     }
239
240     @Override
241     public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
242             GetExternalTunnelInterfaceNameInput input) {
243         SettableFuture.create();
244         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
245         String sourceNode = input.getSourceNode();
246         String dstNode = input.getDestinationNode();
247         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
248                 ExternalTunnelList.class)
249                 .child(ExternalTunnel.class, new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType()));
250
251         Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
252
253         if( ext != null && ext.isPresent())
254         {
255             ExternalTunnel exTunnel = ext.get();
256             GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ;
257             output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ;
258             resultBld = RpcResultBuilder.success();
259             resultBld.withResult(output.build()) ;
260         }else {
261             resultBld = RpcResultBuilder.failed();
262         }
263
264         return Futures.immediateFuture(resultBld.build());
265     }
266
267     @Override
268     public Future<RpcResult<java.lang.Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
269         LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction());
270         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
271         int serviceId = input.getServiceId() ;
272         List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
273         byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
274         // Flags Byte
275         byte Flags = (byte) 0x08;
276         vxLANHeader[0] = Flags;
277
278         // Extract the serviceId details and imprint on the VxLAN Header
279         vxLANHeader[4] = (byte) (serviceId >> 16);
280         vxLANHeader[5] = (byte) (serviceId >> 8);
281         vxLANHeader[6] = (byte) (serviceId >> 0);
282
283         // Matching metadata
284 //        mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
285 //                new BigInteger(1, vxLANHeader),
286 //                MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
287
288         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
289                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId),
290                 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
291
292         ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
293         Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
294
295             @Override
296             public void onSuccess(Void aVoid) {
297                 result.set(RpcResultBuilder.<Void>success().build());
298             }
299
300             @Override
301             public void onFailure(Throwable error) {
302                 String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
303                 LOG.error("create terminating service actions failed. {}. {}", msg, error);
304                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
305             }
306         });
307         // result.set(RpcResultBuilder.<Void>success().build());
308         return result;
309     }
310
311     @Override
312     public Future<RpcResult<java.lang.Void>> removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
313         LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}", input.getDpnId(), input.getServiceId());
314         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
315         Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
316                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5, String.format("%s:%d","ITM Flow Entry ",input.getServiceId()),
317                 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),getTunnelMatchesForServiceId(input.getServiceId()), null );
318
319         ListenableFuture<Void> installFlowResult = mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
320         Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
321
322             @Override
323             public void onSuccess(Void aVoid) {
324                 result.set(RpcResultBuilder.<Void>success().build());
325             }
326
327             @Override
328             public void onFailure(Throwable error) {
329                 String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
330                 LOG.error("remove terminating service actions failed. {}. {}", msg, error);
331                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
332             }
333         });
334         //result.set(RpcResultBuilder.<Void>success().build());
335
336         return result ;
337     }
338
339
340     public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
341         List<MatchInfo> mkMatches = new ArrayList<>();
342         byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
343
344         // Flags Byte
345         byte Flags = (byte) 0x08;
346         vxLANHeader[0] = Flags;
347
348         // Extract the serviceId details and imprint on the VxLAN Header
349         vxLANHeader[4] = (byte) (serviceId >> 16);
350         vxLANHeader[5] = (byte) (serviceId >> 8);
351         vxLANHeader[6] = (byte) (serviceId >> 0);
352
353         // Matching metadata
354         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{
355                 BigInteger.valueOf(serviceId)}));
356
357         return mkMatches;
358     }
359
360     private String getFlowRef(long termSvcTable, int svcId) {
361         return String.valueOf(termSvcTable) + svcId;
362     }
363
364     @Override
365     public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
366             GetInternalOrExternalInterfaceNameInput input) {
367         RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
368         BigInteger srcDpn = input.getSourceDpid() ;
369         srcDpn.toString();
370         IpAddress dstIp = input.getDestinationIp() ;
371         InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(
372                 ExternalTunnelList.class)
373                 .child(ExternalTunnel.class, new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString(), TunnelTypeMplsOverGre.class));
374
375         Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
376
377         if( ext != null && ext.isPresent())
378         {
379             ExternalTunnel extTunnel = ext.get();
380             GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() );
381             resultBld = RpcResultBuilder.success();
382             resultBld.withResult(output.build()) ;
383         } else {
384             List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker);
385             if(meshedDpnList == null){
386                 LOG.error("There are no tunnel mesh info in config DS");
387                 return Futures.immediateFuture(resultBld.build());
388             }
389             // Look for external tunnels if not look for internal tunnel
390             for (DPNTEPsInfo teps : meshedDpnList) {
391                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
392                 if (dstIp.equals(firstEndPt.getIpAddress())) {
393                     InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
394                             TunnelList.class)
395                             .child(InternalTunnel.class, new InternalTunnelKey(teps.getDPNID(), srcDpn, input.getTunnelType()));
396
397                     Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
398                     if (tnl != null && tnl.isPresent()) {
399                         InternalTunnel tunnel = tnl.get();
400                         GetInternalOrExternalInterfaceNameOutputBuilder
401                                 output =
402                                 new GetInternalOrExternalInterfaceNameOutputBuilder()
403                                         .setInterfaceName(tunnel.getTunnelInterfaceName());
404                         resultBld = RpcResultBuilder.success();
405                         resultBld.withResult(output.build());
406                         break;
407                     }else{
408                         LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
409                     }
410                 }
411             }
412         }
413         return Futures.immediateFuture(resultBld.build());
414     }
415
416     @Override
417     public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
418         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
419         boolean foundVxlanTzone = false;
420         try {
421             final IpAddress hwIp = input.getIpAddress();
422             final String node_id = input.getNodeId();
423             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
424             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
425             if (tZonesOptional.isPresent()) {
426                 TransportZones tZones = tZonesOptional.get();
427                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
428                     LOG.error("No teps configured");
429                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
430                     return result;
431                 }
432                 for (TransportZone tzone : tZones.getTransportZone()) {
433                     if (!(tzone.getTunnelType().equals(TunnelTypeVxlan.class)))
434                         continue;
435                     foundVxlanTzone = true;
436                     String transportZone = tzone.getZoneName();
437                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
438                         result.set(RpcResultBuilder.<Void>failed()
439                                 .withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
440                         return result;
441                     }
442                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
443                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
444                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
445                             .child(TransportZone.class, new TransportZoneKey(transportZone))
446                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
447                             .build();
448                     WriteTransaction t = dataBroker.newWriteOnlyTransaction();
449                     //TO DO: add retry if it fails
450
451                     t.delete(LogicalDatastoreType.CONFIGURATION, path);
452
453                     ListenableFuture<Void> futureCheck = t.submit();
454                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
455
456                         @Override public void onSuccess(Void aVoid) {
457                             result.set(RpcResultBuilder.<Void>success().build());
458                         }
459
460                         @Override public void onFailure(Throwable error) {
461                             String msg = String.format("Unable to delete HwVtep {} from datastore", node_id);
462                             LOG.error("Unable to delete HwVtep {}, {} from datastore", node_id, hwIp);
463                             result.set(RpcResultBuilder.<Void>failed()
464                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
465                         }
466                     });
467
468                 }
469             }
470             else {
471                 result.set(RpcResultBuilder.<Void>failed()
472                         .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
473                 return result;
474             }
475
476             if (!foundVxlanTzone) {
477                 result.set(RpcResultBuilder.<Void>failed()
478                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
479                         .build());
480             }
481
482             return result;
483         } catch (Exception e) {
484             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
485                     withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
486             return Futures.immediateFuture(resultBuilder.build());
487         }
488     }
489
490     @Override
491     public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
492
493         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
494         boolean foundVxlanTzone = false;
495         try {
496             final IpAddress hwIp = input.getIpAddress();
497             final String node_id = input.getNodeId();
498             //iterate through all transport zones and put TORs under vxlan
499             //if no vxlan tzone is cnfigured, return an error.
500             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
501             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath,
502                     dataBroker);
503             if (tZonesOptional.isPresent()) {
504                 TransportZones tZones = tZonesOptional.get();
505                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
506                     LOG.error("No transportZone configured");
507                     result.set(RpcResultBuilder.<Void>failed()
508                             .withError(RpcError.ErrorType.APPLICATION, "No transportZone Configured").build());
509                     return result;
510                 }
511                 for (TransportZone tzone : tZones.getTransportZone()) {
512                     if (!(tzone.getTunnelType().equals(TunnelTypeVxlan.class)))
513                         continue;
514                     String transportZone = tzone.getZoneName();
515                     if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
516                         continue;
517                     }
518                     foundVxlanTzone = true;
519                     SubnetsKey subnetsKey = tzone.getSubnets().get(0).getKey();
520                     DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
521                     InstanceIdentifier<DeviceVteps> path = InstanceIdentifier.builder(TransportZones.class)
522                             .child(TransportZone.class, new TransportZoneKey(transportZone))
523                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey)
524                             .build();
525                     DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp)
526                             .setNodeId(node_id).setTopologyId(input.getTopologyId()).build();
527                     WriteTransaction t = dataBroker.newWriteOnlyTransaction();
528                     //TO DO: add retry if it fails
529                     t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
530
531                     ListenableFuture<Void> futureCheck = t.submit();
532                     Futures.addCallback(futureCheck, new FutureCallback<Void>() {
533
534                         @Override public void onSuccess(Void aVoid) {
535                             result.set(RpcResultBuilder.<Void>success().build());
536                         }
537
538                         @Override public void onFailure(Throwable error) {
539                             String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
540                             LOG.error("Unable to write HwVtep {}, {} to datastore", node_id, hwIp);
541                             result.set(RpcResultBuilder.<Void>failed()
542                                     .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
543                         }
544                     });
545
546                 }
547             }
548             else {
549                 result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
550                 return result;
551             }
552
553             if (!foundVxlanTzone) {
554                 result.set(RpcResultBuilder.<Void>failed()
555                         .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
556                         .build());
557             }
558
559             return result;
560         } catch (Exception e) {
561             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
562                     withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
563             return Futures.immediateFuture(resultBuilder.build());
564         }
565     }
566
567     @Override
568     public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input)
569     {
570
571         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
572         try {
573             final IpAddress hwIp = input.getIpAddress();
574             final List<String> node_id = input.getNodeId();
575             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
576             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
577             if (tZonesOptional.isPresent()) {
578                 TransportZones tZones = tZonesOptional.get();
579                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
580                     LOG.error("No teps configured");
581                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
582                     return result;
583                 }
584                 String transportZone = tZones.getTransportZone().get(0).getZoneName();
585                 if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
586                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
587                     return result;
588                 }
589                 SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
590                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
591                 InstanceIdentifier<DeviceVteps> path =
592                         InstanceIdentifier.builder(TransportZones.class)
593                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
594                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
595                 DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp).setNodeId(node_id.get(0)).setTopologyId(input.getTopologyId()).build();
596                 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
597                 //TO DO: add retry if it fails
598                 LOG.trace("writing hWvtep{}",deviceVtep);
599                 t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
600
601                 if(node_id.size() == 2) {
602                     LOG.trace("second node-id {}",node_id.get(1));
603                     DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
604                     InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
605                             .child(TransportZone.class, new TransportZoneKey(transportZone))
606                             .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
607                     DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().setKey(deviceVtepKey2).setIpAddress(hwIp).setNodeId(node_id.get(1))
608                             .setTopologyId(input.getTopologyId()).build();
609                     //TO DO: add retry if it fails
610                     LOG.trace("writing {}",deviceVtep2);
611                     t.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
612                 }ListenableFuture<Void> futureCheck = t.submit();
613                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
614
615                     @Override
616                     public void onSuccess(Void aVoid) {
617                         result.set(RpcResultBuilder.<Void>success().build());
618                     }
619
620                     @Override
621                     public void onFailure(Throwable error) {
622                         String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
623                         LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
624                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
625                     }
626                 });
627             }
628             return result;
629         } catch (Exception e) {
630             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
631                     withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
632             return Futures.immediateFuture(resultBuilder.build());
633         }
634     }
635     @Override
636     public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
637
638         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
639         try {
640             final IpAddress hwIp = input.getIpAddress();
641             final List<String> node_id = input.getNodeId();
642             InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
643             Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
644             if (tZonesOptional.isPresent()) {
645                 TransportZones tZones = tZonesOptional.get();
646                 if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
647                     LOG.error("No teps configured");
648                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
649                     return result;
650                 }
651                 String transportZone = tZones.getTransportZone().get(0).getZoneName();
652                 if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
653                     result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
654                     return result;
655                 }
656                 SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
657                 DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
658                 InstanceIdentifier<DeviceVteps> path =
659                         InstanceIdentifier.builder(TransportZones.class)
660                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
661                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
662                                 deviceVtepKey).build();
663                 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
664                 //TO DO: add retry if it fails
665                 t.delete(LogicalDatastoreType.CONFIGURATION, path);
666
667                 DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
668                 InstanceIdentifier<DeviceVteps> path2 =
669                         InstanceIdentifier.builder(TransportZones.class)
670                                 .child(TransportZone.class, new TransportZoneKey(transportZone))
671                                 .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
672                                 deviceVtepKey2).build();
673                 //TO DO: add retry if it fails
674                 t.delete(LogicalDatastoreType.CONFIGURATION, path2);
675
676                 ListenableFuture<Void> futureCheck = t.submit();
677                 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
678
679                     @Override
680                     public void onSuccess(Void aVoid) {
681                         result.set(RpcResultBuilder.<Void>success().build());
682                     }
683
684                     @Override
685                     public void onFailure(Throwable error) {
686                         String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
687                         LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
688                         result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
689                     }
690                 });
691             }
692             return result;
693         } catch (Exception e) {
694             RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
695                     withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
696             return Futures.immediateFuture(resultBuilder.build());
697         }
698     }
699
700     @Override
701     public Future<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
702             IsTunnelInternalOrExternalInput input) {
703         RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
704         String tunIfName = input.getTunnelInterfaceName();
705         long tunVal = 0;
706         IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder().setTunnelType(tunVal);
707
708         if(ItmUtils.itmCache.getInternalTunnel(tunIfName) != null) {
709             tunVal = 1;
710         } else if (ItmUtils.itmCache.getExternalTunnel(tunIfName) != null) {
711             tunVal = 2;
712         }
713         output.setTunnelType(tunVal);
714         resultBld = RpcResultBuilder.success();
715         resultBld.withResult(output.build());
716         return Futures.immediateFuture(resultBld.build());
717     }
718
719     @Override
720     public Future<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
721         RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
722
723         List<DcGatewayIp> dcGatewayIpList = ItmUtils.getDcGatewayIpList(dataBroker);
724         String dcgwIpStr = input.getDcgwIp();
725         IpAddress dcgwIpAddr = new IpAddress(dcgwIpStr.toCharArray());
726         long retVal;
727
728         if((dcGatewayIpList != null) &&
729                 (!dcGatewayIpList.isEmpty()) &&
730                 (dcGatewayIpList.contains(dcgwIpAddr))) {
731             //Match found
732             retVal = 1;
733             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
734             resultBld.withResult(output.build());
735         } else {
736             //Match not found
737             retVal = 2;
738             IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
739             resultBld.withResult(output.build());
740         }
741         return Futures.immediateFuture(resultBld.build());
742     }
743
744 }