bfd30b56a665db9161a8400ba91286db442c8ce4
[netvirt.git] /
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.netvirt.vpnmanager;
10
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
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 java.math.BigInteger;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.concurrent.ExecutionException;
20
21 import org.apache.commons.lang3.tuple.ImmutablePair;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
27 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
28 import org.opendaylight.netvirt.vpnmanager.api.IVpnFootprintService;
29 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEvent;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddInterfaceToDpnOnVpnEventBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEvent;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveInterfaceFromDpnOnVpnEventBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventData;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add._interface.to.dpn.on.vpn.event.AddInterfaceEventDataBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventData;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove._interface.from.dpn.on.vpn.event.RemoveInterfaceEventDataBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
49 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;
50 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;
51 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;
52 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;
53 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;
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.VpnInterfacesKey;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 public class VpnFootprintService implements IVpnFootprintService {
60
61     private static final Logger LOG = LoggerFactory.getLogger(VpnFootprintService.class);
62
63     private final DataBroker dataBroker;
64     private final IFibManager fibManager;
65     private final VpnOpDataSyncer vpnOpDataSyncer;
66     private final OdlInterfaceRpcService ifaceMgrRpcService;
67     private final NotificationPublishService notificationPublishService;
68
69     public VpnFootprintService(final DataBroker dataBroker, final IFibManager fibManager,
70         final OdlInterfaceRpcService ifaceRpcService, final NotificationPublishService notificationPublishService,
71         final VpnOpDataSyncer vpnOpDataSyncer) {
72         this.dataBroker = dataBroker;
73         this.fibManager = fibManager;
74         this.vpnOpDataSyncer = vpnOpDataSyncer;
75         this.ifaceMgrRpcService = ifaceRpcService;
76         this.notificationPublishService = notificationPublishService;
77     }
78
79     @Override
80     public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName,
81             ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair,
82                                       boolean add) {
83         long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
84         if (dpId == null) {
85             dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
86         }
87         if (!dpId.equals(BigInteger.ZERO)) {
88             if (add) {
89                 // Considering the possibility of VpnInstanceOpData not being ready yet cause the VPN is
90                 // still in its creation process
91                 if (vpnId == VpnConstants.INVALID_ID) {
92                     vpnOpDataSyncer.waitForVpnDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName,
93                         VpnConstants.PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS);
94                     vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
95                 }
96                 if (interfaceName != null) {
97                     createOrUpdateVpnToDpnListForInterfaceName(vpnId, dpId, interfaceName, vpnName);
98                     publishInterfaceAddedToVpnNotification(interfaceName, dpId, vpnName, vpnId);
99                 } else {
100                     createOrUpdateVpnToDpnListForIPAddress(vpnId, dpId, ipAddressSourceValuePair, vpnName);
101                 }
102             } else {
103                 if (interfaceName != null) {
104                     removeOrUpdateVpnToDpnListForInterfaceName(vpnId, dpId, interfaceName, vpnName);
105                     publishInterfaceRemovedFromVpnNotification(interfaceName, dpId, vpnName, vpnId);
106                 } else {
107                     removeOrUpdateVpnToDpnListForIpAddress(vpnId, dpId, ipAddressSourceValuePair, vpnName);
108                 }
109             }
110         }
111     }
112
113     private void createOrUpdateVpnToDpnListForInterfaceName(long vpnId, BigInteger dpnId, String intfName,
114                                                             String vpnName) {
115         String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
116         Boolean newDpnOnVpn = Boolean.FALSE;
117
118         synchronized (vpnName.intern()) {
119             WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
120             InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(primaryRd, dpnId);
121             Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
122             VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
123
124             if (dpnInVpn.isPresent()) {
125                 VpnToDpnList vpnToDpnList = dpnInVpn.get();
126                 List<VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
127                 if (vpnInterfaces == null) {
128                     vpnInterfaces = new ArrayList<>();
129                 }
130                 vpnInterfaces.add(vpnInterface);
131                 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
132                 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
133
134                 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
135                 /* If earlier state was inactive, it is considered new DPN coming back to the
136                  * same VPN
137                  */
138                 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
139                     newDpnOnVpn = Boolean.TRUE;
140                 }
141             } else {
142                 List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
143                 vpnInterfaces.add(vpnInterface);
144                 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
145                 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
146
147                 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
148                 newDpnOnVpn = Boolean.TRUE;
149             }
150             CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
151             try {
152                 futures.get();
153             } catch (InterruptedException | ExecutionException e) {
154                 LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId, e);
155                 throw new RuntimeException(e.getMessage());
156             }
157         }
158         /*
159          * Informing the Fib only after writeTxn is submitted successfuly.
160          */
161         if (newDpnOnVpn) {
162             LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
163             fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd, new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd,
164                 true /* entered */));
165         }
166     }
167
168     private void createOrUpdateVpnToDpnListForIPAddress(long vpnId, BigInteger dpnId,
169             ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
170         String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
171         Boolean newDpnOnVpn = Boolean.FALSE;
172
173         synchronized (vpnName.intern()) {
174             WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
175             InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(primaryRd, dpnId);
176             Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
177             IpAddressesBuilder ipAddressesBldr = new IpAddressesBuilder()
178                     .setIpAddressSource(ipAddressSourceValuePair.getKey());
179             ipAddressesBldr.setKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()));
180             ipAddressesBldr.setIpAddress(ipAddressSourceValuePair.getValue());
181
182             if (dpnInVpn.isPresent()) {
183                 VpnToDpnList vpnToDpnList = dpnInVpn.get();
184                 List<IpAddresses> ipAddresses = vpnToDpnList.getIpAddresses();
185                 if (ipAddresses == null) {
186                     ipAddresses = new ArrayList<>();
187                 }
188                 ipAddresses.add(ipAddressesBldr.build());
189                 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
190                 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
191
192                 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
193                 /* If earlier state was inactive, it is considered new DPN coming back to the
194                  * same VPN
195                  */
196                 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
197                     newDpnOnVpn = Boolean.TRUE;
198                 }
199             } else {
200                 List<IpAddresses> ipAddresses = new ArrayList<>();
201                 ipAddresses.add(ipAddressesBldr.build());
202                 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
203                 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setIpAddresses(ipAddresses);
204
205                 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
206                 newDpnOnVpn = Boolean.TRUE;
207             }
208             CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
209             try {
210                 futures.get();
211             } catch (InterruptedException | ExecutionException e) {
212                 LOG.error("Error adding to dpnToVpnList for vpn {} ipAddresses {} dpn {}", vpnName,
213                         ipAddressSourceValuePair.getValue(), dpnId, e);
214                 throw new RuntimeException(e.getMessage());
215             }
216         }
217         /*
218          * Informing the Fib only after writeTxn is submitted successfuly.
219          */
220         if (newDpnOnVpn) {
221             LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
222             fibManager.populateFibOnNewDpn(dpnId, vpnId, primaryRd, new DpnEnterExitVpnWorker(dpnId, vpnName, primaryRd,
223                     true /* entered */));
224         }
225     }
226
227     private void removeOrUpdateVpnToDpnListForInterfaceName(long vpnId, BigInteger dpnId, String intfName,
228                                                             String vpnName) {
229         Boolean lastDpnOnVpn = Boolean.FALSE;
230         String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
231         synchronized (vpnName.intern()) {
232             InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
233             VpnToDpnList dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id).orNull();
234             if (dpnInVpn == null) {
235                 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={} rd={} id={}]"
236                     + " and dpnId={}", vpnName, rd, id, dpnId);
237                 return;
238             }
239             List<VpnInterfaces> vpnInterfaces = dpnInVpn.getVpnInterfaces();
240             if (vpnInterfaces == null) {
241                 LOG.error("Could not find vpnInterfaces for DpnInVpn map for VPN=[name={} rd={} id={}] and dpnId={}",
242                          vpnName, rd, id, dpnId);
243                 return;
244             }
245
246             VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
247             if (vpnInterfaces.remove(currVpnInterface)) {
248                 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
249                 if (vpnInterfaces.isEmpty()) {
250                     List<IpAddresses> ipAddresses = dpnInVpn.getIpAddresses();
251                     VpnToDpnListBuilder dpnInVpnBuilder = new VpnToDpnListBuilder(dpnInVpn).setVpnInterfaces(null);
252                     if (ipAddresses == null || ipAddresses.isEmpty()) {
253                         dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
254                         lastDpnOnVpn = Boolean.TRUE;
255                     } else {
256                         LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}",
257                                  vpnName, dpnId);
258                     }
259                     writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
260
261                 } else {
262                     writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(VpnInterfaces.class,
263                                                                                new VpnInterfacesKey(intfName)));
264                 }
265                 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
266                 try {
267                     futures.get();
268                 } catch (InterruptedException | ExecutionException e) {
269                     LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}",
270                               vpnName, intfName, dpnId, e);
271                     throw new RuntimeException(e.getMessage());
272                 }
273             }
274         } // Ends synchronized block
275
276         if (lastDpnOnVpn) {
277             LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
278             fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd,
279                 false /* exited */));
280         }
281     }
282
283     private void removeOrUpdateVpnToDpnListForIpAddress(long vpnId, BigInteger dpnId,
284             ImmutablePair<IpAddresses.IpAddressSource, String> ipAddressSourceValuePair, String vpnName) {
285         Boolean lastDpnOnVpn = Boolean.FALSE;
286         String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
287         synchronized (vpnName.intern()) {
288             InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
289             VpnToDpnList dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id).orNull();
290             if (dpnInVpn == null) {
291                 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={} rd={} id={}]"
292                         + " and dpnId={}", vpnName, rd, id, dpnId);
293                 return;
294             }
295             List<IpAddresses> ipAddresses = dpnInVpn.getIpAddresses();
296             if (ipAddresses == null) {
297                 LOG.error("Could not find ipAddresses for DpnInVpn map for VPN=[name={} rd={} id={}] and dpnId={}",
298                         vpnName, rd, id, dpnId);
299                 return;
300             }
301
302             IpAddresses currIpAddress = new IpAddressesBuilder()
303                     .setKey(new IpAddressesKey(ipAddressSourceValuePair.getValue()))
304                     .setIpAddressSource(ipAddressSourceValuePair.getKey())
305                     .build();
306             if (ipAddresses.remove(currIpAddress)) {
307                 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
308                 if (ipAddresses.isEmpty()) {
309                     List<VpnInterfaces> vpnInterfaces = dpnInVpn.getVpnInterfaces();
310                     VpnToDpnListBuilder dpnInVpnBuilder = new VpnToDpnListBuilder(dpnInVpn).setIpAddresses(null);
311                     if (vpnInterfaces == null || vpnInterfaces.isEmpty()) {
312                         dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
313                         lastDpnOnVpn = Boolean.TRUE;
314                     } else {
315                         LOG.warn("ip addresses are empty but vpn interfaces are present for the vpn {} in dpn {}",
316                                 vpnName, dpnId);
317                     }
318                     writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
319
320                 } else {
321                     writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(IpAddresses.class,
322                             new IpAddressesKey(ipAddressSourceValuePair.getValue())));
323                 }
324                 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
325                 try {
326                     futures.get();
327                 } catch (InterruptedException | ExecutionException e) {
328                     LOG.error("Error removing from dpnToVpnList for vpn {} Ipaddress {} dpn {}",
329                             vpnName, ipAddressSourceValuePair.getValue(), dpnId, e);
330                     throw new RuntimeException(e.getMessage());
331                 }
332             }
333         } // Ends synchronized block
334
335         if (lastDpnOnVpn) {
336             LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
337             fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd,
338                     false /* exited */));
339         }
340     }
341
342     private void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
343         LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
344         AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
345         AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
346         final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
347         Futures.addCallback(eventFuture, new FutureCallback<Object>() {
348             @Override
349             public void onFailure(Throwable error) {
350                 LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
351             }
352
353             @Override
354             public void onSuccess(Object arg) {
355                 LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
356             }
357         });
358     }
359
360     private void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
361         LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
362         RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
363         RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
364         final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
365         Futures.addCallback(eventFuture, new FutureCallback<Object>() {
366             @Override
367             public void onFailure(Throwable error) {
368                 LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
369             }
370
371             @Override
372             public void onSuccess(Object arg) {
373                 LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
374             }
375         });
376     }
377
378     private void publishInterfaceAddedToVpnNotification(String interfaceName, BigInteger dpnId, String vpnName,
379                                                         Long vpnId) {
380         LOG.debug("Sending notification for addition of interface {} on dpn {} for vpn {}", interfaceName,
381                 dpnId, vpnName);
382         AddInterfaceEventData data = new AddInterfaceEventDataBuilder().setInterfaceName(interfaceName)
383                 .setVpnId(vpnId).setDpnId(dpnId).build();
384         AddInterfaceToDpnOnVpnEvent event = new AddInterfaceToDpnOnVpnEventBuilder()
385                 .setAddInterfaceEventData(data).build();
386         final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
387         Futures.addCallback(eventFuture, new FutureCallback<Object>() {
388             @Override
389             public void onFailure(Throwable error) {
390                 LOG.warn("Error in notifying listeners for add interface {} on dpn {} in vpn {} event ",
391                         interfaceName, dpnId, vpnName, error);
392             }
393
394             @Override
395             public void onSuccess(Object arg) {
396                 LOG.trace("Successful in notifying listeners for add interface {} on dpn {} in vpn {} event ",
397                         interfaceName, dpnId, vpnName);
398             }
399         });
400     }
401
402     private void publishInterfaceRemovedFromVpnNotification(String interfaceName, BigInteger dpnId, String vpnName,
403                                                             Long vpnId) {
404         LOG.debug("Sending notification for removal of interface {} from dpn {} for vpn {}", interfaceName,
405                 dpnId, vpnName);
406         RemoveInterfaceEventData data = new RemoveInterfaceEventDataBuilder().setInterfaceName(interfaceName)
407                 .setVpnId(vpnId).setDpnId(dpnId).build();
408         RemoveInterfaceFromDpnOnVpnEvent event = new RemoveInterfaceFromDpnOnVpnEventBuilder()
409                 .setRemoveInterfaceEventData(data).build();
410         final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
411         Futures.addCallback(eventFuture, new FutureCallback<Object>() {
412             @Override
413             public void onFailure(Throwable error) {
414                 LOG.warn("Error in notifying listeners for removing interface {} from dpn {} in vpn {} event ",
415                         interfaceName, dpnId, vpnName, error);
416             }
417
418             @Override
419             public void onSuccess(Object arg) {
420                 LOG.trace("Successful in notifying listeners for removing interface {} from dpn {} in vpn {} event ",
421                         interfaceName, dpnId, vpnName);
422             }
423         });
424     }
425
426
427     /**
428      * JobCallback class is used as a future callback for
429      * main and rollback workers to handle success and failure.
430      */
431     private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
432         BigInteger dpnId;
433         String vpnName;
434         String rd;
435         boolean entered;
436
437         DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
438             this.entered = entered;
439             this.dpnId = dpnId;
440             this.vpnName = vpnName;
441             this.rd = rd;
442         }
443
444         /**
445          * This implies that all the future instances have returned success. -- TODO: Confirm this
446          */
447         @Override
448         public void onSuccess(List<Void> voids) {
449             if (entered) {
450                 publishAddNotification(dpnId, vpnName, rd);
451             } else {
452                 publishRemoveNotification(dpnId, vpnName, rd);
453             }
454         }
455
456         /**
457          * This method is used to handle failure callbacks.
458          * If more retry needed, the retrycount is decremented and mainworker is executed again.
459          * After retries completed, rollbackworker is executed.
460          * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
461          */
462         @Override
463         public void onFailure(Throwable throwable) {
464             LOG.warn("Job: failed with exception: ", throwable);
465         }
466     }
467
468 }