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
9 package org.opendaylight.netvirt.vpnmanager;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.atomic.AtomicBoolean;
21 import java.util.concurrent.locks.ReentrantLock;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.apache.commons.lang3.tuple.ImmutablePair;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
28 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
31 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
32 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
33 import org.opendaylight.genius.utils.JvmGlobalLocks;
34 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
35 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
36 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEvent;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEventBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEvent;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEventBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventData;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventDataBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventData;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventDataBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddressesBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddressesKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.opendaylight.yangtools.yang.common.Uint32;
64 import org.opendaylight.yangtools.yang.common.Uint64;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
69 public class VpnFootprintService implements IVpnFootprintService {
71 private static final Logger LOG = LoggerFactory.getLogger(VpnFootprintService.class);
73 private final DataBroker dataBroker;
74 private final ManagedNewTransactionRunner txRunner;
75 private final IFibManager fibManager;
76 private final VpnOpDataSyncer vpnOpDataSyncer;
77 private final NotificationPublishService notificationPublishService;
78 private final IInterfaceManager interfaceManager;
79 private final VpnUtil vpnUtil;
82 public VpnFootprintService(final DataBroker dataBroker, final IFibManager fibManager,
83 final NotificationPublishService notificationPublishService, final VpnOpDataSyncer vpnOpDataSyncer,
84 final IInterfaceManager interfaceManager, VpnUtil vpnUtil) {
85 this.dataBroker = dataBroker;
86 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
87 this.fibManager = fibManager;
88 this.vpnOpDataSyncer = vpnOpDataSyncer;
89 this.notificationPublishService = notificationPublishService;
90 this.interfaceManager = interfaceManager;
91 this.vpnUtil = vpnUtil;
95 public void updateVpnToDpnMapping(Uint64 dpId, String vpnName, String primaryRd, @Nullable String interfaceName,
96 @Nullable ImmutablePair<IpAddresses.IpAddressSource,
97 String> ipAddressSourceValuePair, boolean add) {
98 Uint32 vpnId = vpnUtil.getVpnId(vpnName);
99 if (!dpId.equals(Uint64.ZERO)) {
101 // Considering the possibility of VpnInstanceOpData not being ready yet cause
103 // still in its creation process
104 if (VpnConstants.INVALID_ID.equals(vpnId)) {
105 LOG.error("updateVpnToDpnMapping: Operational data for vpn not ready. Waiting to update vpn"
106 + " footprint for vpn {} on dpn {} interface {}", vpnName, dpId, interfaceName);
107 vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName,
108 VpnConstants.PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS);
109 vpnId = vpnUtil.getVpnId(vpnName);
111 if (interfaceName != null) {
112 createOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
113 publishInterfaceAddedToVpnNotification(interfaceName, dpId, vpnName, vpnId);
115 createOrUpdateVpnToDpnListForIPAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
118 if (interfaceName != null) {
119 removeOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
120 publishInterfaceRemovedFromVpnNotification(interfaceName, dpId, vpnName, vpnId);
122 removeOrUpdateVpnToDpnListForIpAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
128 // Allow deprecated TransactionRunner calls for now
129 @SuppressWarnings("ForbidCertainMethod")
130 private void createOrUpdateVpnToDpnListForInterfaceName(Uint32 vpnId, String primaryRd, Uint64 dpnId,
131 String intfName, String vpnName) {
132 AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
133 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
134 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
136 // FIXME: separate this out somehow?
137 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
140 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
141 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
142 VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
143 Optional<VpnToDpnList> dpnInVpn = tx.read(LogicalDatastoreType.OPERATIONAL, id).checkedGet();
144 if (dpnInVpn.isPresent()) {
145 VpnToDpnList vpnToDpnList = dpnInVpn.get();
146 List<VpnInterfaces> vpnInterfaces = new ArrayList<>(vpnToDpnList.nonnullVpnInterfaces());
147 vpnInterfaces.add(vpnInterface);
148 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
149 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
151 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(),
152 WriteTransaction.CREATE_MISSING_PARENTS);
154 * If earlier state was inactive, it is considered new DPN coming back to the
157 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
158 newDpnOnVpn.set(true);
160 LOG.debug("createOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} interface {}"
161 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
163 List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
164 vpnInterfaces.add(vpnInterface);
165 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
166 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
168 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(),
169 WriteTransaction.CREATE_MISSING_PARENTS);
170 newDpnOnVpn.set(true);
171 LOG.debug("createOrUpdateVpnToDpnList: Creating vpn footprint for vpn {} vpnId {} interface {}"
172 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
176 } catch (InterruptedException | ExecutionException e) {
177 LOG.error("createOrUpdateVpnToDpnList: Error adding to dpnToVpnList for vpn {} vpnId {} interface {}"
178 + " dpn {}", vpnName, vpnId, intfName, dpnId, e);
179 throw new RuntimeException(e.getMessage(), e);
183 LOG.info("createOrUpdateVpnToDpnList: Created/Updated vpn footprint for vpn {} vpnId {} interfacName{}"
184 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
186 * Informing the FIB only after writeTxn is submitted successfully.
188 if (newDpnOnVpn.get()) {
189 if (vpnUtil.isVlan(intfName)) {
190 if (!vpnUtil.shouldPopulateFibForVlan(vpnName, null, dpnId)) {
194 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
195 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
196 LOG.info("createOrUpdateVpnToDpnList: Sent populateFib event for new dpn {} in VPN {} for interface {}",
197 dpnId, vpnName, intfName);
201 // Allow deprecated TransactionRunner calls for now
202 @SuppressWarnings("ForbidCertainMethod")
203 private void createOrUpdateVpnToDpnListForIPAddress(Uint32 vpnId, String primaryRd, Uint64 dpnId,
204 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
205 AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
206 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
207 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
209 // FIXME: separate this out somehow?
210 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
213 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
214 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
215 IpAddressesBuilder ipAddressesBldr = new IpAddressesBuilder()
216 .setIpAddressSource(ipAddressSourceValuePair.getKey());
217 ipAddressesBldr.withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()));
218 ipAddressesBldr.setIpAddress(ipAddressSourceValuePair.getValue());
219 Optional<VpnToDpnList> dpnInVpn = tx.read(LogicalDatastoreType.OPERATIONAL, id).checkedGet();
220 if (dpnInVpn.isPresent()) {
221 VpnToDpnList vpnToDpnList = dpnInVpn.get();
222 List<IpAddresses> ipAddresses = new ArrayList<>(vpnToDpnList.nonnullIpAddresses());
223 ipAddresses.add(ipAddressesBldr.build());
224 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
225 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
227 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
229 * If earlier state was inactive, it is considered new DPN coming back to the
232 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
233 newDpnOnVpn.set(true);
236 List<IpAddresses> ipAddresses = new ArrayList<>();
237 ipAddresses.add(ipAddressesBldr.build());
238 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
239 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
240 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
241 newDpnOnVpn.set(true);
246 } catch (InterruptedException | ExecutionException e) {
247 LOG.error("createOrUpdateVpnToDpnListForIPAddress: Error adding to dpnToVpnList for vpn {}"
248 + " ipAddresses {} dpn {}", vpnName, ipAddressSourceValuePair.getValue(), dpnId, e);
249 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
254 * Informing the Fib only after writeTxn is submitted successfuly.
256 if (newDpnOnVpn.get()) {
257 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
258 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
259 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
263 // Allow deprecated TransactionRunner calls for now
264 @SuppressWarnings("ForbidCertainMethod")
265 private void removeOrUpdateVpnToDpnListForInterfaceName(Uint32 vpnId, String rd, Uint64 dpnId, String intfName,
267 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
268 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
269 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
271 // FIXME: separate this out somehow?
272 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
276 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
277 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
278 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(LogicalDatastoreType.OPERATIONAL, id)
280 if (!dpnInVpnOpt.isPresent()) {
281 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={}"
282 + " rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
285 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
286 List<VpnInterfaces> vpnInterfaces = new ArrayList<>(dpnInVpn.nonnullVpnInterfaces());
287 if (vpnInterfaces == null) {
288 LOG.error("Could not find vpnInterfaces for DpnInVpn map for VPN=[name={} rd={} id={}] and "
289 + "dpnId={}", vpnName, rd, id, dpnId);
292 VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
293 if (vpnInterfaces.remove(currVpnInterface)) {
294 if (vpnInterfaces.isEmpty()) {
295 List<IpAddresses> ipAddresses = dpnInVpn.getIpAddresses();
296 VpnToDpnListBuilder dpnInVpnBuilder =
297 new VpnToDpnListBuilder(dpnInVpn).setVpnInterfaces(null);
298 if (ipAddresses == null || ipAddresses.isEmpty()) {
299 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
300 lastDpnOnVpn.set(true);
302 LOG.error("removeOrUpdateVpnToDpnList: vpn interfaces are empty but ip addresses"
303 + " are present for the vpn {} in dpn {} interface {}", vpnName, dpnId,
306 LOG.debug("removeOrUpdateVpnToDpnList: Removing vpn footprint for vpn {} vpnId {} "
307 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
308 tx.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(),
309 WriteTransaction.CREATE_MISSING_PARENTS);
312 tx.delete(LogicalDatastoreType.OPERATIONAL,
313 id.child(VpnInterfaces.class, new VpnInterfacesKey(intfName)));
314 LOG.debug("removeOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} "
315 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
320 } catch (InterruptedException | ExecutionException e) {
321 LOG.error("removeOrUpdateVpnToDpnList: Error removing from dpnToVpnList for vpn {} vpnId {}"
322 + " interface {} dpn {}", vpnName, vpnId, intfName, dpnId, e);
323 throw new RuntimeException(e.getMessage(), e);
325 // Ends synchronized block
326 LOG.info("removeOrUpdateVpnToDpnList: Updated/Removed vpn footprint for vpn {} vpnId {} interface {},"
327 + " on dpn {}", vpnName, vpnName, intfName, dpnId);
329 if (lastDpnOnVpn.get()) {
330 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
331 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
332 LOG.info("removeOrUpdateVpnToDpnList: Sent cleanup event for dpn {} in VPN {} vpnId {} interface {}",
333 dpnId, vpnName, vpnId, intfName);
340 // Allow deprecated TransactionRunner calls for now
341 @SuppressWarnings("ForbidCertainMethod")
342 private void removeOrUpdateVpnToDpnListForIpAddress(Uint32 vpnId, String rd, Uint64 dpnId,
343 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
344 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
345 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
346 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
348 // FIXME: separate this out somehow?
349 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
352 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
353 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
355 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(LogicalDatastoreType.OPERATIONAL, id)
357 if (!dpnInVpnOpt.isPresent()) {
358 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={} "
359 + "rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
362 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
363 List<IpAddresses> ipAddresses = new ArrayList<>(dpnInVpn.nonnullIpAddresses());
364 if (ipAddresses == null) {
365 LOG.info("Could not find ipAddresses for DpnInVpn map for VPN=[name={} rd={} id={}] "
366 + "and dpnId={}", vpnName, rd, id, dpnId);
370 IpAddresses currIpAddress = new IpAddressesBuilder()
371 .withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()))
372 .setIpAddressSource(ipAddressSourceValuePair.getKey()).build();
373 if (ipAddresses.remove(currIpAddress)) {
374 if (ipAddresses.isEmpty()) {
375 List<VpnInterfaces> vpnInterfaces = dpnInVpn.getVpnInterfaces();
376 VpnToDpnListBuilder dpnInVpnBuilder =
377 new VpnToDpnListBuilder(dpnInVpn).setIpAddresses(null);
378 if (vpnInterfaces == null || vpnInterfaces.isEmpty()) {
379 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
380 lastDpnOnVpn.set(true);
382 LOG.warn("ip addresses are empty but vpn interfaces are present for the vpn {} in "
383 + "dpn {}", vpnName, dpnId);
385 tx.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
388 tx.delete(LogicalDatastoreType.OPERATIONAL, id.child(IpAddresses.class,
389 new IpAddressesKey(ipAddressSourceValuePair.getValue())));
395 } catch (InterruptedException | ExecutionException e) {
396 LOG.error("Error removing from dpnToVpnList for vpn {} Ipaddress {} dpn {}", vpnName,
397 ipAddressSourceValuePair.getValue(), dpnId, e);
398 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
403 if (lastDpnOnVpn.get()) {
404 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
405 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
406 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
410 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
411 justification = "https://github.com/spotbugs/spotbugs/issues/811")
412 private void publishAddNotification(final Uint64 dpnId, final String vpnName, final String rd) {
413 LOG.debug("publishAddNotification: Sending notification for add dpn {} in vpn {} rd {} event ", dpnId, vpnName,
415 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
416 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
417 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
418 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
420 public void onFailure(Throwable error) {
421 LOG.error("publishAddNotification: Error in notifying listeners for add dpn {} in vpn {} rd {} event ",
422 dpnId, vpnName, rd, error);
426 public void onSuccess(Object arg) {
427 LOG.info("publishAddNotification: Successful in notifying listeners for add dpn {} in vpn {} rd {}"
428 + " event ", dpnId, vpnName, rd);
430 }, MoreExecutors.directExecutor());
433 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
434 justification = "https://github.com/spotbugs/spotbugs/issues/811")
435 private void publishRemoveNotification(final Uint64 dpnId, final String vpnName, final String rd) {
436 LOG.debug("publishRemoveNotification: Sending notification for remove dpn {} in vpn {} rd {} event ", dpnId,
438 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
439 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
440 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
441 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
443 public void onFailure(Throwable error) {
444 LOG.error("publishRemoveNotification: Error in notifying listeners for remove dpn {} in vpn {} rd {}"
445 + " event ", dpnId, vpnName, rd, error);
449 public void onSuccess(Object arg) {
450 LOG.info("publishRemoveNotification: Successful in notifying listeners for remove dpn {} in vpn {}"
451 + " rd {} event ", dpnId, vpnName, rd);
453 }, MoreExecutors.directExecutor());
456 private void publishInterfaceAddedToVpnNotification(String interfaceName, Uint64 dpnId, String vpnName,
458 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for addition of interface {} on dpn {}"
459 + " for vpn {}", interfaceName, dpnId, vpnName);
460 AddInterfaceEventData data = new AddInterfaceEventDataBuilder().setInterfaceName(interfaceName).setVpnId(vpnId)
461 .setDpnId(dpnId).build();
462 AddInterfaceToDpnOnVpnEvent event = new AddInterfaceToDpnOnVpnEventBuilder().setAddInterfaceEventData(data)
464 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
465 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
467 public void onFailure(Throwable error) {
468 LOG.warn("publishInterfaceAddedToVpnNotification: Error in notifying listeners for add interface {}"
469 + " on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName, error);
473 public void onSuccess(Object arg) {
474 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for add"
475 + " interface {} on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
477 }, MoreExecutors.directExecutor());
480 private void publishInterfaceRemovedFromVpnNotification(String interfaceName, Uint64 dpnId, String vpnName,
482 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for removal of interface {}"
483 + " from dpn {} for vpn {}", interfaceName, dpnId, vpnName);
484 RemoveInterfaceEventData data = new RemoveInterfaceEventDataBuilder().setInterfaceName(interfaceName)
485 .setVpnId(vpnId).setDpnId(dpnId).build();
486 RemoveInterfaceFromDpnOnVpnEvent event = new RemoveInterfaceFromDpnOnVpnEventBuilder()
487 .setRemoveInterfaceEventData(data).build();
488 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
489 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
491 public void onFailure(Throwable error) {
493 "publishInterfaceAddedToVpnNotification: Error in notifying listeners"
494 + " for removing interface {} from dpn {} in vpn {} event ",
495 interfaceName, dpnId, vpnName, error);
499 public void onSuccess(Object arg) {
500 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for removing"
501 + " interface {} from dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
503 }, MoreExecutors.directExecutor());
507 * JobCallback class is used as a future callback for main and rollback workers
508 * to handle success and failure.
510 private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
511 private final Logger log = LoggerFactory.getLogger(DpnEnterExitVpnWorker.class);
517 DpnEnterExitVpnWorker(Uint64 dpnId, String vpnName, String rd, boolean entered) {
518 this.entered = entered;
520 this.vpnName = vpnName;
525 * This implies that all the future instances have returned success. -- TODO:
529 public void onSuccess(List<Void> voids) {
531 publishAddNotification(dpnId, vpnName, rd);
532 log.info("onSuccess: FootPrint established for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
534 publishRemoveNotification(dpnId, vpnName, rd);
535 log.info("onSuccess: FootPrint cleared for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
540 * This method is used to handle failure callbacks. If more retry needed, the
541 * retrycount is decremented and mainworker is executed again. After retries
542 * completed, rollbackworker is executed. If rollbackworker fails, this is a
543 * double-fault. Double fault is logged and ignored.
546 public void onFailure(Throwable throwable) {
547 log.info("onFailure: Failed to establish/clear footprint for vpn {} rd {} on dpn {} ", vpnName, rd, dpnId,
552 boolean isVpnFootPrintCleared(VpnInstanceOpDataEntry vpnInstanceOpData) {
553 return vpnInstanceOpData.getVpnToDpnList() == null || vpnInstanceOpData.getVpnToDpnList().isEmpty();