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