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 java.math.BigInteger;
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 javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.apache.commons.lang3.tuple.ImmutablePair;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
27 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
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.netvirt.fibmanager.api.IFibManager;
33 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
34 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEvent;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEventBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEvent;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEventBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventData;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventDataBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventData;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventDataBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
54 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;
55 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;
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.IpAddressesKey;
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.VpnInterfaces;
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.VpnInterfacesBuilder;
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.VpnInterfacesKey;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
65 public class VpnFootprintService implements IVpnFootprintService {
67 private static final Logger LOG = LoggerFactory.getLogger(VpnFootprintService.class);
69 private final DataBroker dataBroker;
70 private final ManagedNewTransactionRunner txRunner;
71 private final IFibManager fibManager;
72 private final VpnOpDataSyncer vpnOpDataSyncer;
73 private final NotificationPublishService notificationPublishService;
74 private final IInterfaceManager interfaceManager;
75 private final VpnUtil vpnUtil;
78 public VpnFootprintService(final DataBroker dataBroker, final IFibManager fibManager,
79 final NotificationPublishService notificationPublishService, final VpnOpDataSyncer vpnOpDataSyncer,
80 final IInterfaceManager interfaceManager, VpnUtil vpnUtil) {
81 this.dataBroker = dataBroker;
82 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
83 this.fibManager = fibManager;
84 this.vpnOpDataSyncer = vpnOpDataSyncer;
85 this.notificationPublishService = notificationPublishService;
86 this.interfaceManager = interfaceManager;
87 this.vpnUtil = vpnUtil;
91 public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String primaryRd, @Nullable String interfaceName,
92 @Nullable ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, boolean add) {
93 long vpnId = vpnUtil.getVpnId(vpnName);
94 if (!dpId.equals(BigInteger.ZERO)) {
96 // Considering the possibility of VpnInstanceOpData not being ready yet cause
98 // still in its creation process
99 if (vpnId == VpnConstants.INVALID_ID) {
100 LOG.error("updateVpnToDpnMapping: Operational data for vpn not ready. Waiting to update vpn"
101 + " footprint for vpn {} on dpn {} interface {}", vpnName, dpId, interfaceName);
102 vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName,
103 VpnConstants.PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS);
104 vpnId = vpnUtil.getVpnId(vpnName);
106 if (interfaceName != null) {
107 createOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
108 publishInterfaceAddedToVpnNotification(interfaceName, dpId, vpnName, vpnId);
110 createOrUpdateVpnToDpnListForIPAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
113 if (interfaceName != null) {
114 removeOrUpdateVpnToDpnListForInterfaceName(vpnId, primaryRd, dpId, interfaceName, vpnName);
115 publishInterfaceRemovedFromVpnNotification(interfaceName, dpId, vpnName, vpnId);
117 removeOrUpdateVpnToDpnListForIpAddress(vpnId, primaryRd, dpId, ipAddressSourceValuePair, vpnName);
123 private void createOrUpdateVpnToDpnListForInterfaceName(long vpnId, String primaryRd, BigInteger dpnId,
124 String intfName, String vpnName) {
125 AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
126 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
127 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
129 synchronized (vpnName.intern()) {
131 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
132 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
133 VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
134 Optional<VpnToDpnList> dpnInVpn = tx.read(LogicalDatastoreType.OPERATIONAL, id).checkedGet();
135 if (dpnInVpn.isPresent()) {
136 VpnToDpnList vpnToDpnList = dpnInVpn.get();
137 List<VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
138 if (vpnInterfaces == null) {
139 vpnInterfaces = new ArrayList<>();
141 vpnInterfaces.add(vpnInterface);
142 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
143 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
145 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(),
146 WriteTransaction.CREATE_MISSING_PARENTS);
148 * If earlier state was inactive, it is considered new DPN coming back to the
151 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
152 newDpnOnVpn.set(true);
154 LOG.debug("createOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} interface {}"
155 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
157 List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
158 vpnInterfaces.add(vpnInterface);
159 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
160 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
162 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(),
163 WriteTransaction.CREATE_MISSING_PARENTS);
164 newDpnOnVpn.set(true);
165 LOG.debug("createOrUpdateVpnToDpnList: Creating vpn footprint for vpn {} vpnId {} interface {}"
166 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
170 } catch (InterruptedException | ExecutionException e) {
171 LOG.error("createOrUpdateVpnToDpnList: Error adding to dpnToVpnList for vpn {} vpnId {} interface {}"
172 + " dpn {}", vpnName, vpnId, intfName, dpnId, e);
173 throw new RuntimeException(e.getMessage(), e);
176 // Ends synchronized block
177 LOG.info("createOrUpdateVpnToDpnList: Created/Updated vpn footprint for vpn {} vpnId {} interfacName{}"
178 + " on dpn {}", vpnName, vpnId, intfName, dpnId);
180 * Informing the FIB only after writeTxn is submitted successfully.
182 if (newDpnOnVpn.get()) {
183 if (vpnUtil.isVlan(intfName)) {
184 if (!vpnUtil.shouldPopulateFibForVlan(vpnName, null, dpnId)) {
188 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
189 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
190 LOG.info("createOrUpdateVpnToDpnList: Sent populateFib event for new dpn {} in VPN {} for interface {}",
191 dpnId, vpnName, intfName);
195 private void createOrUpdateVpnToDpnListForIPAddress(long vpnId, String primaryRd, BigInteger dpnId,
196 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
197 AtomicBoolean newDpnOnVpn = new AtomicBoolean(false);
198 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
199 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
201 synchronized (vpnName.intern()) {
203 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
204 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
205 IpAddressesBuilder ipAddressesBldr = new IpAddressesBuilder()
206 .setIpAddressSource(ipAddressSourceValuePair.getKey());
207 ipAddressesBldr.withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()));
208 ipAddressesBldr.setIpAddress(ipAddressSourceValuePair.getValue());
209 Optional<VpnToDpnList> dpnInVpn = tx.read(LogicalDatastoreType.OPERATIONAL, id).checkedGet();
210 if (dpnInVpn.isPresent()) {
211 VpnToDpnList vpnToDpnList = dpnInVpn.get();
212 List<IpAddresses> ipAddresses = vpnToDpnList.getIpAddresses();
213 if (ipAddresses == null) {
214 ipAddresses = new ArrayList<>();
216 ipAddresses.add(ipAddressesBldr.build());
217 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
218 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
220 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
222 * If earlier state was inactive, it is considered new DPN coming back to the
225 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
226 newDpnOnVpn.set(true);
229 List<IpAddresses> ipAddresses = new ArrayList<>();
230 ipAddresses.add(ipAddressesBldr.build());
231 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
232 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
233 tx.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
234 newDpnOnVpn.set(true);
239 } catch (InterruptedException | ExecutionException e) {
240 LOG.error("createOrUpdateVpnToDpnListForIPAddress: Error adding to dpnToVpnList for vpn {}"
241 + " ipAddresses {} dpn {}", vpnName, ipAddressSourceValuePair.getValue(), dpnId, e);
242 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
245 // Ends synchronized block
247 * Informing the Fib only after writeTxn is submitted successfuly.
249 if (newDpnOnVpn.get()) {
250 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
251 fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd,
252 new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd, true /* entered */));
256 private void removeOrUpdateVpnToDpnListForInterfaceName(long vpnId, String rd, BigInteger dpnId, String intfName,
258 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
259 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
260 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
262 synchronized (vpnName.intern()) {
264 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
265 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
266 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(LogicalDatastoreType.OPERATIONAL, id)
268 if (!dpnInVpnOpt.isPresent()) {
269 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={}"
270 + " rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
273 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
274 List<VpnInterfaces> vpnInterfaces = dpnInVpn.getVpnInterfaces();
275 if (vpnInterfaces == null) {
276 LOG.error("Could not find vpnInterfaces for DpnInVpn map for VPN=[name={} rd={} id={}] and "
277 + "dpnId={}", vpnName, rd, id, dpnId);
280 VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
281 if (vpnInterfaces.remove(currVpnInterface)) {
282 if (vpnInterfaces.isEmpty()) {
283 List<IpAddresses> ipAddresses = dpnInVpn.getIpAddresses();
284 VpnToDpnListBuilder dpnInVpnBuilder =
285 new VpnToDpnListBuilder(dpnInVpn).setVpnInterfaces(null);
286 if (ipAddresses == null || ipAddresses.isEmpty()) {
287 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
288 lastDpnOnVpn.set(true);
290 LOG.error("removeOrUpdateVpnToDpnList: vpn interfaces are empty but ip addresses"
291 + " are present for the vpn {} in dpn {} interface {}", vpnName, dpnId,
294 LOG.debug("removeOrUpdateVpnToDpnList: Removing vpn footprint for vpn {} vpnId {} "
295 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
296 tx.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(),
297 WriteTransaction.CREATE_MISSING_PARENTS);
300 tx.delete(LogicalDatastoreType.OPERATIONAL,
301 id.child(VpnInterfaces.class, new VpnInterfacesKey(intfName)));
302 LOG.debug("removeOrUpdateVpnToDpnList: Updating vpn footprint for vpn {} vpnId {} "
303 + "interface {}, on dpn {}", vpnName, vpnName, intfName, dpnId);
308 } catch (InterruptedException | ExecutionException e) {
309 LOG.error("removeOrUpdateVpnToDpnList: Error removing from dpnToVpnList for vpn {} vpnId {}"
310 + " interface {} dpn {}", vpnName, vpnId, intfName, dpnId, e);
311 throw new RuntimeException(e.getMessage(), e);
313 // Ends synchronized block
314 LOG.info("removeOrUpdateVpnToDpnList: Updated/Removed vpn footprint for vpn {} vpnId {} interface {},"
315 + " on dpn {}", vpnName, vpnName, intfName, dpnId);
317 if (lastDpnOnVpn.get()) {
318 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
319 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
320 LOG.info("removeOrUpdateVpnToDpnList: Sent cleanup event for dpn {} in VPN {} vpnId {} interface {}",
321 dpnId, vpnName, vpnId, intfName);
326 private void removeOrUpdateVpnToDpnListForIpAddress(long vpnId, String rd, BigInteger dpnId,
327 ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
328 AtomicBoolean lastDpnOnVpn = new AtomicBoolean(false);
329 /* Starts synchronized block. This ensures only one reader/writer get access to vpn-dpn-list
330 * The future.get ensures that the write to the datastore is complete before leaving the synchronized block.
332 synchronized (vpnName.intern()) {
334 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
335 InstanceIdentifier<VpnToDpnList> id = VpnHelper.getVpnToDpnListIdentifier(rd, dpnId);
337 Optional<VpnToDpnList> dpnInVpnOpt = tx.read(LogicalDatastoreType.OPERATIONAL, id)
339 if (!dpnInVpnOpt.isPresent()) {
340 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={} "
341 + "rd={} id={}] and dpnId={}", vpnName, rd, id, dpnId);
344 VpnToDpnList dpnInVpn = dpnInVpnOpt.get();
345 List<IpAddresses> ipAddresses = dpnInVpn.getIpAddresses();
346 if (ipAddresses == null) {
347 LOG.info("Could not find ipAddresses for DpnInVpn map for VPN=[name={} rd={} id={}] "
348 + "and dpnId={}", vpnName, rd, id, dpnId);
352 IpAddresses currIpAddress = new IpAddressesBuilder()
353 .withKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()))
354 .setIpAddressSource(ipAddressSourceValuePair.getKey()).build();
355 if (ipAddresses.remove(currIpAddress)) {
356 if (ipAddresses.isEmpty()) {
357 List<VpnInterfaces> vpnInterfaces = dpnInVpn.getVpnInterfaces();
358 VpnToDpnListBuilder dpnInVpnBuilder =
359 new VpnToDpnListBuilder(dpnInVpn).setIpAddresses(null);
360 if (vpnInterfaces == null || vpnInterfaces.isEmpty()) {
361 dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
362 lastDpnOnVpn.set(true);
364 LOG.warn("ip addresses are empty but vpn interfaces are present for the vpn {} in "
365 + "dpn {}", vpnName, dpnId);
367 tx.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
370 tx.delete(LogicalDatastoreType.OPERATIONAL, id.child(IpAddresses.class,
371 new IpAddressesKey(ipAddressSourceValuePair.getValue())));
377 } catch (InterruptedException | ExecutionException e) {
378 LOG.error("Error removing from dpnToVpnList for vpn {} Ipaddress {} dpn {}", vpnName,
379 ipAddressSourceValuePair.getValue(), dpnId, e);
380 throw new RuntimeException(e.getMessage(), e); //TODO: Avoid this
383 // Ends synchronized block
385 if (lastDpnOnVpn.get()) {
386 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
387 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd,
388 new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
392 private void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
393 LOG.debug("publishAddNotification: Sending notification for add dpn {} in vpn {} rd {} event ", dpnId, vpnName,
395 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
396 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
397 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
398 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
400 public void onFailure(Throwable error) {
401 LOG.error("publishAddNotification: Error in notifying listeners for add dpn {} in vpn {} rd {} event ",
402 dpnId, vpnName, rd, error);
406 public void onSuccess(Object arg) {
407 LOG.info("publishAddNotification: Successful in notifying listeners for add dpn {} in vpn {} rd {}"
408 + " event ", dpnId, vpnName, rd);
410 }, MoreExecutors.directExecutor());
413 private void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
414 LOG.debug("publishRemoveNotification: Sending notification for remove dpn {} in vpn {} rd {} event ", dpnId,
416 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
417 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
418 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
419 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
421 public void onFailure(Throwable error) {
422 LOG.error("publishRemoveNotification: Error in notifying listeners for remove dpn {} in vpn {} rd {}"
423 + " event ", dpnId, vpnName, rd, error);
427 public void onSuccess(Object arg) {
428 LOG.info("publishRemoveNotification: Successful in notifying listeners for remove dpn {} in vpn {}"
429 + " rd {} event ", dpnId, vpnName, rd);
431 }, MoreExecutors.directExecutor());
434 private void publishInterfaceAddedToVpnNotification(String interfaceName, BigInteger dpnId, String vpnName,
436 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for addition of interface {} on dpn {}"
437 + " for vpn {}", interfaceName, dpnId, vpnName);
438 AddInterfaceEventData data = new AddInterfaceEventDataBuilder().setInterfaceName(interfaceName).setVpnId(vpnId)
439 .setDpnId(dpnId).build();
440 AddInterfaceToDpnOnVpnEvent event = new AddInterfaceToDpnOnVpnEventBuilder().setAddInterfaceEventData(data)
442 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
443 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
445 public void onFailure(Throwable error) {
446 LOG.warn("publishInterfaceAddedToVpnNotification: Error in notifying listeners for add interface {}"
447 + " on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName, error);
451 public void onSuccess(Object arg) {
452 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for add"
453 + " interface {} on dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
455 }, MoreExecutors.directExecutor());
458 private void publishInterfaceRemovedFromVpnNotification(String interfaceName, BigInteger dpnId, String vpnName,
460 LOG.debug("publishInterfaceAddedToVpnNotification: Sending notification for removal of interface {}"
461 + " from dpn {} for vpn {}", interfaceName, dpnId, vpnName);
462 RemoveInterfaceEventData data = new RemoveInterfaceEventDataBuilder().setInterfaceName(interfaceName)
463 .setVpnId(vpnId).setDpnId(dpnId).build();
464 RemoveInterfaceFromDpnOnVpnEvent event = new RemoveInterfaceFromDpnOnVpnEventBuilder()
465 .setRemoveInterfaceEventData(data).build();
466 final ListenableFuture<?> eventFuture = notificationPublishService.offerNotification(event);
467 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
469 public void onFailure(Throwable error) {
471 "publishInterfaceAddedToVpnNotification: Error in notifying listeners"
472 + " for removing interface {} from dpn {} in vpn {} event ",
473 interfaceName, dpnId, vpnName, error);
477 public void onSuccess(Object arg) {
478 LOG.trace("publishInterfaceAddedToVpnNotification: Successful in notifying listeners for removing"
479 + " interface {} from dpn {} in vpn {} event ", interfaceName, dpnId, vpnName);
481 }, MoreExecutors.directExecutor());
485 * JobCallback class is used as a future callback for main and rollback workers
486 * to handle success and failure.
488 private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
489 private final Logger log = LoggerFactory.getLogger(DpnEnterExitVpnWorker.class);
495 DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
496 this.entered = entered;
498 this.vpnName = vpnName;
503 * This implies that all the future instances have returned success. -- TODO:
507 public void onSuccess(List<Void> voids) {
509 publishAddNotification(dpnId, vpnName, rd);
510 log.info("onSuccess: FootPrint established for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
512 publishRemoveNotification(dpnId, vpnName, rd);
513 log.info("onSuccess: FootPrint cleared for vpn {} rd {} on dpn {}", vpnName, rd, dpnId);
518 * This method is used to handle failure callbacks. If more retry needed, the
519 * retrycount is decremented and mainworker is executed again. After retries
520 * completed, rollbackworker is executed. If rollbackworker fails, this is a
521 * double-fault. Double fault is logged and ignored.
524 public void onFailure(Throwable throwable) {
525 log.info("onFailure: Failed to establish/clear footprint for vpn {} rd {} on dpn {} ", vpnName, rd, dpnId,
530 boolean isVpnFootPrintCleared(VpnInstanceOpDataEntry vpnInstanceOpData) {
531 return vpnInstanceOpData.getVpnToDpnList() == null || vpnInstanceOpData.getVpnToDpnList().isEmpty();