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