import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
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.DataStoreJobCoordinator;
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.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.VpnInstanceOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnTargetsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class VpnInstanceListener extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
+public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInstance, VpnInstanceListener>
+ implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(VpnInstanceListener.class);
- private ListenerRegistration<DataChangeListener> listenerRegistration;
private final DataBroker dataBroker;
private final IBgpManager bgpManager;
private final IdManagerService idManager;
private final VpnInterfaceManager vpnInterfaceManager;
private final IFibManager fibManager;
- private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
- .setNameFormat("NV-VpnMgr-%d").build();
- private ExecutorService executorService = Executors.newSingleThreadExecutor(threadFactory);
- private ConcurrentMap<String, Runnable> vpnOpMap = new ConcurrentHashMap<String, Runnable>();
+ private final VpnOpDataSyncer vpnOpDataNotifier;
public VpnInstanceListener(final DataBroker dataBroker, final IBgpManager bgpManager,
final IdManagerService idManager,
final VpnInterfaceManager vpnInterfaceManager,
- final IFibManager fibManager) {
- super(VpnInstance.class);
+ final IFibManager fibManager,
+ final VpnOpDataSyncer vpnOpDataSyncer) {
+ super(VpnInstance.class, VpnInstanceListener.class);
this.dataBroker = dataBroker;
this.bgpManager = bgpManager;
this.idManager = idManager;
this.vpnInterfaceManager = vpnInterfaceManager;
this.fibManager = fibManager;
+ this.vpnOpDataNotifier = vpnOpDataSyncer;
}
public void start() {
LOG.info("{} start", getClass().getSimpleName());
- listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
- getWildCardPath(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
}
- private InstanceIdentifier<VpnInstance> getWildCardPath() {
+ @Override
+ protected InstanceIdentifier<VpnInstance> getWildCardPath() {
return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
}
@Override
- public void close() throws Exception {
- if (listenerRegistration != null) {
- listenerRegistration.close();
- listenerRegistration = null;
- }
- LOG.info("{} close", getClass().getSimpleName());
- }
-
- void notifyTaskIfRequired(String vpnName) {
- Runnable notifyTask = vpnOpMap.remove(vpnName);
- if (notifyTask == null) {
- LOG.trace("VpnInstanceListener update: No Notify Task queued for vpnName {}", vpnName);
- return;
- }
- executorService.execute(notifyTask);
+ protected VpnInstanceListener getDataTreeChangeListener() {
+ return VpnInstanceListener.this;
}
private void waitForOpRemoval(String rd, String vpnName) {
VpnInstanceOpDataEntry vpnOpEntry = null;
Long intfCount = 0L;
Long currentIntfCount = 0L;
- Integer retryCount = 2;
+ Integer retryCount = 3;
long timeout = VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd));
if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
vpnOpEntry = vpnOpValue.get();
LOG.trace("Remove VPN event key: {}, value: {}", identifier, del);
final String vpnName = del.getVpnInstanceName();
final String rd = del.getIpv4Family().getRouteDistinguisher();
- final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
//TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
// Clean up VpnInstanceToVpnId from Config DS
VpnUtil.removeVpnIdToVpnInstance(broker, vpnId, writeTxn);
VpnUtil.removeVpnInstanceToVpnId(broker, vpnName, writeTxn);
-
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- futures.add(writeTxn.submit());
LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", rd, vpnName);
if (rd != null) {
synchronized (vpnName.intern()) {
}
// Clean up VPNExtraRoutes Operational DS
- VpnUtil.removeVpnExtraRouteForVpn(broker, rd, null);
+ InstanceIdentifier<Vpn> vpnToExtraroute = VpnUtil.getVpnToExtrarouteIdentifier(rd);
+ Optional<Vpn> optVpnToExtraroute = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
+ if (optVpnToExtraroute.isPresent()) {
+ VpnUtil.removeVpnExtraRouteForVpn(broker, rd, writeTxn);
+ }
// Clean up VPNInstanceOpDataEntry
- VpnUtil.removeVpnOpInstance(broker, rd, null);
+ VpnUtil.removeVpnOpInstance(broker, rd, writeTxn);
} else {
// Clean up FIB Entries Config DS
synchronized (vpnName.intern()) {
fibManager.removeVrfTable(broker, vpnName, null);
}
// Clean up VPNExtraRoutes Operational DS
- VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName, null);
+ InstanceIdentifier<Vpn> vpnToExtraroute = VpnUtil.getVpnToExtrarouteIdentifier(vpnName);
+ Optional<Vpn> optVpnToExtraroute = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
+ if (optVpnToExtraroute.isPresent()) {
+ VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName, writeTxn);
+ }
// Clean up VPNInstanceOpDataEntry
- VpnUtil.removeVpnOpInstance(broker, vpnName, null);
+ VpnUtil.removeVpnOpInstance(broker, vpnName, writeTxn);
}
// Clean up PrefixToInterface Operational DS
- VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId, null);
+ VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId, writeTxn);
// Clean up L3NextHop Operational DS
- VpnUtil.removeL3nexthopForVpnId(broker, vpnId, null);
+ VpnUtil.removeL3nexthopForVpnId(broker, vpnId, writeTxn);
// Release the ID used for this VPN back to IdManager
VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
return futures;
}
}
@Override
protected void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
LOG.trace("Add VPN event key: {}, value: {}", identifier, value);
- final VpnAfConfig config = value.getIpv4Family();
- final String rd = config.getRouteDistinguisher();
final String vpnName = value.getVpnInstanceName();
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
// If another renderer(for eg : CSS) needs to be supported, check can be performed here
// to call the respective helpers.
final VpnAfConfig config = vpnInstance.getIpv4Family();
- final String rd = config.getRouteDistinguisher();
WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
addVpnInstance(vpnInstance, writeConfigTxn, writeOperTxn);
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(writeConfigTxn.submit());
ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
- if (rd != null) {
- Futures.addCallback(listenableFuture,
- new AddBgpVrfWorker(config , vpnInstance.getVpnInstanceName()));
- }
+ Futures.addCallback(listenableFuture,
+ new PostAddVpnInstanceWorker(config , vpnInstance.getVpnInstanceName()));
return futures;
}
}
String vpnInstanceName = value.getVpnInstanceName();
long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
- LOG.trace("VPN instance to ID generated.");
+ if (vpnId == 0) {
+ LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
+ LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
+ return;
+ }
+ LOG.info("VPN Id {} generated for VpnInstanceName {}", vpnId, vpnInstanceName);
org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
: vpnInstanceName);
try {
String cachedTransType = fibManager.getConfTransType();
- LOG.trace("Value for confTransportType is " + cachedTransType);
if (cachedTransType.equals("Invalid")) {
try {
fibManager.setConfTransType("L3VPN", "VXLAN");
} catch (Exception e) {
- LOG.trace("Exception caught setting the cached value for transportType");
- LOG.error(e.getMessage());
+ LOG.error("Exception caught setting the L3VPN tunnel transportType", e);
}
} else {
- LOG.trace(":cached val is neither unset/invalid. NO-op.");
+ LOG.trace("Configured tunnel transport type for L3VPN as {}", cachedTransType);
}
} catch (Exception e) {
- LOG.error(e.getMessage());
+ LOG.error("Error when trying to retrieve tunnel transport type for L3VPN ", e);
}
if (rd == null) {
VpnInstanceOpDataEntryBuilder builder =
new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
- .setVpnInstanceName(vpnInstanceName)
- .setVpnInterfaceCount(0L);
+ .setVpnInstanceName(vpnInstanceName);
if (writeOperTxn != null) {
writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
builder.build(), TransactionUtil.DEFAULT_CALLBACK);
}
- synchronized (vpnInstanceName.intern()) {
- fibManager.addVrfTable(dataBroker, vpnInstanceName, null);
- }
} else {
VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder()
- .setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName).setVpnInterfaceCount(0L);
+ .setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName);
+
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget> opVpnTargetList = new ArrayList<>();
+ VpnTargets vpnTargets = config.getVpnTargets();
+ if (vpnTargets != null) {
+ List<VpnTarget> vpnTargetList = vpnTargets.getVpnTarget();
+ if (vpnTargetList != null) {
+ for (VpnTarget vpnTarget : vpnTargetList) {
+ VpnTargetBuilder vpnTargetBuilder = new VpnTargetBuilder().setKey(new VpnTargetKey(vpnTarget.getKey().getVrfRTValue()))
+ .setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
+ .instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget.VrfRTType
+ .forValue(vpnTarget.getVrfRTType().getIntValue())).setVrfRTValue(vpnTarget.getVrfRTValue());
+ opVpnTargetList.add(vpnTargetBuilder.build());
+ }
+ }
+ }
+ VpnTargetsBuilder vpnTargetsBuilder = new VpnTargetsBuilder().setVpnTarget(opVpnTargetList);
+ builder.setVpnTargets(vpnTargetsBuilder.build());
if (writeOperTxn != null) {
writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
VpnUtil.getVpnInstanceOpDataIdentifier(rd),
builder.build(), TransactionUtil.DEFAULT_CALLBACK);
}
- synchronized (vpnInstanceName.intern()) {
- fibManager.addVrfTable(dataBroker, rd, null);
- }
}
+ LOG.info("VpnInstanceOpData populated successfully for vpn {} rd {}", vpnInstanceName, rd);
}
- private class AddBgpVrfWorker implements FutureCallback<List<Void>> {
+ private class PostAddVpnInstanceWorker implements FutureCallback<List<Void>> {
VpnAfConfig config;
String vpnName;
- public AddBgpVrfWorker(VpnAfConfig config, String vpnName) {
+ public PostAddVpnInstanceWorker(VpnAfConfig config, String vpnName) {
this.config = config;
this.vpnName = vpnName;
}
*/
@Override
public void onSuccess(List<Void> voids) {
+ /*
+ if rd is null, then its either a router vpn instance (or) a vlan external network vpn instance.
+ if rd is non-null, then it is a bgpvpn instance
+ */
String rd = config.getRouteDistinguisher();
- if (rd != null) {
- List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+ if ((rd == null) || addBgpVrf(voids)) {
+ notifyTask();
+ }
+ }
+
+ private boolean addBgpVrf(List<Void> voids) {
+ String rd = config.getRouteDistinguisher();
+ List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
- List<String> ertList = new ArrayList<String>();
- List<String> irtList = new ArrayList<String>();
+ List<String> ertList = new ArrayList<String>();
+ List<String> irtList = new ArrayList<String>();
+ if (vpnTargetList != null) {
for (VpnTarget vpnTarget : vpnTargetList) {
if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
ertList.add(vpnTarget.getVrfRTValue());
irtList.add(vpnTarget.getVrfRTValue());
}
}
-
- try {
- bgpManager.addVrf(rd, irtList, ertList);
- } catch (Exception e) {
- LOG.error("Exception when adding VRF to BGP", e);
- return;
- }
- vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
+ } else {
+ LOG.error("vpn target list is empty, cannot add BGP VPN {} VRF {}", this.vpnName, rd);
+ return false;
}
+ try {
+ bgpManager.addVrf(rd, irtList, ertList);
+ } catch (Exception e) {
+ LOG.error("Exception when adding VRF to BGP", e);
+ return false;
+ }
+ vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
+ return true;
+ }
+
+ private void notifyTask() {
+ vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName);
+ vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnOpData, vpnName);
}
/**
*
@Override
public void onFailure(Throwable throwable) {
- LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
+ LOG.warn("Job: failed with exception: ", throwable);
}
}
public boolean isVPNConfigured() {
- InstanceIdentifier<VpnInstances> vpnsIdentifier =
- InstanceIdentifier.builder(VpnInstances.class).build();
+ InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class).build();
Optional<VpnInstances> optionalVpns = TransactionUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
vpnsIdentifier);
if (!optionalVpns.isPresent() ||