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.mdsal.binding.util.Datastore.OPERATIONAL;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.MoreExecutors;
17 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.List;
22 import java.util.Optional;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.atomic.AtomicBoolean;
25 import java.util.concurrent.locks.ReentrantLock;
26 import javax.inject.Inject;
27 import javax.inject.Singleton;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
31 import org.opendaylight.genius.utils.JvmGlobalLocks;
32 import org.opendaylight.mdsal.binding.api.DataBroker;
33 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
34 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
35 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
36 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
37 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
38 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEvent;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEventBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEvent;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEventBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventData;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventDataBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventData;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventDataBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
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.IpAddresses;
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.IpAddressesBuilder;
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.IpAddressesKey;
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.VpnInterfaces;
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.VpnInterfacesBuilder;
63 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;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.opendaylight.yangtools.yang.common.Uint32;
66 import org.opendaylight.yangtools.yang.common.Uint64;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
71 public class VpnFootprintService implements IVpnFootprintService {
73 private static final Logger LOG = LoggerFactory.getLogger(VpnFootprintService.class);
75 private final DataBroker dataBroker;
76 private final ManagedNewTransactionRunner txRunner;
77 private final IFibManager fibManager;
78 private final VpnOpDataSyncer vpnOpDataSyncer;
79 private final NotificationPublishService notificationPublishService;
80 private final IInterfaceManager interfaceManager;
81 private final VpnUtil vpnUtil;
84 public VpnFootprintService(final DataBroker dataBroker, final IFibManager fibManager,
85 final NotificationPublishService notificationPublishService, final VpnOpDataSyncer vpnOpDataSyncer,
86 final IInterfaceManager interfaceManager, VpnUtil vpnUtil) {
87 this.dataBroker = dataBroker;
88 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
89 this.fibManager = fibManager;
90 this.vpnOpDataSyncer = vpnOpDataSyncer;
91 this.notificationPublishService = notificationPublishService;
92 this.interfaceManager = interfaceManager;
93 this.vpnUtil = vpnUtil;
97 public void updateVpnToDpnMapping(Uint64 dpId, String vpnName, String primaryRd, @Nullable String interfaceName,
98 @Nullable ImmutablePair<IpAddresses.IpAddressSource,
99 String> ipAddressSourceValuePair, boolean add) {
100 Uint32 vpnId = vpnUtil.getVpnId(vpnName);
101 if (!dpId.equals(Uint64.ZERO)) {
103 // Considering the possibility of VpnInstanceOpData not being ready yet cause
105 // still in its creation process
106 if (VpnConstants.INVALID_ID.equals(vpnId)) {
107 LOG.error("updateVpnToDpnMapping: Operational data for vpn not ready. Waiting to update vpn"
108 + " footprint for vpn {} on dpn {} interface {}", vpnName, dpId, interfaceName);
109 vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName,
110 VpnConstants.PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS);
111 vpnId = vpnUtil.getVpnId(vpnName);
113 if (interfaceName != null) {
114 createOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
115 publishInterfaceAddedToVpnNotification(interfaceName, dpId, vpnName, vpnId);
117 createOrUpdateVpnToDpnListForIPAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
120 if (interfaceName != null) {
121 removeOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
122 publishInterfaceRemovedFromVpnNotification(interfaceName, dpId, vpnName, vpnId);
124 removeOrUpdateVpnToDpnListForIpAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
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<?> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
141 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
142 VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
143 Optional<VpnToDpnList> dpnInVpn = tx.read(id).get();
144 if (dpnInVpn.isPresent()) {
145 VpnToDpnList vpnToDpnList = dpnInVpn.get();
146 List<VpnInterfaces> vpnInterfaces = new ArrayList<>(vpnToDpnList.nonnullVpnInterfaces().values());
147 vpnInterfaces.add(vpnInterface);
148 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
149 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
151 tx.mergeParentStructurePut(id, vpnToDpnListBuilder.build());
153 * If earlier state was inactive, it is considered new DPN coming back to the
156 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
157 newDpnOnVpn.set(true);
159 LOG.debug("createOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} interface {}"
160 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
162 List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
163 vpnInterfaces.add(vpnInterface);
164 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
165 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
167 tx.mergeParentStructurePut(id, vpnToDpnListBuilder.build());
168 newDpnOnVpn.set(true);
169 LOG.debug("createOrUpdateVpnToDpnList: Creating vpn footprint for vpn {} vpnId {} interface {}"
170 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
174 } catch (InterruptedException | ExecutionException e) {
175 LOG.error("createOrUpdateVpnToDpnList: Error adding to dpnToVpnList for vpn {} vpnId {} interface {}"
176 + " dpn {}", vpnName, vpnId, intfName, dpnId, e);
177 throw new RuntimeException(e.getMessage(), e);
181 LOG.info("createOrUpdateVpnToDpnList: Created/Updated vpn footprint for vpn {} vpnId {} interfacName{}"
182 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
184 * Informing the FIB only after writeTxn is submitted successfully.
186 if (newDpnOnVpn.get()) {
187 if (vpnUtil.isVlan(intfName)) {
188 if (!vpnUtil.shouldPopulateFibForVlan(vpnName, null, dpnId)) {
192 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
193 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
194 LOG.info("createOrUpdateVpnToDpnList: Sent populateFib event for new dpn {} in VPN {} for interface {}",
195 dpnId, vpnName, intfName);
199 private void createOrUpdateVpnToDpnListForIPAddress(Uint32 vpnId, String primaryRd, Uint64 dpnId,
200 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
201 AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
202 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
203 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
205 // FIXME: separate this out somehow?
206 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
209 ListenableFuture<?> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
210 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
211 IpAddressesBuilder ipAddressesBldr = new IpAddressesBuilder()
212 .setIpAddressSource(ipAddressSourceValuePair.getKey());
213 ipAddressesBldr.withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()));
214 ipAddressesBldr.setIpAddress(ipAddressSourceValuePair.getValue());
215 Optional<VpnToDpnList> dpnInVpn = tx.read(id).get();
216 if (dpnInVpn.isPresent()) {
217 VpnToDpnList vpnToDpnList = dpnInVpn.get();
218 List<IpAddresses> ipAddresses = new ArrayList<>(vpnToDpnList.nonnullIpAddresses().values());
219 ipAddresses.add(ipAddressesBldr.build());
220 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
221 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
223 tx.mergeParentStructurePut(id, vpnToDpnListBuilder.build());
225 * If earlier state was inactive, it is considered new DPN coming back to the
228 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
229 newDpnOnVpn.set(true);
232 List<IpAddresses> ipAddresses = new ArrayList<>();
233 ipAddresses.add(ipAddressesBldr.build());
234 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
235 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
236 tx.mergeParentStructurePut(id, vpnToDpnListBuilder.build());
237 newDpnOnVpn.set(true);
242 } catch (InterruptedException | ExecutionException e) {
243 LOG.error("createOrUpdateVpnToDpnListForIPAddress: Error adding to dpnToVpnList for vpn {}"
244 + " ipAddresses {} dpn {}", vpnName, ipAddressSourceValuePair.getValue(), dpnId, e);
245 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
250 * Informing the Fib only after writeTxn is submitted successfuly.
252 if (newDpnOnVpn.get()) {
253 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
254 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
255 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
259 private void removeOrUpdateVpnToDpnListForInterfaceName(Uint32 vpnId, String rd, Uint64 dpnId, String intfName,
261 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
262 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
263 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
265 // FIXME: separate this out somehow?
266 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
270 ListenableFuture<?> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
271 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
272 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(id).get();
273 if (!dpnInVpnOpt.isPresent()) {
274 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={}"
275 + " rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
278 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
279 List<VpnInterfaces> vpnInterfaces = new ArrayList<>(dpnInVpn.nonnullVpnInterfaces().values());
280 if (vpnInterfaces == null) {
281 LOG.error("Could not find vpnInterfaces for DpnInVpn map for VPN=[name={} rd={} id={}] and "
282 + "dpnId={}", vpnName, rd, id, dpnId);
285 VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
286 if (vpnInterfaces.remove(currVpnInterface)) {
287 if (vpnInterfaces.isEmpty()) {
288 Map<IpAddressesKey, IpAddresses> ipAddressesMap = dpnInVpn.nonnullIpAddresses();
289 VpnToDpnListBuilder dpnInVpnBuilder =
290 new VpnToDpnListBuilder(dpnInVpn).setVpnInterfaces(Collections.emptyMap());
291 if (ipAddressesMap == null || ipAddressesMap.isEmpty()) {
292 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
293 lastDpnOnVpn.set(true);
295 LOG.error("removeOrUpdateVpnToDpnList: vpn interfaces are empty but ip addresses"
296 + " are present for the vpn {} in dpn {} interface {}", vpnName, dpnId,
299 LOG.debug("removeOrUpdateVpnToDpnList: Removing vpn footprint for vpn {} vpnId {} "
300 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
301 tx.mergeParentStructurePut(id, dpnInVpnBuilder.build());
304 tx.delete(id.child(VpnInterfaces.class, new VpnInterfacesKey(intfName)));
305 LOG.debug("removeOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} "
306 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
311 } catch (InterruptedException | ExecutionException e) {
312 LOG.error("removeOrUpdateVpnToDpnList: Error removing from dpnToVpnList for vpn {} vpnId {}"
313 + " interface {} dpn {}", vpnName, vpnId, intfName, dpnId, e);
314 throw new RuntimeException(e.getMessage(), e);
316 // Ends synchronized block
317 LOG.info("removeOrUpdateVpnToDpnList: Updated/Removed vpn footprint for vpn {} vpnId {} interface {},"
318 + " on dpn {}", vpnName, vpnName, intfName, dpnId);
320 if (lastDpnOnVpn.get()) {
321 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
322 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
323 LOG.info("removeOrUpdateVpnToDpnList: Sent cleanup event for dpn {} in VPN {} vpnId {} interface {}",
324 dpnId, vpnName, vpnId, intfName);
331 private void removeOrUpdateVpnToDpnListForIpAddress(Uint32 vpnId, String rd, Uint64 dpnId,
332 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
333 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
334 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
335 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
337 // FIXME: separate this out somehow?
338 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
341 ListenableFuture<?> future = txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
342 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
344 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(id).get();
345 if (!dpnInVpnOpt.isPresent()) {
346 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={} "
347 + "rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
350 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
351 List<IpAddresses> ipAddresses = new ArrayList<>(dpnInVpn.nonnullIpAddresses().values());
352 if (ipAddresses == null) {
353 LOG.info("Could not find ipAddresses for DpnInVpn map for VPN=[name={} rd={} id={}] "
354 + "and dpnId={}", vpnName, rd, id, dpnId);
358 IpAddresses currIpAddress = new IpAddressesBuilder()
359 .withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()))
360 .setIpAddressSource(ipAddressSourceValuePair.getKey()).build();
361 if (ipAddresses.remove(currIpAddress)) {
362 if (ipAddresses.isEmpty()) {
363 Map<VpnInterfacesKey, VpnInterfaces> vpnInterfacesMap = dpnInVpn.nonnullVpnInterfaces();
364 VpnToDpnListBuilder dpnInVpnBuilder =
365 new VpnToDpnListBuilder(dpnInVpn).setIpAddresses(Collections.<IpAddresses>emptyList());
366 if (vpnInterfacesMap == null || vpnInterfacesMap.isEmpty()) {
367 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
368 lastDpnOnVpn.set(true);
370 LOG.warn("ip addresses are empty but vpn interfaces are present for the vpn {} in "
371 + "dpn {}", vpnName, dpnId);
373 tx.mergeParentStructurePut(id, dpnInVpnBuilder.build());
376 tx.delete(id.child(IpAddresses.class, new IpAddressesKey(ipAddressSourceValuePair.getValue())));
382 } catch (InterruptedException | ExecutionException e) {
383 LOG.error("Error removing from dpnToVpnList for vpn {} Ipaddress {} dpn {}", vpnName,
384 ipAddressSourceValuePair.getValue(), dpnId, e);
385 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
390 if (lastDpnOnVpn.get()) {
391 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
392 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
393 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
397 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
398 justification = "https://github.com/spotbugs/spotbugs/issues/811")
399 private void publishAddNotification(final Uint64 dpnId, final String vpnName, final String rd) {
400 LOG.debug("publishAddNotification: Sending notification for add dpn {} in vpn {} rd {} event ", dpnId, vpnName,
402 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
403 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
404 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
405 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
407 public void onFailure(Throwable error) {
408 LOG.error("publishAddNotification: Error in notifying listeners for add dpn {} in vpn {} rd {} event ",
409 dpnId, vpnName, rd, error);
413 public void onSuccess(Object arg) {
414 LOG.info("publishAddNotification: Successful in notifying listeners for add dpn {} in vpn {} rd {}"
415 + " event ", dpnId, vpnName, rd);
417 }, MoreExecutors.directExecutor());
420 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
421 justification = "https://github.com/spotbugs/spotbugs/issues/811")
422 private void publishRemoveNotification(final Uint64 dpnId, final String vpnName, final String rd) {
423 LOG.debug("publishRemoveNotification: Sending notification for remove dpn {} in vpn {} rd {} event ", dpnId,
425 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
426 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
427 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
428 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
430 public void onFailure(Throwable error) {
431 LOG.error("publishRemoveNotification: Error in notifying listeners for remove dpn {} in vpn {} rd {}"
432 + " event ", dpnId, vpnName, rd, error);
436 public void onSuccess(Object arg) {
437 LOG.info("publishRemoveNotification: Successful in notifying listeners for remove dpn {} in vpn {}"
438 + " rd {} event ", dpnId, vpnName, rd);
440 }, MoreExecutors.directExecutor());
443 private void publishInterfaceAddedToVpnNotification(String interfaceName, Uint64 dpnId, String vpnName,
445 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for addition of interface {} on dpn {}"
446 + " for vpn {}", interfaceName, dpnId, vpnName);
447 AddInterfaceEventData data = new AddInterfaceEventDataBuilder().setInterfaceName(interfaceName).setVpnId(vpnId)
448 .setDpnId(dpnId).build();
449 AddInterfaceToDpnOnVpnEvent event = new AddInterfaceToDpnOnVpnEventBuilder().setAddInterfaceEventData(data)
451 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
452 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
454 public void onFailure(Throwable error) {
455 LOG.warn("publishInterfaceAddedToVpnNotification: Error in notifying listeners for add interface {}"
456 + " on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName, error);
460 public void onSuccess(Object arg) {
461 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for add"
462 + " interface {} on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
464 }, MoreExecutors.directExecutor());
467 private void publishInterfaceRemovedFromVpnNotification(String interfaceName, Uint64 dpnId, String vpnName,
469 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for removal of interface {}"
470 + " from dpn {} for vpn {}", interfaceName, dpnId, vpnName);
471 RemoveInterfaceEventData data = new RemoveInterfaceEventDataBuilder().setInterfaceName(interfaceName)
472 .setVpnId(vpnId).setDpnId(dpnId).build();
473 RemoveInterfaceFromDpnOnVpnEvent event = new RemoveInterfaceFromDpnOnVpnEventBuilder()
474 .setRemoveInterfaceEventData(data).build();
475 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
476 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
478 public void onFailure(Throwable error) {
480 "publishInterfaceAddedToVpnNotification: Error in notifying listeners"
481 + " for removing interface {} from dpn {} in vpn {} event ",
482 interfaceName, dpnId, vpnName, error);
486 public void onSuccess(Object arg) {
487 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for removing"
488 + " interface {} from dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
490 }, MoreExecutors.directExecutor());
494 * JobCallback class is used as a future callback for main and rollback workers
495 * to handle success and failure.
497 private class DpnEnterExitVpnWorker implements FutureCallback<List<?>> {
498 private final Logger log = LoggerFactory.getLogger(DpnEnterExitVpnWorker.class);
504 DpnEnterExitVpnWorker(Uint64 dpnId, String vpnName, String rd, boolean entered) {
505 this.entered = entered;
507 this.vpnName = vpnName;
512 * This implies that all the future instances have returned success. -- TODO:
516 public void onSuccess(List<?> voids) {
518 publishAddNotification(dpnId, vpnName, rd);
519 log.info("onSuccess: FootPrint established for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
521 publishRemoveNotification(dpnId, vpnName, rd);
522 log.info("onSuccess: FootPrint cleared for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
527 * This method is used to handle failure callbacks. If more retry needed, the
528 * retrycount is decremented and mainworker is executed again. After retries
529 * completed, rollbackworker is executed. If rollbackworker fails, this is a
530 * double-fault. Double fault is logged and ignored.
533 public void onFailure(Throwable throwable) {
534 log.info("onFailure: Failed to establish/clear footprint for vpn {} rd {} on dpn {} ", vpnName, rd, dpnId,
539 boolean isVpnFootPrintCleared(VpnInstanceOpDataEntry vpnInstanceOpData) {
540 return vpnInstanceOpData.getVpnToDpnList() == null || vpnInstanceOpData.getVpnToDpnList().isEmpty();