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 static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12 import static org.opendaylight.mdsal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Optional;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.atomic.AtomicBoolean;
24 import java.util.concurrent.locks.ReentrantLock;
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27 import org.apache.commons.lang3.tuple.ImmutablePair;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
31 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
32 import org.opendaylight.genius.utils.JvmGlobalLocks;
33 import org.opendaylight.mdsal.binding.api.DataBroker;
34 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
35 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
36 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
37 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEvent;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEventBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEvent;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEventBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventData;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventDataBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventData;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventDataBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
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.IpAddresses;
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.IpAddressesBuilder;
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.IpAddressesKey;
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.VpnInterfaces;
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.VpnInterfacesBuilder;
62 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;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.opendaylight.yangtools.yang.common.Uint32;
65 import org.opendaylight.yangtools.yang.common.Uint64;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
70 public class VpnFootprintService implements IVpnFootprintService {
72 private static final Logger LOG = LoggerFactory.getLogger(VpnFootprintService.class);
74 private final DataBroker dataBroker;
75 private final ManagedNewTransactionRunner txRunner;
76 private final IFibManager fibManager;
77 private final VpnOpDataSyncer vpnOpDataSyncer;
78 private final NotificationPublishService notificationPublishService;
79 private final IInterfaceManager interfaceManager;
80 private final VpnUtil vpnUtil;
83 public VpnFootprintService(final DataBroker dataBroker, final IFibManager fibManager,
84 final NotificationPublishService notificationPublishService, final VpnOpDataSyncer vpnOpDataSyncer,
85 final IInterfaceManager interfaceManager, VpnUtil vpnUtil) {
86 this.dataBroker = dataBroker;
87 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
88 this.fibManager = fibManager;
89 this.vpnOpDataSyncer = vpnOpDataSyncer;
90 this.notificationPublishService = notificationPublishService;
91 this.interfaceManager = interfaceManager;
92 this.vpnUtil = vpnUtil;
96 public void updateVpnToDpnMapping(Uint64 dpId, String vpnName, String primaryRd, @Nullable String interfaceName,
97 @Nullable ImmutablePair<IpAddresses.IpAddressSource,
98 String> ipAddressSourceValuePair, boolean add) {
99 Uint32 vpnId = vpnUtil.getVpnId(vpnName);
100 if (!dpId.equals(Uint64.ZERO)) {
102 // Considering the possibility of VpnInstanceOpData not being ready yet cause
104 // still in its creation process
105 if (VpnConstants.INVALID_ID.equals(vpnId)) {
106 LOG.error("updateVpnToDpnMapping: Operational data for vpn not ready. Waiting to update vpn"
107 + " footprint for vpn {} on dpn {} interface {}", vpnName, dpId, interfaceName);
108 vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName,
109 VpnConstants.PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS);
110 vpnId = vpnUtil.getVpnId(vpnName);
112 if (interfaceName != null) {
113 createOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
114 publishInterfaceAddedToVpnNotification(interfaceName, dpId, vpnName, vpnId);
116 createOrUpdateVpnToDpnListForIPAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
119 if (interfaceName != null) {
120 removeOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
121 publishInterfaceRemovedFromVpnNotification(interfaceName, dpId, vpnName, vpnId);
123 removeOrUpdateVpnToDpnListForIpAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
129 private void createOrUpdateVpnToDpnListForInterfaceName(Uint32 vpnId, String primaryRd, Uint64 dpnId,
130 String intfName, String vpnName) {
131 AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
132 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
133 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
135 // FIXME: separate this out somehow?
136 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
139 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
140 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
141 VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
142 Optional<VpnToDpnList> dpnInVpn = tx.read(id).get();
143 if (dpnInVpn.isPresent()) {
144 VpnToDpnList vpnToDpnList = dpnInVpn.get();
145 List<VpnInterfaces> vpnInterfaces = new ArrayList<>(vpnToDpnList.nonnullVpnInterfaces());
146 vpnInterfaces.add(vpnInterface);
147 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
148 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
150 tx.put(id, vpnToDpnListBuilder.build(), CREATE_MISSING_PARENTS);
152 * If earlier state was inactive, it is considered new DPN coming back to the
155 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
156 newDpnOnVpn.set(true);
158 LOG.debug("createOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} interface {}"
159 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
161 List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
162 vpnInterfaces.add(vpnInterface);
163 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
164 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
166 tx.put(id, vpnToDpnListBuilder.build(), CREATE_MISSING_PARENTS);
167 newDpnOnVpn.set(true);
168 LOG.debug("createOrUpdateVpnToDpnList: Creating vpn footprint for vpn {} vpnId {} interface {}"
169 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
173 } catch (InterruptedException | ExecutionException e) {
174 LOG.error("createOrUpdateVpnToDpnList: Error adding to dpnToVpnList for vpn {} vpnId {} interface {}"
175 + " dpn {}", vpnName, vpnId, intfName, dpnId, e);
176 throw new RuntimeException(e.getMessage(), e);
180 LOG.info("createOrUpdateVpnToDpnList: Created/Updated vpn footprint for vpn {} vpnId {} interfacName{}"
181 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
183 * Informing the FIB only after writeTxn is submitted successfully.
185 if (newDpnOnVpn.get()) {
186 if (vpnUtil.isVlan(intfName)) {
187 if (!vpnUtil.shouldPopulateFibForVlan(vpnName, null, dpnId)) {
191 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
192 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
193 LOG.info("createOrUpdateVpnToDpnList: Sent populateFib event for new dpn {} in VPN {} for interface {}",
194 dpnId, vpnName, intfName);
198 private void createOrUpdateVpnToDpnListForIPAddress(Uint32 vpnId, String primaryRd, Uint64 dpnId,
199 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
200 AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
201 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
202 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
204 // FIXME: separate this out somehow?
205 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
208 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
209 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
210 IpAddressesBuilder ipAddressesBldr = new IpAddressesBuilder()
211 .setIpAddressSource(ipAddressSourceValuePair.getKey());
212 ipAddressesBldr.withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()));
213 ipAddressesBldr.setIpAddress(ipAddressSourceValuePair.getValue());
214 Optional<VpnToDpnList> dpnInVpn = tx.read(id).get();
215 if (dpnInVpn.isPresent()) {
216 VpnToDpnList vpnToDpnList = dpnInVpn.get();
217 List<IpAddresses> ipAddresses = new ArrayList<>(vpnToDpnList.nonnullIpAddresses());
218 ipAddresses.add(ipAddressesBldr.build());
219 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
220 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
222 tx.put(id, vpnToDpnListBuilder.build(), CREATE_MISSING_PARENTS);
224 * If earlier state was inactive, it is considered new DPN coming back to the
227 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
228 newDpnOnVpn.set(true);
231 List<IpAddresses> ipAddresses = new ArrayList<>();
232 ipAddresses.add(ipAddressesBldr.build());
233 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
234 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
235 tx.put(id, vpnToDpnListBuilder.build(), CREATE_MISSING_PARENTS);
236 newDpnOnVpn.set(true);
241 } catch (InterruptedException | ExecutionException e) {
242 LOG.error("createOrUpdateVpnToDpnListForIPAddress: Error adding to dpnToVpnList for vpn {}"
243 + " ipAddresses {} dpn {}", vpnName, ipAddressSourceValuePair.getValue(), dpnId, e);
244 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
249 * Informing the Fib only after writeTxn is submitted successfuly.
251 if (newDpnOnVpn.get()) {
252 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
253 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
254 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
258 private void removeOrUpdateVpnToDpnListForInterfaceName(Uint32 vpnId, String rd, Uint64 dpnId, String intfName,
260 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
261 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
262 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
264 // FIXME: separate this out somehow?
265 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
269 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
270 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
271 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(id).get();
272 if (!dpnInVpnOpt.isPresent()) {
273 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={}"
274 + " rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
277 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
278 List<VpnInterfaces> vpnInterfaces = new ArrayList<>(dpnInVpn.nonnullVpnInterfaces());
279 if (vpnInterfaces == null) {
280 LOG.error("Could not find vpnInterfaces for DpnInVpn map for VPN=[name={} rd={} id={}] and "
281 + "dpnId={}", vpnName, rd, id, dpnId);
284 VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
285 if (vpnInterfaces.remove(currVpnInterface)) {
286 if (vpnInterfaces.isEmpty()) {
287 List<IpAddresses> ipAddresses = dpnInVpn.getIpAddresses();
288 VpnToDpnListBuilder dpnInVpnBuilder =
289 new VpnToDpnListBuilder(dpnInVpn).setVpnInterfaces(null);
290 if (ipAddresses == null || ipAddresses.isEmpty()) {
291 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
292 lastDpnOnVpn.set(true);
294 LOG.error("removeOrUpdateVpnToDpnList: vpn interfaces are empty but ip addresses"
295 + " are present for the vpn {} in dpn {} interface {}", vpnName, dpnId,
298 LOG.debug("removeOrUpdateVpnToDpnList: Removing vpn footprint for vpn {} vpnId {} "
299 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
300 tx.put(id, dpnInVpnBuilder.build(), CREATE_MISSING_PARENTS);
303 tx.delete(id.child(VpnInterfaces.class, new VpnInterfacesKey(intfName)));
304 LOG.debug("removeOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} "
305 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
310 } catch (InterruptedException | ExecutionException e) {
311 LOG.error("removeOrUpdateVpnToDpnList: Error removing from dpnToVpnList for vpn {} vpnId {}"
312 + " interface {} dpn {}", vpnName, vpnId, intfName, dpnId, e);
313 throw new RuntimeException(e.getMessage(), e);
315 // Ends synchronized block
316 LOG.info("removeOrUpdateVpnToDpnList: Updated/Removed vpn footprint for vpn {} vpnId {} interface {},"
317 + " on dpn {}", vpnName, vpnName, intfName, dpnId);
319 if (lastDpnOnVpn.get()) {
320 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
321 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
322 LOG.info("removeOrUpdateVpnToDpnList: Sent cleanup event for dpn {} in VPN {} vpnId {} interface {}",
323 dpnId, vpnName, vpnId, intfName);
330 private void removeOrUpdateVpnToDpnListForIpAddress(Uint32 vpnId, String rd, Uint64 dpnId,
331 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
332 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
333 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
334 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
336 // FIXME: separate this out somehow?
337 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
340 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
341 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
343 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(id).get();
344 if (!dpnInVpnOpt.isPresent()) {
345 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={} "
346 + "rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
349 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
350 List<IpAddresses> ipAddresses = new ArrayList<>(dpnInVpn.nonnullIpAddresses());
351 if (ipAddresses == null) {
352 LOG.info("Could not find ipAddresses for DpnInVpn map for VPN=[name={} rd={} id={}] "
353 + "and dpnId={}", vpnName, rd, id, dpnId);
357 IpAddresses currIpAddress = new IpAddressesBuilder()
358 .withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()))
359 .setIpAddressSource(ipAddressSourceValuePair.getKey()).build();
360 if (ipAddresses.remove(currIpAddress)) {
361 if (ipAddresses.isEmpty()) {
362 List<VpnInterfaces> vpnInterfaces = dpnInVpn.getVpnInterfaces();
363 VpnToDpnListBuilder dpnInVpnBuilder =
364 new VpnToDpnListBuilder(dpnInVpn).setIpAddresses(null);
365 if (vpnInterfaces == null || vpnInterfaces.isEmpty()) {
366 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
367 lastDpnOnVpn.set(true);
369 LOG.warn("ip addresses are empty but vpn interfaces are present for the vpn {} in "
370 + "dpn {}", vpnName, dpnId);
372 tx.put(id, dpnInVpnBuilder.build(), CREATE_MISSING_PARENTS);
375 tx.delete(id.child(IpAddresses.class, new IpAddressesKey(ipAddressSourceValuePair.getValue())));
381 } catch (InterruptedException | ExecutionException e) {
382 LOG.error("Error removing from dpnToVpnList for vpn {} Ipaddress {} dpn {}", vpnName,
383 ipAddressSourceValuePair.getValue(), dpnId, e);
384 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
389 if (lastDpnOnVpn.get()) {
390 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
391 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
392 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
396 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
397 justification = "https://github.com/spotbugs/spotbugs/issues/811")
398 private void publishAddNotification(final Uint64 dpnId, final String vpnName, final String rd) {
399 LOG.debug("publishAddNotification: Sending notification for add dpn {} in vpn {} rd {} event ", dpnId, vpnName,
401 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
402 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
403 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
404 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
406 public void onFailure(Throwable error) {
407 LOG.error("publishAddNotification: Error in notifying listeners for add dpn {} in vpn {} rd {} event ",
408 dpnId, vpnName, rd, error);
412 public void onSuccess(Object arg) {
413 LOG.info("publishAddNotification: Successful in notifying listeners for add dpn {} in vpn {} rd {}"
414 + " event ", dpnId, vpnName, rd);
416 }, MoreExecutors.directExecutor());
419 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
420 justification = "https://github.com/spotbugs/spotbugs/issues/811")
421 private void publishRemoveNotification(final Uint64 dpnId, final String vpnName, final String rd) {
422 LOG.debug("publishRemoveNotification: Sending notification for remove dpn {} in vpn {} rd {} event ", dpnId,
424 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
425 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
426 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
427 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
429 public void onFailure(Throwable error) {
430 LOG.error("publishRemoveNotification: Error in notifying listeners for remove dpn {} in vpn {} rd {}"
431 + " event ", dpnId, vpnName, rd, error);
435 public void onSuccess(Object arg) {
436 LOG.info("publishRemoveNotification: Successful in notifying listeners for remove dpn {} in vpn {}"
437 + " rd {} event ", dpnId, vpnName, rd);
439 }, MoreExecutors.directExecutor());
442 private void publishInterfaceAddedToVpnNotification(String interfaceName, Uint64 dpnId, String vpnName,
444 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for addition of interface {} on dpn {}"
445 + " for vpn {}", interfaceName, dpnId, vpnName);
446 AddInterfaceEventData data = new AddInterfaceEventDataBuilder().setInterfaceName(interfaceName).setVpnId(vpnId)
447 .setDpnId(dpnId).build();
448 AddInterfaceToDpnOnVpnEvent event = new AddInterfaceToDpnOnVpnEventBuilder().setAddInterfaceEventData(data)
450 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
451 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
453 public void onFailure(Throwable error) {
454 LOG.warn("publishInterfaceAddedToVpnNotification: Error in notifying listeners for add interface {}"
455 + " on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName, error);
459 public void onSuccess(Object arg) {
460 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for add"
461 + " interface {} on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
463 }, MoreExecutors.directExecutor());
466 private void publishInterfaceRemovedFromVpnNotification(String interfaceName, Uint64 dpnId, String vpnName,
468 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for removal of interface {}"
469 + " from dpn {} for vpn {}", interfaceName, dpnId, vpnName);
470 RemoveInterfaceEventData data = new RemoveInterfaceEventDataBuilder().setInterfaceName(interfaceName)
471 .setVpnId(vpnId).setDpnId(dpnId).build();
472 RemoveInterfaceFromDpnOnVpnEvent event = new RemoveInterfaceFromDpnOnVpnEventBuilder()
473 .setRemoveInterfaceEventData(data).build();
474 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
475 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
477 public void onFailure(Throwable error) {
479 "publishInterfaceAddedToVpnNotification: Error in notifying listeners"
480 + " for removing interface {} from dpn {} in vpn {} event ",
481 interfaceName, dpnId, vpnName, error);
485 public void onSuccess(Object arg) {
486 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for removing"
487 + " interface {} from dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
489 }, MoreExecutors.directExecutor());
493 * JobCallback class is used as a future callback for main and rollback workers
494 * to handle success and failure.
496 private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
497 private final Logger log = LoggerFactory.getLogger(DpnEnterExitVpnWorker.class);
503 DpnEnterExitVpnWorker(Uint64 dpnId, String vpnName, String rd, boolean entered) {
504 this.entered = entered;
506 this.vpnName = vpnName;
511 * This implies that all the future instances have returned success. -- TODO:
515 public void onSuccess(List<Void> voids) {
517 publishAddNotification(dpnId, vpnName, rd);
518 log.info("onSuccess: FootPrint established for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
520 publishRemoveNotification(dpnId, vpnName, rd);
521 log.info("onSuccess: FootPrint cleared for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
526 * This method is used to handle failure callbacks. If more retry needed, the
527 * retrycount is decremented and mainworker is executed again. After retries
528 * completed, rollbackworker is executed. If rollbackworker fails, this is a
529 * double-fault. Double fault is logged and ignored.
532 public void onFailure(Throwable throwable) {
533 log.info("onFailure: Failed to establish/clear footprint for vpn {} rd {} on dpn {} ", vpnName, rd, dpnId,
538 boolean isVpnFootPrintCleared(VpnInstanceOpDataEntry vpnInstanceOpData) {
539 return vpnInstanceOpData.getVpnToDpnList() == null || vpnInstanceOpData.getVpnToDpnList().isEmpty();