*/
package org.opendaylight.netvirt.vpnmanager;
-import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
-import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantLock;
-import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
import org.opendaylight.genius.infra.Datastore.Configuration;
import org.opendaylight.genius.infra.Datastore.Operational;
import org.opendaylight.genius.utils.JvmGlobalLocks;
import org.opendaylight.genius.utils.SystemPropertyReader;
import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
-import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
+import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
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.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIpKey;
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.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.neutronvpn.l3vpn.rev200204.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.Uint32;
import org.opendaylight.yangtools.yang.common.Uint64;
import org.slf4j.LoggerFactory;
@Singleton
-public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInstance, VpnInstanceListener> {
+public class VpnInstanceListener extends AbstractAsyncDataTreeChangeListener<VpnInstance> {
private static final Logger LOG = LoggerFactory.getLogger(VpnInstanceListener.class);
private static final String LOGGING_PREFIX_ADD = "VPN-ADD:";
private static final String LOGGING_PREFIX_UPDATE = "VPN-UPDATE:";
final VpnInterfaceManager vpnInterfaceManager, final IFibManager fibManager,
final VpnOpDataSyncer vpnOpDataSyncer, final IMdsalApiManager mdsalManager,
final JobCoordinator jobCoordinator, VpnUtil vpnUtil) {
- super(VpnInstance.class, VpnInstanceListener.class);
+ super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class),
+ Executors.newListeningSingleThreadExecutor("VpnInstanceListener", LOG));
this.dataBroker = dataBroker;
this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
this.idManager = idManager;
this.mdsalManager = mdsalManager;
this.jobCoordinator = jobCoordinator;
this.vpnUtil = vpnUtil;
+ start();
}
- @PostConstruct
public void start() {
LOG.info("{} start", getClass().getSimpleName());
- registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
}
@Override
- protected InstanceIdentifier<VpnInstance> getWildCardPath() {
- return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
+ @PreDestroy
+ public void close() {
+ super.close();
+ Executors.shutdownAndAwaitTermination(getExecutorService());
}
- @Override
- protected VpnInstanceListener getDataTreeChangeListener() {
- return VpnInstanceListener.this;
- }
@Override
- protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
+ public void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
LOG.trace("{} : VPN event key: {}, value: {}", LOGGING_PREFIX_DELETE, identifier, del);
final String vpnName = del.getVpnInstanceName();
Optional<VpnInstanceOpDataEntry> vpnOpValue;
try {
vpnOpValue = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd));
- } catch (ReadFailedException e) {
+ } catch (InterruptedException | ExecutionException e) {
LOG.error("{}, failed to remove VPN: Exception while retrieving VpnInstanceOpDataEntry for VPN {}. ",
LOGGING_PREFIX_DELETE, vpnName, e);
return;
}
@Override
- protected void update(InstanceIdentifier<VpnInstance> identifier,
+ public void update(InstanceIdentifier<VpnInstance> identifier,
VpnInstance original, VpnInstance update) {
LOG.trace("VPN-UPDATE: update: VPN event key: {}, value: {}.", identifier, update);
String vpnName = update.getVpnInstanceName();
- if (original.getIpv4Family() != null && update.getIpv4Family() != null
- && original.getIpv4Family().getRouteDistinguisher() != null
- && update.getIpv4Family().getRouteDistinguisher() != null
- && original.getIpv4Family().getRouteDistinguisher().size()
- != update.getIpv4Family().getRouteDistinguisher().size()) {
+ if (original != null && update != null
+ && original.getRouteDistinguisher() != null
+ && update.getRouteDistinguisher() != null
+ && original.getRouteDistinguisher().size()
+ != update.getRouteDistinguisher().size()) {
LOG.debug("VPN-UPDATE: VpnInstance:{} updated with new RDs: {} from old RDs: {}", vpnName,
- update.getIpv4Family().getRouteDistinguisher(), original.getIpv4Family().getRouteDistinguisher());
- vpnUtil.updateVpnInstanceWithRdList(vpnName, update.getIpv4Family().getRouteDistinguisher());
+ update.getRouteDistinguisher(), original.getRouteDistinguisher());
+ vpnUtil.updateVpnInstanceWithRdList(vpnName, update.getRouteDistinguisher());
}
vpnInterfaceManager.updateVpnInterfacesForUnProcessAdjancencies(vpnName);
}
@Override
- protected void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
+ public void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
LOG.trace("{} add: Add VPN event key: {}, value: {}", LOGGING_PREFIX_ADD, identifier, value);
final String vpnName = value.getVpnInstanceName();
jobCoordinator.enqueueJob("VPN-" + vpnName, new AddVpnInstanceWorker(dataBroker, value),
SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
}
- private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
+ private class AddVpnInstanceWorker implements Callable<List<? extends ListenableFuture<?>>> {
private final Logger log = LoggerFactory.getLogger(AddVpnInstanceWorker.class);
VpnInstance vpnInstance;
DataBroker broker;
futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx ->
addVpnInstance(vpnInstance, confTx, operTx));
- ListenableFutures.addErrorLogging(future, LOG, "{} call: error creating VPN {} rd {}",
+ LoggingFutures.addErrorLogging(future, LOG, "{} call: error creating VPN {} rd {}",
LOGGING_PREFIX_ADD, vpnInstance.getVpnInstanceName(),
- vpnInstance.getIpv4Family().getRouteDistinguisher());
+ vpnInstance.getRouteDistinguisher());
futures.add(future);
}));
Futures.addCallback(Futures.allAsList(futures),
private void addVpnInstance(VpnInstance value, TypedWriteTransaction<Configuration> writeConfigTxn,
TypedWriteTransaction<Operational> writeOperTxn) {
if (writeConfigTxn == null) {
- ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx ->
+ LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx ->
addVpnInstance(value, tx, writeOperTxn)), LOG, "Error adding VPN instance {}", value);
return;
}
if (writeOperTxn == null) {
- ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx ->
+ LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx ->
addVpnInstance(value, writeConfigTxn, tx)), LOG, "Error adding VPN instance {}", value);
return;
}
- VpnAfConfig config = value.getIpv4Family();
String vpnInstanceName = value.getVpnInstanceName();
Uint32 vpnId = vpnUtil.getUniqueId(VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, primaryRd);
- writeConfigTxn.put(VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
- vpnInstanceToVpnId, CREATE_MISSING_PARENTS);
+ writeConfigTxn.mergeParentStructurePut(VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
+ vpnInstanceToVpnId);
VpnIds vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
primaryRd, VpnUtil.isBgpVpn(vpnInstanceName, primaryRd));
- writeConfigTxn.put(VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId), vpnIdToVpnInstance, CREATE_MISSING_PARENTS);
+ writeConfigTxn.mergeParentStructurePut(VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId), vpnIdToVpnInstance);
try {
String cachedTransType = fibManager.getConfTransType();
if (value.getL3vni() != null) {
builder.setL3vni(value.getL3vni());
}
- if (value.getType() == VpnInstance.Type.L2) {
+ if (value.isL2vpn()) {
builder.setType(VpnInstanceOpDataEntry.Type.L2);
}
- VpnTargets vpnTargets = config.getVpnTargets();
+ VpnTargets vpnTargets = value.getVpnTargets();
if (vpnTargets != null) {
- List<VpnTarget> vpnTargetList = vpnTargets.getVpnTarget();
- if (vpnTargetList != null) {
- for (VpnTarget vpnTarget : vpnTargetList) {
+ @Nullable Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn
+ .instances.vpn.instance.vpntargets.VpnTargetKey, VpnTarget> vpnTargetListMap
+ = vpnTargets.nonnullVpnTarget();
+ if (vpnTargetListMap != null) {
+ for (VpnTarget vpnTarget : vpnTargetListMap.values()) {
VpnTargetBuilder vpnTargetBuilder =
new VpnTargetBuilder().withKey(new VpnTargetKey(vpnTarget.key().getVrfRTValue()))
.setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
VpnTargetsBuilder vpnTargetsBuilder = new VpnTargetsBuilder().setVpnTarget(opVpnTargetList);
builder.setVpnTargets(vpnTargetsBuilder.build());
- List<String> rds = config.getRouteDistinguisher();
+ List<String> rds = value.getRouteDistinguisher();
builder.setRd(rds);
} else {
builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.VPN);
}
- writeOperTxn.merge(VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd), builder.build(), CREATE_MISSING_PARENTS);
+ writeOperTxn.mergeParentStructureMerge(VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd), builder.build());
LOG.info("{} addVpnInstance: VpnInstanceOpData populated successfully for vpn {} rd {}", LOGGING_PREFIX_ADD,
vpnInstanceName, primaryRd);
}
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
*/
- VpnAfConfig config = vpnInstance.getIpv4Family();
- List<String> rd = config.getRouteDistinguisher();
+ List<String> rd = vpnInstance.getRouteDistinguisher();
if (rd == null || addBgpVrf()) {
notifyTask();
vpnInterfaceManager.vpnInstanceIsReady(vpnName);
Arrays.asList(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnInstanceOpDataEntry
.getVpnId().toJava()), MetaDataUtil.METADATA_MASK_VRFID),
new InstructionGotoTable(NwConstants.L3_GW_MAC_TABLE));
-
- for (Uint64 dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
- String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
- vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
- FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
- NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef, VpnConstants.DEFAULT_FLOW_PRIORITY,
- "VxLAN VPN Tunnel Bind Service", 0, 0, NwConstants.COOKIE_VM_FIB_TABLE,
- mkMatches, instructions);
- mdsalManager.installFlow(dpnId, flowEntity);
+ try {
+ for (Uint64 dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
+ String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
+ vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
+ NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef,
+ VpnConstants.DEFAULT_FLOW_PRIORITY, "VxLAN VPN Tunnel Bind Service",
+ 0, 0, NwConstants.COOKIE_VM_FIB_TABLE, mkMatches, instructions);
+ mdsalManager.installFlow(dpnId, flowEntity);
+ }
+ } catch (ExecutionException | InterruptedException e) {
+ LOG.error("PostAddVpnInstanceWorker: Exception while getting the list of Operative DPNs for Vpn {}",
+ vpnName, e);
}
///////////////////////
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
private boolean addBgpVrf() {
- VpnAfConfig config = vpnInstance.getIpv4Family();
String primaryRd = vpnUtil.getPrimaryRd(vpnName);
- List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+ @Nullable Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn
+ .instances.vpn.instance.vpntargets.VpnTargetKey, VpnTarget> vpnTargetList
+ = vpnInstance.getVpnTargets().getVpnTarget();
if (vpnTargetList == null) {
log.error("{} addBgpVrf: vpn target list is empty for vpn {} RD {}", LOGGING_PREFIX_ADD,
InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
try {
return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
- id).orNull();
- } catch (ReadFailedException e) {
+ id).orElse(null);
+ } catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("Error reading VPN instance data for " + rd, e);
}
}
LOG.info("No DC gateways configured.");
return tunnelInterfaceNameList;
}
- List<DcGatewayIp> dcGatewayIps = dcGatewayIpListOptional.get().nonnullDcGatewayIp();
+ Map<DcGatewayIpKey, DcGatewayIp> keyDcGatewayIpMap = dcGatewayIpListOptional.get().nonnullDcGatewayIp();
InstanceIdentifier<ExternalTunnelList> externalTunnelListId = InstanceIdentifier
.create(ExternalTunnelList.class);
Optional<ExternalTunnelList> externalTunnelListOptional = SingleTransactionDataBroker.syncReadOptional(
dataBroker, LogicalDatastoreType.OPERATIONAL, externalTunnelListId);
if (externalTunnelListOptional.isPresent()) {
- List<ExternalTunnel> externalTunnels = externalTunnelListOptional.get().nonnullExternalTunnel();
+ Map<ExternalTunnelKey, ExternalTunnel> keyExternalTunnelMap
+ = externalTunnelListOptional.get().nonnullExternalTunnel();
List<String> externalTunnelIpList = new ArrayList<>();
- for (ExternalTunnel externalTunnel: externalTunnels) {
+ for (ExternalTunnel externalTunnel: keyExternalTunnelMap.values()) {
externalTunnelIpList.add(externalTunnel.getDestinationDevice());
}
List<String> dcGatewayIpList = new ArrayList<>();
- for (DcGatewayIp dcGatewayIp: dcGatewayIps) {
+ for (DcGatewayIp dcGatewayIp: keyDcGatewayIpMap.values()) {
dcGatewayIpList.add(dcGatewayIp.getIpAddress().getIpv4Address().toString());
}
// Find all externalTunnelIps present in dcGateWayIpList
}
}
for (String externalTunnelIpsInDcGatewayIp: externalTunnelIpsInDcGatewayIpList) {
- for (ExternalTunnel externalTunnel: externalTunnels) {
+ for (ExternalTunnel externalTunnel: keyExternalTunnelMap.values()) {
if (externalTunnel.getDestinationDevice().contentEquals(externalTunnelIpsInDcGatewayIp)) {
tunnelInterfaceNameList.add(externalTunnel.getTunnelInterfaceName());
}
}
}
- } catch (ReadFailedException e) {
+ } catch (InterruptedException | ExecutionException e) {
LOG.error("getDcGatewayTunnelInterfaceNameList: Failed to read data store");
}
return tunnelInterfaceNameList;