2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.itm.rpc;
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;
98 public class ItmManagerRpcService implements ItmRpcService {
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;
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;
114 public void start() {
115 LOG.info("ItmManagerRpcService Started");
119 public void close() {
120 LOG.info("ItmManagerRpcService Closed");
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();
130 if (ItmUtils.isTunnelAggregationUsed(input.getTunnelType())) {
131 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn,
132 TunnelTypeLogicalGroup.class, dataBroker);
133 LOG.debug("MULTIPLE_VxLAN_TUNNELS: getTunnelInterfaceName {}", optTunnel);
135 if (!optTunnel.isPresent()) {
136 optTunnel = ItmUtils.getInternalTunnelFromDS(sourceDpn, destinationDpn, input.getTunnelType(), dataBroker);
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());
147 resultBld = RpcResultBuilder.failed();
151 resultBld = RpcResultBuilder.failed();
153 return Futures.immediateFuture(resultBld.build());
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>() {
172 @Override public void onSuccess(Void voidInstance) {
173 result.set(RpcResultBuilder.<Void>success().build());
176 @Override public void onFailure(Throwable error) {
177 String msg = "Unable to delete DcGatewayIp " + input.getDestinationIp()
178 + " in datastore and tunnel type " + input.getTunnelType();
180 result.set(RpcResultBuilder.<Void>failed()
181 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
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());
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>() {
211 public void onSuccess(Void voidInstance) {
212 result.set(RpcResultBuilder.<Void>success().build());
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());
228 public Future<RpcResult<Void>> addExternalTunnelEndpoint(
229 AddExternalTunnelEndpointInput input) {
230 // TODO Auto-generated method stub
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>() {
247 @Override public void onSuccess(Void voidInstance) {
248 result.set(RpcResultBuilder.<Void>success().build());
251 @Override public void onFailure(Throwable error) {
253 "Unable to create DcGatewayIp {} in datastore for ip " + input.getDestinationIp() + "and "
254 + "tunnel type " + input.getTunnelType();
256 result.set(RpcResultBuilder.<Void>failed()
257 .withError(RpcError.ErrorType.APPLICATION, msg, error).build());
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());
282 resultBld = RpcResultBuilder.failed();
285 return Futures.immediateFuture(resultBld.build());
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};
298 byte flags = (byte) 0x08;
299 vxLANHeader[0] = flags;
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);
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());
311 ListenableFuture<Void> installFlowResult =
312 mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
313 Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
316 public void onSuccess(Void voidInstance) {
317 result.set(RpcResultBuilder.<Void>success().build());
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)
328 // result.set(RpcResultBuilder.<Void>success().build());
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);
344 ListenableFuture<Void> installFlowResult =
345 mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
346 Futures.addCallback(installFlowResult, new FutureCallback<Void>() {
349 public void onSuccess(Void voidInstance) {
350 result.set(RpcResultBuilder.<Void>success().build());
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)
361 //result.set(RpcResultBuilder.<Void>success().build());
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};
372 byte flag = (byte) 0x08;
373 vxLANHeader[0] = flag;
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);
381 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
386 private String getFlowRef(long termSvcTable, int svcId) {
387 return String.valueOf(termSvcTable) + svcId;
391 public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
392 GetInternalOrExternalInterfaceNameInput input) {
393 RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
394 BigInteger srcDpn = input.getSourceDpid() ;
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));
401 Optional<ExternalTunnel> optExtTunnel = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
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()) ;
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());
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);
426 if (!optTunnel.isPresent()) {
427 optTunnel = ItmUtils.getInternalTunnelFromDS(srcDpn, teps.getDPNID(),
428 input.getTunnelType(), dataBroker);
430 if (optTunnel.isPresent()) {
431 InternalTunnel tunnel = optTunnel.get();
432 List<String> tunnelInterfaces = tunnel.getTunnelInterfaceNames();
433 if (tunnelInterfaces != null && !tunnelInterfaces.isEmpty()) {
434 GetInternalOrExternalInterfaceNameOutputBuilder
436 new GetInternalOrExternalInterfaceNameOutputBuilder()
437 .setInterfaceName(tunnelInterfaces.get(0));
438 resultBld = RpcResultBuilder.success();
439 resultBld.withResult(output.build());
441 LOG.error("No tunnel interface found between source DPN {} ans destination IP {}", srcDpn,
446 LOG.error("Tunnel not found for source DPN {} ans destination IP {}", srcDpn, dstIp);
451 return Futures.immediateFuture(resultBld.build());
454 @SuppressWarnings("checkstyle:IllegalCatch")
456 public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
457 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
458 boolean foundVxlanTzone = false;
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());
473 for (TransportZone tzone : transportZones.getTransportZone()) {
474 if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
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());
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)
490 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
491 //TO DO: add retry if it fails
493 transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
495 ListenableFuture<Void> futureCheck = transaction.submit();
496 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
498 @Override public void onSuccess(Void voidInstance) {
499 result.set(RpcResultBuilder.<Void>success().build());
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());
512 result.set(RpcResultBuilder.<Void>failed()
513 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
517 if (!foundVxlanTzone) {
518 result.set(RpcResultBuilder.<Void>failed()
519 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
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());
531 @SuppressWarnings("checkstyle:IllegalCatch")
533 public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
535 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
536 boolean foundVxlanTzone = false;
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());
553 for (TransportZone tzone : transportZones.getTransportZone()) {
554 if (!tzone.getTunnelType().equals(TunnelTypeVxlan.class)) {
557 String transportZone = tzone.getZoneName();
558 if (tzone.getSubnets() == null || tzone.getSubnets().isEmpty()) {
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)
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);
574 ListenableFuture<Void> futureCheck = transaction.submit();
575 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
577 @Override public void onSuccess(Void voidInstance) {
578 result.set(RpcResultBuilder.<Void>success().build());
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());
591 result.set(RpcResultBuilder.<Void>failed()
592 .withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
596 if (!foundVxlanTzone) {
597 result.set(RpcResultBuilder.<Void>failed()
598 .withError(RpcError.ErrorType.APPLICATION, "No VxLan TransportZones configured")
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());
610 @SuppressWarnings("checkstyle:IllegalCatch")
612 public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input) {
614 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
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());
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());
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);
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);
662 ListenableFuture<Void> futureCheck = writeTransaction.submit();
663 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
666 public void onSuccess(Void voidInstance) {
667 result.set(RpcResultBuilder.<Void>success().build());
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)
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());
687 @SuppressWarnings("checkstyle:IllegalCatch")
689 public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
691 final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
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());
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());
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);
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);
733 ListenableFuture<Void> futureCheck = transaction.submit();
734 Futures.addCallback(futureCheck, new FutureCallback<Void>() {
737 public void onSuccess(Void voidInstance) {
738 result.set(RpcResultBuilder.<Void>success().build());
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)
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());
759 public Future<RpcResult<IsTunnelInternalOrExternalOutput>> isTunnelInternalOrExternal(
760 IsTunnelInternalOrExternalInput input) {
761 RpcResultBuilder<IsTunnelInternalOrExternalOutput> resultBld;
762 String tunIfName = input.getTunnelInterfaceName();
764 IsTunnelInternalOrExternalOutputBuilder output = new IsTunnelInternalOrExternalOutputBuilder()
765 .setTunnelType(tunVal);
767 if (ItmUtils.ITM_CACHE.getInternalTunnel(tunIfName) != null) {
769 } else if (ItmUtils.ITM_CACHE.getExternalTunnel(tunIfName) != null) {
772 output.setTunnelType(tunVal);
773 resultBld = RpcResultBuilder.success();
774 resultBld.withResult(output.build());
775 return Futures.immediateFuture(resultBld.build());
779 public Future<RpcResult<IsDcgwPresentOutput>> isDcgwPresent(IsDcgwPresentInput input) {
780 RpcResultBuilder<IsDcgwPresentOutput> resultBld = RpcResultBuilder.success();
782 List<DcGatewayIp> dcGatewayIpList = ItmUtils.getDcGatewayIpList(dataBroker);
783 String dcgwIpStr = input.getDcgwIp();
784 IpAddress dcgwIpAddr = new IpAddress(dcgwIpStr.toCharArray());
787 if (dcGatewayIpList != null
788 && !dcGatewayIpList.isEmpty()
789 && dcGatewayIpList.contains(dcgwIpAddr)) {
792 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
793 resultBld.withResult(output.build());
797 IsDcgwPresentOutputBuilder output = new IsDcgwPresentOutputBuilder().setRetVal(retVal);
798 resultBld.withResult(output.build());
800 return Futures.immediateFuture(resultBld.build());
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());
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());
822 List<IpAddress> nexthopIpList = new ArrayList<>();
823 tunnelEndPointList.forEach(tunnelEndPoint -> {
824 nexthopIpList.add(tunnelEndPoint.getIpAddress());
827 GetDpnEndpointIpsOutputBuilder output = new GetDpnEndpointIpsOutputBuilder().setNexthopipList(nexthopIpList);
828 resultBld = RpcResultBuilder.success();
829 resultBld.withResult(output.build()) ;
830 return Futures.immediateFuture(resultBld.build());