Use Java declarations instead of Google Collections
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnInstanceListener.java
1 /*
2  * Copyright (c) 2015 - 2016 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 package org.opendaylight.netvirt.vpnmanager;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
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 java.util.ArrayList;
16 import java.util.List;
17 import java.util.concurrent.Callable;
18 import java.util.concurrent.ExecutionException;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
25 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
26 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
27 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
28 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
30 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
31 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
32 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnTargetsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInstance, VpnInstanceListener>
48     implements AutoCloseable {
49     private static final Logger LOG = LoggerFactory.getLogger(VpnInstanceListener.class);
50     private final DataBroker dataBroker;
51     private final IBgpManager bgpManager;
52     private final IdManagerService idManager;
53     private final VpnInterfaceManager vpnInterfaceManager;
54     private final IFibManager fibManager;
55     private final VpnOpDataSyncer vpnOpDataNotifier;
56
57     public VpnInstanceListener(final DataBroker dataBroker, final IBgpManager bgpManager,
58         final IdManagerService idManager, final VpnInterfaceManager vpnInterfaceManager, final IFibManager fibManager,
59         final VpnOpDataSyncer vpnOpDataSyncer) {
60         super(VpnInstance.class, VpnInstanceListener.class);
61         this.dataBroker = dataBroker;
62         this.bgpManager = bgpManager;
63         this.idManager = idManager;
64         this.vpnInterfaceManager = vpnInterfaceManager;
65         this.fibManager = fibManager;
66         this.vpnOpDataNotifier = vpnOpDataSyncer;
67     }
68
69     public void start() {
70         LOG.info("{} start", getClass().getSimpleName());
71         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
72     }
73
74     @Override
75     protected InstanceIdentifier<VpnInstance> getWildCardPath() {
76         return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
77     }
78
79     @Override
80     protected VpnInstanceListener getDataTreeChangeListener() {
81         return VpnInstanceListener.this;
82     }
83
84     private void waitForOpRemoval(String rd, String vpnName) {
85         //wait till DCN for update on VPN Instance Op Data signals that vpn interfaces linked to this vpn instance is
86         // zero
87         //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
88         VpnInstanceOpDataEntry vpnOpEntry = null;
89         Long intfCount = 0L;
90         Long currentIntfCount = 0L;
91         Integer retryCount = 3;
92         long timeout = VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
93         Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
94         vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
95             VpnUtil.getVpnInstanceOpDataIdentifier(rd));
96
97         if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
98             vpnOpEntry = vpnOpValue.get();
99             List<VpnToDpnList> dpnToVpns = vpnOpEntry.getVpnToDpnList();
100             if (dpnToVpns != null) {
101                 for (VpnToDpnList dpn : dpnToVpns) {
102                     if (dpn.getVpnInterfaces() != null) {
103                         intfCount = intfCount + dpn.getVpnInterfaces().size();
104                     }
105                 }
106             }
107             //intfCount = vpnOpEntry.getVpnInterfaceCount();
108             while (true) {
109                 if (intfCount > 0) {
110                     // Minimum wait time of 5 seconds for one VPN Interface clearance (inclusive of full trace on)
111                     timeout = intfCount * VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
112                     // Maximum wait time of 90 seconds for all VPN Interfaces clearance (inclusive of full trace on)
113                     if (timeout > VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS) {
114                         timeout = VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS;
115                     }
116                     LOG.info("VPNInstance removal count of interface at {} for for rd {}, vpnname {}",
117                         intfCount, rd, vpnName);
118                 }
119                 LOG.info("VPNInstance removal thread waiting for {} seconds for rd {}, vpnname {}",
120                     (timeout / 1000), rd, vpnName);
121
122                 try {
123                     Thread.sleep(timeout);
124                 } catch (InterruptedException e) {
125                     // Ignored
126                 }
127
128                 // Check current interface count
129                 vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
130                     VpnUtil.getVpnInstanceOpDataIdentifier(rd));
131                 if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
132                     vpnOpEntry = vpnOpValue.get();
133                     dpnToVpns = vpnOpEntry.getVpnToDpnList();
134                     currentIntfCount = 0L;
135                     if (dpnToVpns != null) {
136                         for (VpnToDpnList dpn : dpnToVpns) {
137                             if (dpn.getVpnInterfaces() != null) {
138                                 currentIntfCount = currentIntfCount + dpn.getVpnInterfaces().size();
139                             }
140                         }
141                     }
142                     if ((currentIntfCount == 0) || (currentIntfCount >= intfCount)) {
143                         // Either the FibManager completed its job to cleanup all vpnInterfaces in VPN
144                         // OR
145                         // There is no progress by FibManager in removing all the interfaces even after good time!
146                         // In either case, let us quit and take our chances.
147                         //TODO(vpnteam): L3VPN refactoring to take care of this case.
148                         if ((dpnToVpns == null) || dpnToVpns.size() <= 0) {
149                             LOG.info("VPN Instance vpn {} rd {} ready for removal, exiting wait loop", vpnName, rd);
150                             break;
151                         } else {
152                             if (retryCount > 0) {
153                                 retryCount--;
154                                 LOG.info(
155                                     "Retrying clearing vpn with vpnname {} rd {} since current interface count {} ",
156                                     vpnName, rd, currentIntfCount);
157                                 if (currentIntfCount > 0) {
158                                     intfCount = currentIntfCount;
159                                 } else {
160                                     LOG.info(
161                                         "Current interface count is zero, but instance Op for vpn {} and rd {} not "
162                                             + "cleared yet. Waiting for 5 more seconds.",
163                                         vpnName, rd);
164                                     intfCount = 1L;
165                                 }
166                             } else {
167                                 LOG.info(
168                                     "VPNInstance bailing out of wait loop as current interface count is {} and max "
169                                         + "retries exceeded for for vpnName {}, rd {}",
170                                     currentIntfCount, vpnName, rd);
171                                 break;
172                             }
173                         }
174                     } else {
175                         LOG.info("Retrying clearing because not all vpnInterfaces removed : current interface count {},"
176                                 + " initial count {} for rd {}, vpnname {}", currentIntfCount, intfCount, rd, vpnName);
177                         intfCount = currentIntfCount;
178                     }
179                 } else {
180                     // There is no VPNOPEntry.  Something else happened on the system !
181                     // So let us quit and take our chances.
182                     //TODO(vpnteam): L3VPN refactoring to take care of this case.
183                     LOG.error("VpnInstanceOpData is not present in the operational DS for rd {}, vpnname {}", rd,
184                             vpnName);
185                     break;
186                 }
187             }
188         }
189         LOG.info("Returned out of waiting for  Op Data removal for rd {}, vpnname {}", rd, vpnName);
190     }
191
192     @Override
193     protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
194         LOG.trace("Remove VPN event key: {}, value: {}", identifier, del);
195         final String vpnName = del.getVpnInstanceName();
196         final String rd = del.getIpv4Family().getRouteDistinguisher();
197         Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
198
199         //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
200         try {
201             if ((rd != null) && (!rd.isEmpty())) {
202                 vpnOpValue = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
203                     VpnUtil.getVpnInstanceOpDataIdentifier(rd));
204             } else {
205                 vpnOpValue = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
206                     VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
207             }
208         } catch (ReadFailedException e) {
209             LOG.error("Exception when attempting to retrieve VpnInstanceOpDataEntry for VPN {}. ", vpnName, e);
210             return;
211         }
212
213         if (vpnOpValue == null || !vpnOpValue.isPresent()) {
214             LOG.error("Unable to retrieve VpnInstanceOpDataEntry for VPN {}. ", vpnName);
215             return;
216         }
217
218         DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
219         dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
220             new DeleteVpnInstanceWorker(idManager, dataBroker, del));
221     }
222
223     private class DeleteVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
224         IdManagerService idManager;
225         DataBroker broker;
226         VpnInstance vpnInstance;
227
228         DeleteVpnInstanceWorker(IdManagerService idManager,
229             DataBroker broker,
230             VpnInstance value) {
231             this.idManager = idManager;
232             this.broker = broker;
233             this.vpnInstance = value;
234         }
235
236         // TODO Clean up the exception handling
237         @SuppressWarnings("checkstyle:IllegalCatch")
238         @Override
239         public List<ListenableFuture<Void>> call() {
240             final String vpnName = vpnInstance.getVpnInstanceName();
241             final String rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
242             final long vpnId = VpnUtil.getVpnId(broker, vpnName);
243             WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
244             if ((rd != null) && (!rd.isEmpty())) {
245                 waitForOpRemoval(rd, vpnName);
246             } else {
247                 waitForOpRemoval(vpnName, vpnName);
248             }
249
250             // Clean up VpnInstanceToVpnId from Config DS
251             VpnUtil.removeVpnIdToVpnInstance(broker, vpnId, writeTxn);
252             VpnUtil.removeVpnInstanceToVpnId(broker, vpnName, writeTxn);
253             LOG.trace("Removed vpnIdentifier for  rd{} vpnname {}", rd, vpnName);
254             if (rd != null) {
255                 synchronized (vpnName.intern()) {
256                     fibManager.removeVrfTable(broker, rd, null);
257                 }
258                 try {
259                     bgpManager.deleteVrf(rd, false);
260                 } catch (Exception e) {
261                     LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
262                 }
263
264                 // Clean up VPNExtraRoutes Operational DS
265                 InstanceIdentifier<Vpn> vpnToExtraroute = VpnUtil.getVpnToExtrarouteIdentifier(rd);
266                 Optional<Vpn> optVpnToExtraroute =
267                     VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
268                 if (optVpnToExtraroute.isPresent()) {
269                     VpnUtil.removeVpnExtraRouteForVpn(broker, rd, writeTxn);
270                 }
271
272                 // Clean up VPNInstanceOpDataEntry
273                 VpnUtil.removeVpnOpInstance(broker, rd, writeTxn);
274             } else {
275                 // Clean up FIB Entries Config DS
276                 synchronized (vpnName.intern()) {
277                     fibManager.removeVrfTable(broker, vpnName, null);
278                 }
279                 // Clean up VPNExtraRoutes Operational DS
280                 InstanceIdentifier<Vpn> vpnToExtraroute = VpnUtil.getVpnToExtrarouteIdentifier(vpnName);
281                 Optional<Vpn> optVpnToExtraroute =
282                     VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
283                 if (optVpnToExtraroute.isPresent()) {
284                     VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName, writeTxn);
285                 }
286
287                 // Clean up VPNInstanceOpDataEntry
288                 VpnUtil.removeVpnOpInstance(broker, vpnName, writeTxn);
289             }
290             // Clean up PrefixToInterface Operational DS
291             VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId, writeTxn);
292
293             // Clean up L3NextHop Operational DS
294             VpnUtil.removeL3nexthopForVpnId(broker, vpnId, writeTxn);
295
296             // Release the ID used for this VPN back to IdManager
297             VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
298
299             List<ListenableFuture<Void>> futures = new ArrayList<>();
300             futures.add(writeTxn.submit());
301             return futures;
302         }
303     }
304
305     @Override
306     protected void update(InstanceIdentifier<VpnInstance> identifier,
307         VpnInstance original, VpnInstance update) {
308         LOG.trace("Update VPN event key: {}, value: {}", identifier, update);
309     }
310
311     @Override
312     protected void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
313         LOG.trace("Add VPN event key: {}, value: {}", identifier, value);
314         final String vpnName = value.getVpnInstanceName();
315
316         DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
317         dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
318             new AddVpnInstanceWorker(idManager, vpnInterfaceManager, dataBroker, value));
319     }
320
321     private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
322         IdManagerService idManager;
323         VpnInterfaceManager vpnInterfaceManager;
324         VpnInstance vpnInstance;
325         DataBroker broker;
326
327         AddVpnInstanceWorker(IdManagerService idManager,
328             VpnInterfaceManager vpnInterfaceManager,
329             DataBroker broker,
330             VpnInstance value) {
331             this.idManager = idManager;
332             this.vpnInterfaceManager = vpnInterfaceManager;
333             this.broker = broker;
334             this.vpnInstance = value;
335         }
336
337         @Override
338         public List<ListenableFuture<Void>> call() throws Exception {
339             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
340             // to call the respective helpers.
341             final VpnAfConfig config = vpnInstance.getIpv4Family();
342             WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
343             WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
344             addVpnInstance(vpnInstance, writeConfigTxn, writeOperTxn);
345             CheckedFuture<Void, TransactionCommitFailedException> checkFutures = writeOperTxn.submit();
346             try {
347                 checkFutures.get();
348             } catch (InterruptedException | ExecutionException e) {
349                 LOG.error("Error creating vpn {} ", vpnInstance.getVpnInstanceName());
350                 throw new RuntimeException(e.getMessage());
351             }
352             List<ListenableFuture<Void>> futures = new ArrayList<>();
353             futures.add(writeConfigTxn.submit());
354             ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
355             Futures.addCallback(listenableFuture,
356                 new PostAddVpnInstanceWorker(config, vpnInstance.getVpnInstanceName()));
357             return futures;
358         }
359     }
360
361     // TODO Clean up the exception handling
362     @SuppressWarnings("checkstyle:IllegalCatch")
363     private void addVpnInstance(VpnInstance value, WriteTransaction writeConfigTxn,
364         WriteTransaction writeOperTxn) {
365         VpnAfConfig config = value.getIpv4Family();
366         String rd = config.getRouteDistinguisher();
367         String vpnInstanceName = value.getVpnInstanceName();
368
369         long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
370         if (vpnId == 0) {
371             LOG.error(
372                 "Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}",
373                 value.getVpnInstanceName());
374             LOG.error(
375                 "Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}",
376                 value.getVpnInstanceName());
377             return;
378         }
379         LOG.info("VPN Id {} generated for VpnInstanceName {}", vpnId, vpnInstanceName);
380         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
381             vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
382             : vpnInstanceName);
383
384         if (writeConfigTxn != null) {
385             writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
386                 VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
387                 vpnInstanceToVpnId, true);
388         } else {
389             TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
390                 VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
391                 vpnInstanceToVpnId, TransactionUtil.DEFAULT_CALLBACK);
392         }
393
394         VpnIds vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
395             (rd != null) ? rd : value.getVpnInstanceName(), (rd != null)/*isExternalVpn*/);
396
397         if (writeConfigTxn != null) {
398             writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
399                 VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
400                 vpnIdToVpnInstance, true);
401         } else {
402             TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
403                 VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
404                 vpnIdToVpnInstance, TransactionUtil.DEFAULT_CALLBACK);
405         }
406
407         try {
408             String cachedTransType = fibManager.getConfTransType();
409             if (cachedTransType.equals("Invalid")) {
410                 try {
411                     fibManager.setConfTransType("L3VPN", "VXLAN");
412                 } catch (Exception e) {
413                     LOG.error("Exception caught setting the L3VPN tunnel transportType", e);
414                 }
415             } else {
416                 LOG.trace("Configured tunnel transport type for L3VPN as {}", cachedTransType);
417             }
418         } catch (Exception e) {
419             LOG.error("Error when trying to retrieve tunnel transport type for L3VPN ", e);
420         }
421
422         if (rd == null) {
423             VpnInstanceOpDataEntryBuilder builder =
424                 new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
425                     .setVpnInstanceName(vpnInstanceName);
426             if (writeOperTxn != null) {
427                 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
428                     VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
429                     builder.build(), true);
430             } else {
431                 TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
432                     VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
433                     builder.build(), TransactionUtil.DEFAULT_CALLBACK);
434             }
435         } else {
436             VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder()
437                 .setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName);
438
439             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
440                 .instance.op.data.entry.vpntargets.VpnTarget>
441                 opVpnTargetList = new ArrayList<>();
442             VpnTargets vpnTargets = config.getVpnTargets();
443             if (vpnTargets != null) {
444                 List<VpnTarget> vpnTargetList = vpnTargets.getVpnTarget();
445                 if (vpnTargetList != null) {
446                     for (VpnTarget vpnTarget : vpnTargetList) {
447                         VpnTargetBuilder vpnTargetBuilder =
448                             new VpnTargetBuilder().setKey(new VpnTargetKey(vpnTarget.getKey().getVrfRTValue()))
449                                 .setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
450                                     .instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget.VrfRTType
451                                     .forValue(vpnTarget.getVrfRTType().getIntValue())).setVrfRTValue(
452                                 vpnTarget.getVrfRTValue());
453                         opVpnTargetList.add(vpnTargetBuilder.build());
454                     }
455                 }
456             }
457             VpnTargetsBuilder vpnTargetsBuilder = new VpnTargetsBuilder().setVpnTarget(opVpnTargetList);
458             builder.setVpnTargets(vpnTargetsBuilder.build());
459
460             if (writeOperTxn != null) {
461                 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
462                     VpnUtil.getVpnInstanceOpDataIdentifier(rd),
463                     builder.build(), true);
464             } else {
465                 TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
466                     VpnUtil.getVpnInstanceOpDataIdentifier(rd),
467                     builder.build(), TransactionUtil.DEFAULT_CALLBACK);
468             }
469         }
470         LOG.info("VpnInstanceOpData populated successfully for vpn {} rd {}", vpnInstanceName, rd);
471     }
472
473
474     private class PostAddVpnInstanceWorker implements FutureCallback<List<Void>> {
475         VpnAfConfig config;
476         String vpnName;
477
478         PostAddVpnInstanceWorker(VpnAfConfig config, String vpnName) {
479             this.config = config;
480             this.vpnName = vpnName;
481         }
482
483         /**
484          * This implies that all the future instances have returned success. -- TODO: Confirm this
485          */
486         @Override
487         public void onSuccess(List<Void> voids) {
488             /*
489             if rd is null, then its either a router vpn instance (or) a vlan external network vpn instance.
490             if rd is non-null, then it is a bgpvpn instance
491              */
492             String rd = config.getRouteDistinguisher();
493             if ((rd == null) || addBgpVrf(voids)) {
494                 notifyTask();
495                 vpnInterfaceManager.vpnInstanceIsReady(vpnName);
496             }
497         }
498
499         // TODO Clean up the exception handling
500         @SuppressWarnings("checkstyle:IllegalCatch")
501         private boolean addBgpVrf(List<Void> voids) {
502             String rd = config.getRouteDistinguisher();
503             List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
504
505             List<String> ertList = new ArrayList<String>();
506             List<String> irtList = new ArrayList<String>();
507
508             if (vpnTargetList != null) {
509                 for (VpnTarget vpnTarget : vpnTargetList) {
510                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
511                         ertList.add(vpnTarget.getVrfRTValue());
512                     }
513                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
514                         irtList.add(vpnTarget.getVrfRTValue());
515                     }
516                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
517                         ertList.add(vpnTarget.getVrfRTValue());
518                         irtList.add(vpnTarget.getVrfRTValue());
519                     }
520                 }
521             } else {
522                 LOG.error("vpn target list is empty, cannot add BGP VPN {} VRF {}", this.vpnName, rd);
523                 return false;
524             }
525             try {
526                 bgpManager.addVrf(rd, irtList, ertList);
527             } catch (Exception e) {
528                 LOG.error("Exception when adding VRF to BGP", e);
529                 return false;
530             }
531             vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
532             return true;
533         }
534
535         private void notifyTask() {
536             vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName);
537             vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnOpData, vpnName);
538         }
539
540         /**
541          * This method is used to handle failure callbacks.
542          * If more retry needed, the retrycount is decremented and mainworker is executed again.
543          * After retries completed, rollbackworker is executed.
544          * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
545          */
546
547         @Override
548         public void onFailure(Throwable throwable) {
549             LOG.error("Job for vpnInstance: {} failed with exception: {}", vpnName ,throwable);
550             vpnInterfaceManager.vpnInstanceFailed(vpnName);
551         }
552     }
553
554     public boolean isVPNConfigured() {
555
556         InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class).build();
557         Optional<VpnInstances> optionalVpns = TransactionUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
558             vpnsIdentifier);
559         if (!optionalVpns.isPresent()
560             || optionalVpns.get().getVpnInstance() == null
561             || optionalVpns.get().getVpnInstance().isEmpty()) {
562             LOG.trace("No VPNs configured.");
563             return false;
564         }
565         LOG.trace("VPNs are configured on the system.");
566         return true;
567     }
568
569     protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
570         InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
571         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
572             TransactionUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
573         if (vpnInstanceOpData.isPresent()) {
574             return vpnInstanceOpData.get();
575         }
576         return null;
577     }
578 }