import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
}
}
+ public void addVrfTable(String rd, WriteTransaction writeConfigTxn) {
+ LOG.debug("Adding vrf table for rd {}", rd);
+ InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+ VrfTablesBuilder vrfTablesBuilder = new VrfTablesBuilder().setKey(new VrfTablesKey(rd))
+ .setRouteDistinguisher(rd).setVrfEntry(new ArrayList<VrfEntry>());
+ if (writeConfigTxn != null) {
+ writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTablesBuilder.build());
+ } else {
+ MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ vrfTableId, vrfTablesBuilder.build());
+ }
+ }
+
public void removeVrfTable(String rd, WriteTransaction writeConfigTxn) {
LOG.debug("Removing vrf table for rd {}", rd);
InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
package org.opendaylight.netvirt.vpnmanager;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.ExecutionException;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.genius.utils.SystemPropertyReader;
import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.Vpn;
String primaryRd = update.getVrfId();
final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
jobCoordinator.enqueueJob("VPN-" + update.getVpnInstanceName(), () -> {
- WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
+ WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
+ WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
// Clean up VpnInstanceToVpnId from Config DS
- VpnUtil.removeVpnIdToVpnInstance(dataBroker, vpnId, writeTxn);
- VpnUtil.removeVpnInstanceToVpnId(dataBroker, vpnName, writeTxn);
+ VpnUtil.removeVpnIdToVpnInstance(dataBroker, vpnId, writeConfigTxn);
+ VpnUtil.removeVpnInstanceToVpnId(dataBroker, vpnName, writeConfigTxn);
LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", primaryRd, vpnName);
+
// Clean up FIB Entries Config DS
- fibManager.removeVrfTable(primaryRd, null);
+ synchronized (vpnName.intern()) {
+ fibManager.removeVrfTable(primaryRd, null);
+ }
+
// Clean up VPNExtraRoutes Operational DS
if (VpnUtil.isBgpVpn(vpnName, primaryRd)) {
if (update.getType() == VpnInstanceOpDataEntry.Type.L2) {
Optional<Vpn> optVpnToExtraroute = VpnUtil.read(dataBroker,
LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
if (optVpnToExtraroute.isPresent()) {
- VpnUtil.removeVpnExtraRouteForVpn(dataBroker, vpnName, writeTxn);
+ VpnUtil.removeVpnExtraRouteForVpn(dataBroker, vpnName, writeOperTxn);
}
if (VpnUtil.isL3VpnOverVxLan(update.getL3vni())) {
VpnUtil.removeExternalTunnelDemuxFlows(vpnName, dataBroker, mdsalManager);
}
- // Clean up VPNInstanceOpDataEntry
- VpnUtil.removeVpnOpInstance(dataBroker, primaryRd, writeTxn);
// Clean up PrefixToInterface Operational DS
- VpnUtil.removePrefixToInterfaceForVpnId(dataBroker, vpnId, writeTxn);
+ Optional<VpnIds> optPrefixToIntf = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(vpnId));
+ if (optPrefixToIntf.isPresent()) {
+ VpnUtil.removePrefixToInterfaceForVpnId(dataBroker, vpnId, writeOperTxn);
+ }
// Clean up L3NextHop Operational DS
- VpnUtil.removeL3nexthopForVpnId(dataBroker, vpnId, writeTxn);
+ InstanceIdentifier<VpnNexthops> vpnNextHops = InstanceIdentifier.builder(L3nexthop.class).child(
+ VpnNexthops.class, new VpnNexthopsKey(vpnId)).build();
+ Optional<VpnNexthops> optL3nexthopForVpnId = VpnUtil.read(dataBroker,
+ LogicalDatastoreType.OPERATIONAL,
+ vpnNextHops);
+ if (optL3nexthopForVpnId.isPresent()) {
+ VpnUtil.removeL3nexthopForVpnId(dataBroker, vpnId, writeOperTxn);
+ }
+
+ // Clean up VPNInstanceOpDataEntry
+ VpnUtil.removeVpnOpInstance(dataBroker, primaryRd, writeOperTxn);
- // Release the ID used for this VPN back to IdManager
- VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
+ // Note: Release the of VpnId will happen in PostDeleteVpnInstancWorker only if
+ // operationalTxn/Config succeeds.
+ CheckedFuture<Void, TransactionCommitFailedException> checkFutures = writeOperTxn.submit();
+ try {
+ checkFutures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error deleting vpn {} ", vpnName);
+ writeConfigTxn.cancel();
+ throw new RuntimeException(e);
+ }
List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(writeTxn.submit());
+ futures.add(writeConfigTxn.submit());
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ Futures.addCallback(listenableFuture, new VpnOpStatusListener.PostDeleteVpnInstanceWorker(vpnName));
+ LOG.info("Removed vpn data for vpnname {}", vpnName);
return futures;
}, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
} else if (update.getVpnState() == VpnInstanceOpDataEntry.VpnState.Created) {
final VpnInstanceOpDataEntry value) {
LOG.debug("add: Ignoring vpn Op {} with rd {}", value.getVpnInstanceName(), value.getVrfId());
}
+
+ private class PostDeleteVpnInstanceWorker implements FutureCallback<List<Void>> {
+ private final Logger log = LoggerFactory.getLogger(VpnOpStatusListener.PostDeleteVpnInstanceWorker.class);
+ String vpnName;
+
+ PostDeleteVpnInstanceWorker(String vpnName) {
+ this.vpnName = vpnName;
+ }
+
+ /**
+ * This implies that all the future instances have returned success.
+ * Release the ID used for VPN back to IdManager
+ */
+ @Override
+ public void onSuccess(List<Void> voids) {
+ VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
+ log.info("onSuccess: VpnId for VpnName {} is released to IdManager successfully.", vpnName);
+ }
+
+ /**
+ * This method is used to handle failure callbacks.
+ */
+ @Override
+ public void onFailure(Throwable throwable) {
+ log.error("onFailure: Job for vpnInstance: {} failed with exception:",
+ vpnName , throwable);
+ }
+ }
}