X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=neutronvpn%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Fneutronvpn%2FNeutronvpnManager.java;h=397e8c644e223c7b2b927be511a79e6237191891;hb=refs%2Fchanges%2F04%2F92004%2F4;hp=1bd1742f781a298e5f84675afe3d091fb5d4ed0f;hpb=1e771de00a30d2ca9019b59ec2fd0b69b87ab768;p=netvirt.git diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java index 1bd1742f78..397e8c644e 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java @@ -9,9 +9,8 @@ package org.opendaylight.netvirt.neutronvpn; import static java.util.Collections.singletonList; import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional; -import static org.opendaylight.genius.infra.Datastore.CONFIGURATION; +import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -19,6 +18,7 @@ import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -30,31 +30,36 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import javax.annotation.PreDestroy; 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.NotificationPublishService; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; -import org.opendaylight.genius.infra.Datastore; -import org.opendaylight.genius.infra.ManagedNewTransactionRunner; -import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; -import org.opendaylight.genius.infra.TypedWriteTransaction; +import org.opendaylight.genius.mdsalutil.NwConstants; +import org.opendaylight.genius.utils.JvmGlobalLocks; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; -import org.opendaylight.infrautils.utils.concurrent.KeyedLocks; -import org.opendaylight.infrautils.utils.concurrent.ListenableFutures; +import org.opendaylight.infrautils.utils.concurrent.LoggingFutures; +import org.opendaylight.infrautils.utils.concurrent.NamedLocks; +import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.util.Datastore.Configuration; +import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner; +import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl; +import org.opendaylight.mdsal.binding.util.TypedWriteTransaction; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.OptimisticLockFailedException; +import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; import org.opendaylight.netvirt.alarm.NeutronvpnAlarms; import org.opendaylight.netvirt.elanmanager.api.IElanService; import org.opendaylight.netvirt.fibmanager.api.FibHelper; @@ -64,40 +69,38 @@ import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager; import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils; import org.opendaylight.netvirt.vpnmanager.api.IVpnManager; import org.opendaylight.netvirt.vpnmanager.api.VpnHelper; -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.VpnInterfaces; -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.VpnTargetsBuilder; -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.af.config.vpntargets.VpnTargetBuilder; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort; 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.VpnInstanceOpDataEntry.BgpvpnType; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder; +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.VpnInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey; +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.VpnInstanceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey; +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.VpnTargetsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNamesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder; @@ -131,17 +134,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder; @@ -154,12 +155,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature; @@ -169,6 +172,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.att import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension; @@ -189,11 +193,10 @@ import org.slf4j.helpers.MessageFormatter; public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener { private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class); - private static long LOCK_WAIT_TIME = 10L; + private static final long LOCK_WAIT_TIME = 10L; private final DataBroker dataBroker; private final ManagedNewTransactionRunner txRunner; - private final NotificationPublishService notificationPublishService; private final VpnRpcService vpnRpcService; private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener; private final IElanService elanService; @@ -205,19 +208,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even private final IVpnManager vpnManager; private final ConcurrentHashMap unprocessedPortsMap = new ConcurrentHashMap<>(); private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms(); - private final KeyedLocks vpnLock = new KeyedLocks<>(); - private final KeyedLocks interfaceLock = new KeyedLocks<>(); + private final NamedLocks vpnLock = new NamedLocks<>(); + private final NamedLocks interfaceLock = new NamedLocks<>(); @Inject public NeutronvpnManager( - final DataBroker dataBroker, final NotificationPublishService notiPublishService, + final DataBroker dataBroker, final VpnRpcService vpnRpcSrv, final IElanService elanService, final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener, final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager, - final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) { + final JobCoordinator jobCoordinator, + final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException { this.dataBroker = dataBroker; this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); - notificationPublishService = notiPublishService; vpnRpcService = vpnRpcSrv; this.elanService = elanService; floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener; @@ -237,15 +240,25 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.info("{} close", getClass().getSimpleName()); } - private void configureFeatures() { + private void configureFeatures() throws TransactionCommitFailedException { InstanceIdentifier iid = InstanceIdentifier.builder( Neutron.class).child(Features.class).child( Feature.class, new FeatureKey(OperationalPortStatus.class)).build(); Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build(); try { SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature); - } catch (TransactionCommitFailedException e) { - LOG.warn("Error configuring feature {}", feature, e); + } catch (OptimisticLockFailedException e) { + LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e); + } + InstanceIdentifier bgpvpnVniIid = InstanceIdentifier.builder( + Neutron.class).child(Features.class).child( + Feature.class, new FeatureKey(BgpvpnVni.class)).build(); + Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build(); + try { + SingleTransactionDataBroker.syncWrite( + dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature); + } catch (OptimisticLockFailedException e) { + LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e); } } @@ -256,11 +269,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId, - NetworkAttributes.NetworkType networkType, long segmentationId) { + NetworkAttributes.@Nullable NetworkType networkType, long segmentationId, + boolean isExternalNw) { try { InstanceIdentifier subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId); - synchronized (subnetId.getValue().intern()) { - LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString()); + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); + try { + LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue()); Optional sn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier); if (sn.isPresent()) { @@ -270,13 +286,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId)) .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId) - .setNetworkType(networkType).setSegmentationId(segmentationId); + .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw); LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}", subnetId.getValue()); SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier, subnetmapBuilder.build()); + } finally { + lock.unlock(); } - } catch (TransactionCommitFailedException | ReadFailedException e) { + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue()); } // check if there are ports to update for already created Subnetmap node @@ -289,206 +307,218 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) { - Subnetmap subnetmap = null; - SubnetmapBuilder builder = null; + @Nullable + protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId, + @Nullable Uuid internetvpnId) { InstanceIdentifier id = InstanceIdentifier.builder(Subnetmaps.class) .child(Subnetmap.class, new SubnetmapKey(subnetId)) .build(); + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); try { - synchronized (subnetId.getValue().intern()) { - Optional sn = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - id); - if (sn.isPresent()) { - builder = new SubnetmapBuilder(sn.get()); - LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue()); - } else { - LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue()); - return null; - } - if (routerId != null) { - builder.setRouterId(routerId); - } - if (vpnId != null) { - builder.setVpnId(vpnId); - } + Optional sn = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id); + if (!sn.isPresent()) { + LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue()); + return null; + } + LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue()); + SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); + if (routerId != null) { + builder.setRouterId(routerId); + } + if (vpnId != null) { + builder.setVpnId(vpnId); + } + if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) { builder.setInternetVpnId(internetvpnId); - - subnetmap = builder.build(); - LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue()); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap); } - } catch (ReadFailedException | TransactionCommitFailedException e) { + Subnetmap subnetmap = builder.build(); + LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue()); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap); + return subnetmap; + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e); + return null; + } finally { + lock.unlock(); } - return subnetmap; } - protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId, - Uuid routerInterfacePortId, String fixedIp, - String routerIntfMacAddress, Uuid vpnId) { - Subnetmap subnetmap = null; - SubnetmapBuilder builder = null; + protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId, + @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp, + @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) { InstanceIdentifier id = - InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); + InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); try { - synchronized (subnetId.getValue().intern()) { - Optional sn = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - id); - if (sn.isPresent()) { - builder = new SubnetmapBuilder(sn.get()); - LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}", - subnetId.getValue()); - } else { - LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ", - subnetId.getValue()); - return; - } - builder.setRouterId(routerId); - builder.setRouterInterfacePortId(routerInterfacePortId); - builder.setRouterIntfMacAddress(routerIntfMacAddress); - builder.setRouterInterfaceFixedIp(fixedIp); - if (vpnId != null) { - builder.setVpnId(vpnId); - } - subnetmap = builder.build(); - LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ", + Optional sn = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id); + if (!sn.isPresent()) { + LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ", subnetId.getValue()); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap); + return; } - } catch (ReadFailedException | TransactionCommitFailedException e) { - LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}", + LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}", + subnetId.getValue()); + SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); + builder.setRouterId(routerId); + builder.setRouterInterfacePortId(routerInterfacePortId); + builder.setRouterIntfMacAddress(routerIntfMacAddress); + builder.setRouterInterfaceFixedIp(fixedIp); + if (vpnId != null) { + builder.setVpnId(vpnId); + } + Subnetmap subnetmap = builder.build(); + LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ", + subnetId.getValue()); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap); + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { + LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}", subnetId.getValue(), e); + } finally { + lock.unlock(); } } - protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) { + protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId, + @Nullable Uuid directPortId) { Subnetmap subnetmap = null; InstanceIdentifier id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); - LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString()); + LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue()); + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); try { - synchronized (subnetId.getValue().intern()) { - Optional sn = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - id); - if (sn.isPresent()) { - SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); - if (null != portId) { - List portList = builder.getPortList(); - if (null == portList) { - portList = new ArrayList<>(); - } - portList.add(portId); - builder.setPortList(portList); - LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}", - subnetId.getValue(), portId.getValue()); + Optional sn = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, + id); + if (sn.isPresent()) { + SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); + if (null != portId) { + List existingPortList = builder.getPortList(); + List portList = new ArrayList<>(); + if (null != existingPortList) { + portList.addAll(existingPortList); } - if (null != directPortId) { - List directPortList = builder.getDirectPortList(); - if (null == directPortList) { - directPortList = new ArrayList<>(); - } - directPortList.add(directPortId); - builder.setDirectPortList(directPortList); - LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(), - directPortId.getValue()); + portList.add(portId); + builder.setPortList(portList); + LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}", + subnetId.getValue(), portId.getValue()); + } + if (null != directPortId) { + List existingDirectPortList = builder.getDirectPortList(); + List directPortList = new ArrayList<>(); + if (null != existingDirectPortList) { + directPortList.addAll(existingDirectPortList); } - subnetmap = builder.build(); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, - subnetmap); - } else { - LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed " - + "cache ", subnetId.getValue(), portId.getValue()); - unprocessedPortsMap.put(portId, subnetId); + directPortList.add(directPortId); + builder.setDirectPortList(directPortList); + LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(), + directPortId.getValue()); } + subnetmap = builder.build(); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, + subnetmap); + } else { + LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed " + + "cache ", subnetId.getValue(), portId.getValue()); + unprocessedPortsMap.put(portId, subnetId); } - } catch (ReadFailedException | TransactionCommitFailedException e) { + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e); + } finally { + lock.unlock(); } return subnetmap; } - protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, - Uuid vpnId, Uuid portId) { + protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId, + Uuid vpnId, @Nullable Uuid portId) { Subnetmap subnetmap = null; InstanceIdentifier id = InstanceIdentifier.builder(Subnetmaps.class) .child(Subnetmap.class, new SubnetmapKey(subnetId)) .build(); + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); try { - synchronized (subnetId.getValue().intern()) { - Optional sn = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - id); - if (sn.isPresent()) { - SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); - if (routerId != null) { - builder.setRouterId(null); - } - if (networkId != null) { - builder.setNetworkId(null); - } - if (vpnId != null) { - builder.setVpnId(null); - } - builder.setInternetVpnId(null); - if (portId != null && builder.getPortList() != null) { - List portList = builder.getPortList(); - portList.remove(portId); - builder.setPortList(portList); - } - - subnetmap = builder.build(); - LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue()); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, - subnetmap); - } else { - LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue()); + Optional sn = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, + id); + if (sn.isPresent()) { + SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); + if (routerId != null) { + builder.setRouterId(null); + } + if (networkId != null) { + builder.setNetworkId(null); } + if (vpnId != null) { + builder.setVpnId(null); + } + builder.setInternetVpnId(null); + if (portId != null && builder.getPortList() != null) { + List portList = new ArrayList<>(builder.getPortList()); + portList.remove(portId); + builder.setPortList(portList); + } + + subnetmap = builder.build(); + LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue()); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, + subnetmap); + } else { + LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue()); } - } catch (ReadFailedException | TransactionCommitFailedException e) { + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue()); + } finally { + lock.unlock(); } return subnetmap; } - protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) { + @Nullable + protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId, + @Nullable Uuid directPortId) { Subnetmap subnetmap = null; InstanceIdentifier id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); try { - synchronized (subnetId.getValue().intern()) { - Optional sn = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - id); - if (sn.isPresent()) { - SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); - if (null != portId && null != builder.getPortList()) { - List portList = builder.getPortList(); - portList.remove(portId); - builder.setPortList(portList); - LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(), - subnetId.getValue()); - } - if (null != directPortId && null != builder.getDirectPortList()) { - List directPortList = builder.getDirectPortList(); - directPortList.remove(directPortId); - builder.setDirectPortList(directPortList); - LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId - .getValue(), subnetId.getValue()); - } - subnetmap = builder.build(); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, - subnetmap); - } else { - LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue()); + Optional sn = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, + id); + if (sn.isPresent()) { + SubnetmapBuilder builder = new SubnetmapBuilder(sn.get()); + if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) { + List portList = new ArrayList<>(builder.getPortList()); + portList.remove(portId); + builder.setPortList(portList); + LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(), + subnetId.getValue()); + } + if (null != directPortId && null != builder.getDirectPortList() + && !builder.getDirectPortList().isEmpty()) { + List directPortList = new ArrayList<>(builder.getDirectPortList()); + directPortList.remove(directPortId); + builder.setDirectPortList(directPortList); + LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId + .getValue(), subnetId.getValue()); } + subnetmap = builder.build(); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, + subnetmap); + } else { + LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue()); } - } catch (ReadFailedException | TransactionCommitFailedException e) { + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { LOG.error("Removing a port from port list of a subnetmap failed for node: {}", subnetId.getValue(), e); + } finally { + lock.unlock(); } return subnetmap; } @@ -499,13 +529,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even InstanceIdentifier subnetMapIdentifier = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build(); LOG.debug("removing subnetMap node: {} ", subnetId.getValue()); + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); try { - synchronized (subnetId.getValue().intern()) { - SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, - subnetMapIdentifier); - } + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier); } catch (TransactionCommitFailedException e) { LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue()); + } finally { + lock.unlock(); } } @@ -517,132 +548,124 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier); if (!vpnInstanceConfig.isPresent()) { - LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId); + LOG.debug("updateVpnInstanceWithRDs: " + + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId); return; } VpnInstance vpnInstance = vpnInstanceConfig.get(); VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance); - if (vpnInstance.getIpv4Family() != null) { - Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family()); - updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build()); - } - if (vpnInstance.getIpv6Family() != null) { - Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family()); - updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build()); - } - LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds); + updateVpnInstanceBuilder.setRouteDistinguisher(rds); + LOG.debug("updateVpnInstanceWithRDs: " + + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds); SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, updateVpnInstanceBuilder.build()); - } catch (ReadFailedException | TransactionCommitFailedException ex) { - LOG.warn("Error configuring feature ", ex); + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) { + LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with " + + "the list of RDs: {}", vpnInstanceId, rds, ex); } } private void updateVpnInstanceNode(Uuid vpnId, List rd, List irt, List ert, - VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) { + boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) { String vpnName = vpnId.getValue(); VpnInstanceBuilder builder = null; List vpnTargetList = new ArrayList<>(); - boolean isLockAcquired = false; InstanceIdentifier vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class) .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build(); + Optional optionalVpn; try { - Optional optionalVpn = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - vpnIdentifier); - LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName); - if (optionalVpn.isPresent()) { - builder = new VpnInstanceBuilder(optionalVpn.get()); - LOG.debug("updating existing vpninstance node"); - } else { - builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName) - .setType(type).setL3vni(l3vni); - } - if (irt != null && !irt.isEmpty()) { - if (ert != null && !ert.isEmpty()) { - List commonRT = new ArrayList<>(irt); - commonRT.retainAll(ert); - - for (String common : commonRT) { - irt.remove(common); - ert.remove(common); - VpnTarget vpnTarget = - new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common) - .setVrfRTType(VpnTarget.VrfRTType.Both).build(); - vpnTargetList.add(vpnTarget); - } - } - for (String importRT : irt) { - VpnTarget vpnTarget = - new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT) - .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build(); - vpnTargetList.add(vpnTarget); - } - } + optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, + vpnIdentifier); + } catch (ExecutionException | InterruptedException e) { + LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert); + return; + } + LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName); + if (optionalVpn.isPresent()) { + builder = new VpnInstanceBuilder(optionalVpn.get()); + LOG.debug("updating existing vpninstance node"); + } else { + builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName) + .setL2vpn(isL2Vpn).setL3vni(l3vni).setBgpvpnType(VpnInstance.BgpvpnType.InternalVPN); + } + if (irt != null && !irt.isEmpty()) { if (ert != null && !ert.isEmpty()) { - for (String exportRT : ert) { + List commonRT = new ArrayList<>(irt); + commonRT.retainAll(ert); + + for (String common : commonRT) { + irt.remove(common); + ert.remove(common); VpnTarget vpnTarget = - new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT) - .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build(); + new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common) + .setVrfRTType(VpnTarget.VrfRTType.Both).build(); vpnTargetList.add(vpnTarget); } } + for (String importRT : irt) { + VpnTarget vpnTarget = + new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT) + .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build(); + vpnTargetList.add(vpnTarget); + } + } - VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build(); + if (ert != null && !ert.isEmpty()) { + for (String exportRT : ert) { + VpnTarget vpnTarget = + new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT) + .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build(); + vpnTargetList.add(vpnTarget); + } + } - Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets); - Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets); + VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build(); + if (rd != null && !rd.isEmpty()) { + builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets).setBgpvpnType(VpnInstance.BgpvpnType.BGPVPN); + } - if (rd != null && !rd.isEmpty()) { - ipv4vpnBuilder.setRouteDistinguisher(rd); - ipv6vpnBuilder.setRouteDistinguisher(rd); + builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice)); + VpnInstance newVpn = builder.build(); + try (AcquireResult lock = tryVpnLock(vpnId)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(vpnId); } - if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) { - builder.setIpv4Family(ipv4vpnBuilder.build()); - } - if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) { - builder.setIpv6Family(ipv6vpnBuilder.build()); - } - if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) { - builder.setIpv4Family(ipv4vpnBuilder.build()); - } - VpnInstance newVpn = builder.build(); - isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS); LOG.debug("Creating/Updating vpn-instance for {} ", vpnName); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, + try { + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn); - } catch (ReadFailedException | TransactionCommitFailedException e) { - LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert); - } finally { - if (isLockAcquired) { - vpnLock.unlock(vpnId); + } catch (TransactionCommitFailedException e) { + LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert); } } } private void deleteVpnMapsNode(Uuid vpnId) { - boolean isLockAcquired = false; InstanceIdentifier vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) .child(VpnMap.class, new VpnMapKey(vpnId)) .build(); LOG.debug("removing vpnMaps node: {} ", vpnId.getValue()); - try { - isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS); - SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier); - } catch (TransactionCommitFailedException e) { - LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue()); - } finally { - if (isLockAcquired) { - vpnLock.unlock(vpnId); + try (AcquireResult lock = tryVpnLock(vpnId)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(vpnId); + } + + try { + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, + vpnMapIdentifier); + } catch (TransactionCommitFailedException e) { + LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue()); } } } - private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List networks) { + protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId, + @Nullable List networks) { VpnMapBuilder builder; - boolean isLockAcquired = false; InstanceIdentifier vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) .child(VpnMap.class, new VpnMapKey(vpnId)) .build(); @@ -664,39 +687,44 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } if (router != null) { RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build(); - List rtrIds = builder.getRouterIds(); + List rtrIds = builder.getRouterIds() != null + ? new ArrayList<>(builder.getRouterIds().values()) : null; if (rtrIds == null) { rtrIds = Collections.singletonList(vpnRouterId); } else { - rtrIds.add(vpnRouterId); + //Add vpnRouterId to rtrIds list only if update routerId is not existing in the VpnMap already + for (RouterIds routerId: rtrIds) { + if (!Objects.equals(routerId, vpnRouterId)) { + rtrIds.add(vpnRouterId); + } + } } builder.setRouterIds(rtrIds); } if (networks != null) { - List nwList = builder.getNetworkIds(); - if (nwList == null) { - nwList = new ArrayList<>(); - } + List nwList = builder.getNetworkIds() != null + ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>(); nwList.addAll(networks); builder.setNetworkIds(nwList); } - isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS); - LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue()); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, - builder.build()); - LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue()); - } catch (ReadFailedException | TransactionCommitFailedException e) { - LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue()); - } finally { - if (isLockAcquired) { - vpnLock.unlock(vpnId); + try (AcquireResult lock = tryVpnLock(vpnId)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(vpnId); + } + + LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue()); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, + builder.build()); + LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue()); } + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { + LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue()); } } - private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List networkIds) { - boolean isLockAcquired = false; + private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List networkIds) { InstanceIdentifier vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) .child(VpnMap.class, new VpnMapKey(vpnId)) .build(); @@ -705,14 +733,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even optionalVpnMap = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier); - } catch (ReadFailedException e) { + } catch (ExecutionException | InterruptedException e) { LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e); return; } if (optionalVpnMap.isPresent()) { VpnMap vpnMap = optionalVpnMap.get(); VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap); - List rtrIds = vpnMap.getRouterIds(); + List rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds().values()); if (rtrIds == null) { rtrIds = new ArrayList<>(); } @@ -720,17 +748,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) { rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build()); vpnMapBuilder.setRouterIds(rtrIds); - try { - // remove entire node in case of internal VPN - isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS); + + try (AcquireResult lock = tryVpnLock(vpnId)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(vpnId); + } + LOG.debug("removing vpnMaps node: {} ", vpnId); - SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, - vpnMapIdentifier); - } catch (TransactionCommitFailedException e) { - LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue()); - } finally { - if (isLockAcquired) { - vpnLock.unlock(vpnId); + try { + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, + vpnMapIdentifier); + } catch (TransactionCommitFailedException e) { + LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue()); } } return; @@ -741,7 +771,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } if (networkIds != null) { - List vpnNw = vpnMap.getNetworkIds(); + List vpnNw = vpnMap.getNetworkIds() != null + ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>(); vpnNw.removeAll(networkIds); if (vpnNw.isEmpty()) { LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue()); @@ -751,16 +782,18 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - try { - isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS); + try (AcquireResult lock = tryVpnLock(vpnId)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(vpnId); + } + LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue()); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, - vpnMapBuilder.build()); - } catch (TransactionCommitFailedException e) { - LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue()); - } finally { - if (isLockAcquired) { - vpnLock.unlock(vpnId); + try { + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, + vpnMapIdentifier, vpnMapBuilder.build()); + } catch (TransactionCommitFailedException e) { + LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue()); } } } else { @@ -770,40 +803,43 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } private void deleteVpnInstance(Uuid vpnId) { - boolean isLockAcquired = false; InstanceIdentifier vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class) .child(VpnInstance.class, new VpnInstanceKey(vpnId.getValue())) .build(); - try { - isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS); + + try (AcquireResult lock = tryVpnLock(vpnId)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(vpnId); + } + LOG.debug("Deleting vpnInstance {}", vpnId.getValue()); - SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier); - } catch (TransactionCommitFailedException e) { - LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue()); - } finally { - if (isLockAcquired) { - vpnLock.unlock(vpnId); + try { + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier); + } catch (TransactionCommitFailedException e) { + LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue()); } } } protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface, - TypedWriteTransaction wrtConfigTxn, - Subnetmap sn, VpnInterface vpnIface) { + TypedWriteTransaction wrtConfigTxn, + @Nullable VpnInterface vpnIface) { List adjList = new ArrayList<>(); if (vpnIface != null) { - adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency(); + adjList = new ArrayList(vpnIface.augmentation(Adjacencies.class).getAdjacency().values()); } String infName = port.getUuid().getValue(); LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName); - for (FixedIps ip : port.getFixedIps()) { + for (FixedIps ip : port.nonnullFixedIps().values()) { String ipValue = ip.getIpAddress().stringValue(); String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128"; - if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) { + Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId()); + if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, + snTemp.getSubnetIp(), false)) { continue; } - Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId()); Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null; if (vpnId != null) { neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, @@ -824,7 +860,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (routerId != null) { Router rtr = neutronvpnUtils.getNeutronRouter(routerId); if (rtr != null && rtr.getRoutes() != null) { - List routeList = rtr.getRoutes(); + List routeList = new ArrayList(rtr.getRoutes().values()); // create extraroute Adjacence for each ipValue, // because router can have IPv4 and IPv6 subnet ports, or can have // more that one IPv4 subnet port or more than one IPv6 subnet port @@ -835,23 +871,35 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } } - return new AdjacenciesBuilder().setAdjacency(adjList).build(); + return new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(adjList)).build(); + } + + private Map getAdjacencyMap(List adjList) { + //convert to set to remove duplicates. + Set adjset = adjList.stream().collect(Collectors.toSet()); + Map adjacencyMap = new HashMap<>(); + for (Adjacency adj : adjset) { + adjacencyMap.put(new AdjacencyKey(adj.getIpAddress()), adj); + } + return adjacencyMap; } protected void createVpnInterface(Collection vpnIds, Port port, - TypedWriteTransaction wrtConfigTxn) { + @Nullable TypedWriteTransaction wrtConfigTxn) { boolean isRouterInterface = false; if (port.getDeviceOwner() != null) { isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner()); } - Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null); String infName = port.getUuid().getValue(); + // Handling cluster reboot scenario where VpnInterface already exists in datastore. + VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName); + Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface); LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface); writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn); } protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId, - Port port, Subnetmap sn, TypedWriteTransaction wrtConfigTxn) { + Port port, Subnetmap sn, TypedWriteTransaction wrtConfigTxn) { String infName = port.getUuid().getValue(); InstanceIdentifier vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName); Optional optionalVpnInterface = null; @@ -861,7 +909,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even optionalVpnInterface = SingleTransactionDataBroker .syncReadOptional(dataBroker, LogicalDatastoreType .CONFIGURATION, vpnIfIdentifier); - } catch (ReadFailedException e) { + } catch (ExecutionException | InterruptedException e) { LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e); return; } @@ -870,10 +918,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(), sn != null ? sn.getSubnetIp() : "null"); - List vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency(); + Map keyAdjacencyMap + = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency(); List updatedAdjsList = new ArrayList<>(); boolean isIpFromAnotherSubnet = false; - for (Adjacency adj : vpnAdjsList) { + for (Adjacency adj : keyAdjacencyMap.values()) { String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress()); if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) { if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) { @@ -894,12 +943,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even String.valueOf(adjString), wrtConfigTxn); } } else { - if (port.getDeviceOwner() - .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) { + if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner()) + && sn.getRouterId() != null) { Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId()); if (rtr != null && rtr.getRoutes() != null) { List extraRoutesToRemove = new ArrayList<>(); - for (Routes rt: rtr.getRoutes()) { + for (Routes rt: rtr.getRoutes().values()) { if (rt.getNexthop().toString().equals(adjString)) { extraRoutesToRemove.add(rt); } @@ -914,13 +963,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } } - Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build(); + Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(updatedAdjsList)).build(); if (vpnId != null) { updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn); } - if (internetVpnId != null) { - updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn); - } if (!isIpFromAnotherSubnet) { // no more subnetworks for neutron port if (sn != null && sn.getRouterId() != null) { @@ -935,9 +981,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") protected void deleteVpnInterface(String infName, @Nullable String vpnId, - TypedWriteTransaction wrtConfigTxn) { + @Nullable TypedWriteTransaction wrtConfigTxn) { if (wrtConfigTxn == null) { - ListenableFutures.addErrorLogging( + LoggingFutures.addErrorLogging( txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> deleteVpnInterface(infName, vpnId, tx)), LOG, "Error deleting VPN interface {} {}", infName, vpnId); @@ -951,7 +997,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even optionalVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier); - } catch (ReadFailedException ex) { + } catch (ExecutionException | InterruptedException ex) { LOG.error("Error during deletion of vpninterface {}", infName, ex); return; } @@ -961,17 +1007,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } if (vpnId != null) { VpnInterface vpnInterface = optionalVpnInterface.get(); - List vpnList = vpnInterface.getVpnInstanceNames(); - if (vpnList != null - && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) { - VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList); - if (!vpnList.isEmpty()) { + Map keyVpnInstanceNamesMap = vpnInterface.getVpnInstanceNames(); + if (keyVpnInstanceNamesMap != null + && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, + new ArrayList(keyVpnInstanceNamesMap.values()))) { + VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, + new ArrayList(keyVpnInstanceNamesMap.values())); + if (!keyVpnInstanceNamesMap.isEmpty()) { LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName " + "List not empty", infName); return; } VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get()) - .setVpnInstanceNames(vpnList); + .setVpnInstanceNames(keyVpnInstanceNamesMap); wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder .build()); } @@ -980,8 +1028,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even wrtConfigTxn.delete(vpnIfIdentifier); } - protected void removeVpnFromVpnInterface(Uuid vpnId, Port port, - TypedWriteTransaction writeConfigTxn, + protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port, + TypedWriteTransaction writeConfigTxn, Subnetmap sm) { if (vpnId == null || port == null) { return; @@ -993,17 +1041,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even .syncReadOptional(dataBroker, LogicalDatastoreType .CONFIGURATION, vpnIfIdentifier); if (optionalVpnInterface.isPresent()) { - List listVpn = optionalVpnInterface.get().getVpnInstanceNames(); - if (listVpn != null - && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) { - VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn); + Map keyVpnInstanceNamesMap + = optionalVpnInterface.get().getVpnInstanceNames(); + if (keyVpnInstanceNamesMap != null + && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), + new ArrayList(keyVpnInstanceNamesMap.values()))) { + VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), + new ArrayList(keyVpnInstanceNamesMap.values())); } VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get()) - .setVpnInstanceNames(listVpn); + .setVpnInstanceNames(keyVpnInstanceNamesMap); Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class); LOG.debug("Updating vpn interface {}", infName); - List adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>(); - Iterator adjacencyIter = adjacencyList.iterator(); + Map keyAdjacencyMap = adjs != null ? adjs.getAdjacency() : new HashMap<>(); + Iterator adjacencyIter = keyAdjacencyMap.values().iterator(); while (adjacencyIter.hasNext()) { Adjacency adjacency = adjacencyIter.next(); if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) { @@ -1018,7 +1069,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (optionalVpnVipToPort.isPresent()) { LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}", infName, vpnId); - if (listVpn == null || listVpn.isEmpty()) { + if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) { adjacencyIter.remove(); } neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery); @@ -1026,13 +1077,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even mipToQuery, infName, vpnId.getValue()); } } - List ips = port.getFixedIps(); - for (FixedIps ip : ips) { + for (FixedIps ip : port.nonnullFixedIps().values()) { String ipValue = ip.getIpAddress().stringValue(); + //skip IPv4 address + if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) { + continue; + } neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, writeConfigTxn); } - if (listVpn == null || listVpn.isEmpty()) { + if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) { if (sm != null && sm.getRouterId() != null) { removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue()); } @@ -1043,103 +1097,120 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } else { LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName); } - } catch (ReadFailedException ex) { + } catch (ExecutionException | InterruptedException ex) { LOG.error("Update of vpninterface {} failed", infName, ex); } } - protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated, + protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated, boolean isSubnetIp, - TypedWriteTransaction writeConfigTxn) { + TypedWriteTransaction writeConfigTxn, + boolean isInternetVpn) { if (vpnId == null || port == null) { return; } - boolean isLockAcquired = false; String infName = port.getUuid().getValue(); InstanceIdentifier vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName); - try { - isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS); - Optional optionalVpnInterface = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, + try (AcquireResult lock = tryInterfaceLock(infName)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(infName); + } + + try { + Optional optionalVpnInterface = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier); - if (optionalVpnInterface.isPresent()) { - VpnInstanceNames vpnInstance = VpnHelper - .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets); - List listVpn = new ArrayList<>(optionalVpnInterface - .get().getVpnInstanceNames()); - if (oldVpnId != null - && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) { - VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn); - } - if (vpnId.getValue() != null - && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) { - listVpn.add(vpnInstance); - } - VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get()) - .setVpnInstanceNames(listVpn); - LOG.debug("Updating vpn interface {}", infName); - if (!isBeingAssociated) { - Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class); - List adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>(); - Iterator adjacencyIter = adjacencyList.iterator(); - while (adjacencyIter.hasNext()) { - Adjacency adjacency = adjacencyIter.next(); - String mipToQuery = adjacency.getIpAddress().split("/")[0]; - InstanceIdentifier id = - NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery); - Optional optionalVpnVipToPort = - SingleTransactionDataBroker.syncReadOptional(dataBroker, + if (optionalVpnInterface.isPresent()) { + VpnInstanceNames vpnInstance = VpnHelper + .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets); + List listVpn = new ArrayList<>(optionalVpnInterface.get() + .getVpnInstanceNames().values()); + if (oldVpnId != null + && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) { + VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn); + } + if (vpnId.getValue() != null + && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) { + listVpn.add(vpnInstance); + } + VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get()) + .setVpnInstanceNames(listVpn); + LOG.debug("Updating vpn interface {}", infName); + if (!isBeingAssociated) { + Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class); + Map keyAdjacencyMap = adjs != null ? adjs.getAdjacency() + : new HashMap(); + Iterator adjacencyIter = keyAdjacencyMap.values().iterator(); + while (adjacencyIter.hasNext()) { + Adjacency adjacency = adjacencyIter.next(); + String mipToQuery = adjacency.getIpAddress().split("/")[0]; + InstanceIdentifier id = + NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery); + Optional optionalVpnVipToPort = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, id); - if (optionalVpnVipToPort.isPresent()) { - LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} " - + "from VPN {}", infName, vpnId, oldVpnId); - adjacencyIter.remove(); - neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery); - LOG.trace( - "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData", + if (optionalVpnVipToPort.isPresent() + && optionalVpnVipToPort.get().getPortName().equals(infName)) { + LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} " + + "from VPN {}", infName, vpnId, oldVpnId); + adjacencyIter.remove(); + neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery); + LOG.trace( + "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort", mipToQuery, infName, vpnId.getValue()); + } + InstanceIdentifier build = + NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery); + Optional persistedIp = SingleTransactionDataBroker.syncReadOptional( + dataBroker, LogicalDatastoreType.OPERATIONAL, build); + if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) { + neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null); + LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort", + mipToQuery, infName, vpnId.getValue()); + } } + Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(keyAdjacencyMap).build(); + vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies); } - Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build(); - vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies); - } - List ips = port.getFixedIps(); - for (FixedIps ip : ips) { - String ipValue = ip.getIpAddress().stringValue(); - if (oldVpnId != null) { - neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), + for (FixedIps ip : port.nonnullFixedIps().values()) { + String ipValue = ip.getIpAddress().stringValue(); + if (oldVpnId != null) { + neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), ipValue, writeConfigTxn); - } - neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port + } + if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6 + && isInternetVpn == true) { + continue; + } + + neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port .getMacAddress().getValue(), isSubnetIp, writeConfigTxn); + } + writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build()); + } else { + LOG.error("VPN Interface {} not found", infName); } - writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build()); - } else { - LOG.error("VPN Interface {} not found", infName); - } - } catch (ReadFailedException ex) { - LOG.error("Updation of vpninterface {} failed", infName, ex); - } finally { - if (isLockAcquired) { - interfaceLock.unlock(infName); + } catch (ExecutionException | InterruptedException ex) { + LOG.error("Updation of vpninterface {} failed", infName, ex); } } } - public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List rd, List irt, - List ert, Uuid router, List networks) { + public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List rdList, List irtList, + List ertList, Uuid routerId, List networksList) { - IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router); + IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId); // Update VPN Instance node - updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices); + updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices); // Update local vpn-subnet DS - updateVpnMaps(vpn, name, router, tenant, networks); + updateVpnMaps(vpnId, name, routerId, tenantId, networksList); - if (router != null) { - Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true); + if (routerId != null) { + Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true); if (existingVpn != null) { // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn // if before reboot, router was already associated to VPN, should not proceed associating router to @@ -1148,10 +1219,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to // RouterInterfacesMap via #createVPNInterface call. LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated " - + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue()); + + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue()); return; } - associateRouterToInternalVpn(vpn, router); + associateRouterToInternalVpn(vpnId, routerId); } } @@ -1167,13 +1238,13 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * @param ertList A list of Export Route Targets * @param routerIdsList ist of neutron router Id to associate with created VPN * @param networkList UUID of the neutron network the VPN may be associated to - * @param type Type of the VPN Instance + * @param isL2Vpn True if VPN Instance is of type L2, false if L3 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay * @throws Exception if association of L3VPN failed */ public void createVpn(Uuid vpnId, String name, Uuid tenantId, List rdList, List irtList, - List ertList, @Nullable List routerIdsList, List networkList, - VpnInstance.Type type, long l3vni) throws Exception { + List ertList, @Nullable List routerIdsList, @Nullable List networkList, + boolean isL2Vpn, long l3vni) throws Exception { IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED; @@ -1183,7 +1254,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even ipVersChoices = ipVersChoices.addVersion(vers); } } - updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices); + updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices); // Please note that router and networks will be filled into VPNMaps // by subsequent calls here to associateRouterToVpn and @@ -1202,7 +1273,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even List failStrings = associateNetworksToVpn(vpnId, networkList); if (!failStrings.isEmpty()) { LOG.error("VPN {} association to networks failed for networks: {}. ", - vpnId.getValue(), failStrings.toString()); + vpnId.getValue(), failStrings); throw new Exception(failStrings.toString()); } } @@ -1243,10 +1314,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even warningcount++; continue; } - VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3; long l3vni = 0; if (vpn.getL3vni() != null) { - l3vni = vpn.getL3vni(); + l3vni = vpn.getL3vni().toJava(); } List existingRDs = neutronvpnUtils.getExistingRDs(); @@ -1271,10 +1341,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even continue; } if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) { - List - routerIdsList = vpn.getRouterIds(); + Map keyRouterIdsMap = vpn.getRouterIds(); for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds - routerId : routerIdsList) { + routerId : keyRouterIdsMap.values()) { if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) { errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers" @@ -1320,19 +1391,27 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even List rtrIdsList = new ArrayList<>(); if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) { for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds - rtrId : vpn.getRouterIds()) { + rtrId : vpn.getRouterIds().values()) { rtrIdsList.add(rtrId.getRouterId()); } } try { LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, " + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(), - vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(), - vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds()); - createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(), - vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(), - vpnInstanceType, l3vni); + vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(), + vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds()); + + List rdList = vpn.getRouteDistinguisher() != null + ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>(); + List importRdList = vpn.getImportRT() != null + ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>(); + List exportRdList = vpn.getExportRT() != null + ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>(); + + createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList, + importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni); } catch (Exception ex) { + LOG.error("VPN Creation exception :", ex); errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex), ex.getMessage())); @@ -1380,13 +1459,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnsIdentifier); if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) { - for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) { + for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance().values()) { // eliminating implicitly created (router and VLAN provider external network specific) VPNs // from getL3VPN output - if (vpn.getIpv4Family().getRouteDistinguisher() != null) { - vpns.add(vpn); - } - if (vpn.getIpv6Family().getRouteDistinguisher() != null) { + if (vpn.getRouteDistinguisher() != null) { vpns.add(vpn); } } @@ -1406,8 +1482,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even vpnIdentifier); // eliminating implicitly created (router or VLAN provider external network specific) VPN from // getL3VPN output - if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null - || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) { + if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) { vpns.add(optionalVpn.get()); } else { result.set( @@ -1421,24 +1496,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even // create VpnMaps id L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder(); List rd = Collections.EMPTY_LIST; - if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) { - rd = vpnInstance.getIpv4Family().getRouteDistinguisher(); - } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) { - rd = vpnInstance.getIpv6Family().getRouteDistinguisher(); + if (vpnInstance.getRouteDistinguisher() != null) { + rd = vpnInstance.getRouteDistinguisher(); } List ertList = new ArrayList<>(); List irtList = new ArrayList<>(); - if (vpnInstance.getIpv4Family().getVpnTargets() != null - || vpnInstance.getIpv6Family().getVpnTargets() != null) { - List vpnTargetList = Collections.EMPTY_LIST; - if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) { - vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget(); - } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) { - vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget(); + if (vpnInstance.getVpnTargets() != null) { + Map keyVpnTargetMap = Collections.EMPTY_MAP; + if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) { + keyVpnTargetMap = vpnInstance.getVpnTargets().getVpnTarget(); } - if (!vpnTargetList.isEmpty()) { - for (VpnTarget vpnTarget : vpnTargetList) { + if (!keyVpnTargetMap.isEmpty()) { + for (VpnTarget vpnTarget : keyVpnTargetMap.values()) { if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) { ertList.add(vpnTarget.getVrfRTValue()); } @@ -1467,7 +1537,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even VpnMap vpnMap = optionalVpnMap.get(); List rtrIds = new ArrayList<>(); if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) { - for (RouterIds rtrId : vpnMap.getRouterIds()) { + for (RouterIds rtrId : vpnMap.getRouterIds().values()) { rtrIds.add(rtrId.getRouterId()); } } @@ -1482,7 +1552,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even opBuilder.setL3vpnInstances(l3vpnList); result.set(RpcResultBuilder.success().withResult(opBuilder.build()).build()); - } catch (ReadFailedException ex) { + } catch (ExecutionException | InterruptedException ex) { result.set(RpcResultBuilder.failed().withError(ErrorType.APPLICATION, formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build()); } @@ -1501,10 +1571,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even int failurecount = 0; int warningcount = 0; - List vpns = input.getId(); + List vpns = input.getId() != null ? input.getId() : Collections.emptyList(); for (Uuid vpn : vpns) { - RpcError error; - String msg; try { LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue()); InstanceIdentifier vpnIdentifier = @@ -1520,7 +1588,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue()))); warningcount++; } - } catch (ReadFailedException ex) { + } catch (ExecutionException | InterruptedException ex) { errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()), ex.getMessage())); @@ -1575,7 +1643,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even return; } final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue()); - LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString()); + LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance); if (isVpnOfTypeL2(vpnInstance)) { neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(), NeutronEvpnUtils.Operation.ADD); @@ -1605,112 +1673,121 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } final Boolean isRouterInterface = port.getDeviceOwner() .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false; - jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList( - txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> { - Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn, + jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> { + ListenableFuture future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + wrtConfigTxn -> { + Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface); - if (vpnIface == null) { - LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName); - Set listVpn = new HashSet<>(); - if (vpnId != null) { - listVpn.add(vpnId); - } - if (internetId != null) { - listVpn.add(internetId); - } - writeVpnInterfaceToDs(listVpn, - vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn); - if (sn.getRouterId() != null) { - addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue()); - } - } else { - LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj); - if (vpnId != null) { - updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn); - } - if (internetId != null) { - updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn); + if (vpnIface == null) { + LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName); + Set listVpn = new HashSet<>(); + if (vpnId != null) { + listVpn.add(vpnId); + } + if (internetId != null) { + listVpn.add(internetId); + } + writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(), + isRouterInterface, wrtConfigTxn); + if (sn.getRouterId() != null) { + addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue()); + } + } else { + LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj); + if (vpnId != null) { + updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn); + } + if (internetId != null) { + updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn); + } } - } - })) - ); + }); + LoggingFutures.addErrorLogging(future, LOG, + "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}" + + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue()); + return Collections.singletonList(future); + }); } } } - protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) { + protected void removeSubnetFromVpn(final Uuid vpnId, Subnetmap subnetmap, @Nullable Uuid internetVpnId) { Preconditions.checkArgument(vpnId != null || internetVpnId != null, "removeSubnetFromVpn: at least one VPN must be not null"); - LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(), + Uuid subnetId = subnetmap.getId(); + LOG.debug("Removing subnet {} from vpn {}/{}", subnetId.getValue(), vpnId, internetVpnId); - Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet); - if (sn == null) { - LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue()); - return; - } + LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnetId.getValue()); VpnMap vpnMap = null; VpnInstance vpnInstance = null; if (vpnId != null) { vpnMap = neutronvpnUtils.getVpnMap(vpnId); if (vpnMap == null) { LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN", - vpnId.getValue(), subnet.getValue()); + vpnId.getValue(), subnetId.getValue()); return; } vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue()); } if (internetVpnId == null) { - internetVpnId = sn.getInternetVpnId(); + internetVpnId = subnetmap.getInternetVpnId(); } if (internetVpnId != null) { vpnMap = neutronvpnUtils.getVpnMap(internetVpnId); if (vpnMap == null) { LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}" + " from Internet VPN", - internetVpnId.getValue(), subnet.getValue()); + internetVpnId.getValue(), subnetId.getValue()); return; } } if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) { - neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(), + neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(), NeutronEvpnUtils.Operation.DELETE); } boolean subnetVpnAssociation = false; - if (vpnId != null && sn.getVpnId() != null - && sn.getVpnId().getValue().equals(vpnId.getValue())) { + if (vpnId != null && subnetmap.getVpnId() != null + && subnetmap.getVpnId().getValue().equals(vpnId.getValue())) { subnetVpnAssociation = true; - } else if (internetVpnId != null && sn.getInternetVpnId() != null - && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) { + } else if (internetVpnId != null && subnetmap.getInternetVpnId() != null + && subnetmap.getInternetVpnId().getValue().matches(internetVpnId.getValue())) { subnetVpnAssociation = true; } if (subnetVpnAssociation == false) { LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}", - vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId()); + vpnId, internetVpnId, subnetmap.getVpnId(), subnetmap.getInternetVpnId()); return; } // Check if there are ports on this subnet; remove corresponding vpn-interfaces - List portList = sn.getPortList(); + List portList = subnetmap.getPortList(); final Uuid internetId = internetVpnId; if (portList != null) { for (final Uuid portId : portList) { - LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue()); + LOG.debug("withdrawing subnet IP {} from vpn-interface {}", subnetmap.getSubnetIp(), portId.getValue()); final Port port = neutronvpnUtils.getNeutronPort(portId); - jobCoordinator.enqueueJob("PORT-" + portId.getValue(), - () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit( - CONFIGURATION, tx -> { + jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> { + List> futures = new ArrayList<>(); + ListenableFuture future = txRunner.callWithNewWriteOnlyTransactionAndSubmit( + CONFIGURATION, tx -> { if (port != null) { - withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx); + withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx); } else { - LOG.warn( - "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since " - + "port is absent in Neutron config DS", portId.getValue(), - subnet.getValue()); + LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since" + + " port is absent in Neutron config DS", portId.getValue(), + subnetId.getValue()); } - }))); + }); + LoggingFutures.addErrorLogging(future, LOG, + "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}" + + " belonging to subnet {} and vpnId {}", + portId.getValue(), subnetId.getValue(), vpnId.getValue()); + futures.add(future); + return futures; + }); } } //update subnet-vpn association - removeFromSubnetNode(subnet, null, null, vpnId, null); + removeFromSubnetNode(subnetId, null, null, vpnId, null); } protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) { @@ -1733,10 +1810,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> { if (isBeingAssociated) { updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort( - sm.getRouterInterfacePortId()), true, true, wrtConfigTxn); + sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true); } else { - removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), - wrtConfigTxn, sm); + removeInternetVpnFromVpnInterface(vpn, + neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm); } } ))); @@ -1753,15 +1830,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even tx -> { if (isBeingAssociated) { updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port), - true, false, tx); + true, false, tx, true); } else { - removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm); + removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm); } }))); } } } + @Nullable private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) { LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(), oldVpnId.getValue(), newVpnId.getValue()); @@ -1775,17 +1853,30 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue()); return sn; } - + /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been + * associated with internet BGP-VPN. + */ + if (vpnExtUuid != null) { + /* Update V6 Internet default route match with new VPN metadata. + * isBeingAssociated = true means oldVpnId is same as routerId + * isBeingAssociated = false means newVpnId is same as routerId + */ + if (isBeingAssociated) { + neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true); + } else { + neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true); + } + } //Update Router Interface first synchronously. //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again ! - ListenableFuture future = + ListenableFuture future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> updateVpnInterface(newVpnId, oldVpnId, neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()), - isBeingAssociated, true, tx)); - Futures.addCallback(future, new FutureCallback() { + isBeingAssociated, true, tx, false)); + Futures.addCallback(future, new FutureCallback() { @Override - public void onSuccess(Void result) { + public void onSuccess(Object result) { // Check for ports on this subnet and update association of // corresponding vpn-interfaces to external vpn List portList = sn.getPortList(); @@ -1797,7 +1888,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> updateVpnInterface(newVpnId, oldVpnId, neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false, - tx)))); + tx, false)))); } } } @@ -1820,59 +1911,59 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) { - synchronized (routerId.getValue().intern()) { - InstanceIdentifier routerInterfacesId = getRouterInterfacesId(routerId); - try { - Optional optRouterInterfaces = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerInterfacesId); - Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName)) + final InstanceIdentifier routerInterfacesId = getRouterInterfacesId(routerId); + final ReentrantLock lock = lockForUuid(routerId); + lock.lock(); + try { + Optional optRouterInterfaces = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, + routerInterfacesId); + Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName)) .setInterfaceId(interfaceName).build(); - if (optRouterInterfaces.isPresent()) { - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), - routerInterface); - } else { - // TODO Shouldn't we be doing something with builder and interfaces? -// RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId); -// List interfaces = new ArrayList<>(); -// interfaces.add(routerInterface); - - SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), - routerInterface); - } - } catch (ReadFailedException | TransactionCommitFailedException e) { - LOG.error("Error reading router interfaces for {}", routerInterfacesId, e); + if (optRouterInterfaces.isPresent()) { + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, + routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface); + } else { + RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId); + List interfaces = new ArrayList<>(); + interfaces.add(routerInterface); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, + routerInterfacesId, builder.setInterfaces(interfaces).build()); } + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { + LOG.error("Error reading router interfaces for {}", routerInterfacesId, e); + } finally { + lock.unlock(); } } protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) { - synchronized (routerId.getValue().intern()) { - InstanceIdentifier routerInterfacesId = getRouterInterfacesId(routerId); - try { - Optional optRouterInterfaces = - SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerInterfacesId); - Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName)) + final InstanceIdentifier routerInterfacesId = getRouterInterfacesId(routerId); + final ReentrantLock lock = lockForUuid(routerId); + lock.lock(); + try { + Optional optRouterInterfaces = + SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, + routerInterfacesId); + Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName)) .setInterfaceId(interfaceName).build(); - if (optRouterInterfaces.isPresent()) { - RouterInterfaces routerInterfaces = optRouterInterfaces.get(); - List interfaces = routerInterfaces.getInterfaces(); - if (interfaces != null && interfaces.remove(routerInterface)) { - if (interfaces.isEmpty()) { - SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerInterfacesId); - } else { - SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName))); - } + if (optRouterInterfaces.isPresent()) { + RouterInterfaces routerInterfaces = optRouterInterfaces.get(); + List interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces().values()); + if (interfaces != null && interfaces.remove(routerInterface)) { + if (interfaces.isEmpty()) { + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, + routerInterfacesId); + } else { + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, + routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName))); } } - } catch (ReadFailedException | TransactionCommitFailedException e) { - LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e); } + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { + LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e); + } finally { + lock.unlock(); } } @@ -1940,7 +2031,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even .setVpnInstanceName(vpnName.getValue()) .build(); - ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread( + LoggingFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread( vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes"); } else { // Any other case is a fault. @@ -1955,7 +2046,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * Returns true if the specified nexthop is the other endpoint in an * InterVpnLink, regarding one of the VPN's point of view. */ - private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) { + private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, + InterVpnLink interVpnLink) { return interVpnLink != null && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid) @@ -1964,7 +2056,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)); } - @Nonnull + @NonNull protected List getAdjacencyforExtraRoute(List routeList, String fixedIp) { List adjList = new ArrayList<>(); Map> adjMap = new HashMap<>(); @@ -2030,18 +2122,21 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination) .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination)) .setAdjacencyType(AdjacencyType.ExtraRoute).build(); - isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, + + try (AcquireResult lock = tryInterfaceLock(infName)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(infName); + } + + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, erAdj); + } } catch (TransactionCommitFailedException e) { LOG.error("exception in adding extra route with destination: {}, next hop: {}", destination, nextHop, e); - } catch (ReadFailedException e) { + } catch (ExecutionException | InterruptedException e) { LOG.error("Exception on reading data-store ", e); - } finally { - if (isLockAcquired) { - interfaceLock.unlock(infName); - } } } else { LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} " @@ -2083,7 +2178,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even String nextHop = route.getNexthop().stringValue(); List nextHopList = new ArrayList<>(); nextHopList.add(nextHop); - int nbNextHops = 0; + int nbNextHops = 1; for (Routes routeTmp : routeList) { String routeDest = routeTmp.getDestination().stringValue(); if (!destination.equals(routeDest)) { @@ -2097,21 +2192,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even nextHopList.add(routeTmp.getNexthop().stringValue()); } final List rdList = new ArrayList<>(); - if (vpnInstance.getIpv4Family() != null - && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) { - vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> { + if (vpnInstance != null + && vpnInstance.getRouteDistinguisher() != null) { + vpnInstance.getRouteDistinguisher().forEach(rd -> { if (rd != null) { rdList.add(rd); } }); } - if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) { - vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> { - if (rd != null && !rdList.contains(rd)) { - rdList.add(rd); - } - }); - } // 1. VPN Instance Name String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe"; @@ -2152,7 +2240,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even protected void removeAdjacencyforExtraRoute(Uuid vpnId, List routeList) { for (Routes route : routeList) { if (route != null && route.getNexthop() != null && route.getDestination() != null) { - boolean isLockAcquired = false; String nextHop = route.getNexthop().stringValue(); String destination = route.getDestination().stringValue(); String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(), @@ -2192,34 +2279,37 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS); - if (updateNextHops) { - // An update must be done, not including the current next hop - InstanceIdentifier vpnIfIdentifier = InstanceIdentifier.builder( + try (AcquireResult lock = tryInterfaceLock(infName)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(infName); + } + + if (updateNextHops) { + // An update must be done, not including the current next hop + InstanceIdentifier vpnIfIdentifier = InstanceIdentifier.builder( VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build(); - Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination) - .setNextHopIpList(nextHopList) - .withKey(new AdjacencyKey(destination)) - .build(); - Adjacencies erAdjs = - new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build(); - VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName)) - .addAugmentation(Adjacencies.class, erAdjs).build(); - SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, + Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination) + .setNextHopIpList(nextHopList) + .withKey(new AdjacencyKey(destination)) + .build(); + List newAdjList = Collections.singletonList(newAdj); + Adjacencies erAdjs = + new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(newAdjList)).build(); + VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName)) + .addAugmentation(Adjacencies.class, erAdjs).build(); + SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf); - } else { - // Remove the whole route - SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, + } else { + // Remove the whole route + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier); - LOG.trace("extra route {} deleted successfully", route); + LOG.trace("extra route {} deleted successfully", route); + } } - } catch (TransactionCommitFailedException | ReadFailedException e) { + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) { LOG.error("exception in deleting extra route with destination {} for interface {}", destination, infName, e); - } finally { - if (isLockAcquired) { - interfaceLock.unlock(infName); - } } } else { LOG.error("Incorrect input received for extra route: {}", route); @@ -2230,18 +2320,22 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even public void removeVpn(Uuid vpnId) { // read VPNMaps VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId); - List routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null; - // dissociate router - if (routerIdsList != null && !routerIdsList.isEmpty()) { - for (RouterIds routerId : routerIdsList) { - dissociateRouterFromVpn(vpnId, routerId.getRouterId()); - } - List rtrIdsList = routerIdsList.stream().map(routerId -> routerId.getRouterId()) - .collect(Collectors.toList()); - if (rtrIdsList.contains(vpnId) && vpnMap.getNetworkIds() != null) { - // dissociate networks + if (vpnMap != null) { + Map keyRouterIdsMap = vpnMap.getRouterIds(); + List routerUuidList = new ArrayList<>(); + // dissociate router + if (keyRouterIdsMap != null && !keyRouterIdsMap.isEmpty()) { + for (RouterIds router : keyRouterIdsMap.values()) { + Uuid routerId = router.getRouterId(); + routerUuidList.add(routerId); + dissociateRouterFromVpn(vpnId, routerId); + } + } + if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) { dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds()); } + } else { + LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue()); } // remove entire vpnMaps node deleteVpnMapsNode(vpnId); @@ -2252,30 +2346,29 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } private boolean isVpnOfTypeL2(VpnInstance vpnInstance) { - return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2; + return vpnInstance != null && vpnInstance.isL2vpn(); } // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) { updateVpnMaps(vpnId, null, routerId, null, null); - LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue()); - List routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId); - for (Uuid subnetId : routerSubnets) { - Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true); - if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) { - neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), - NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true); + LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue()); + List subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId); + IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; + for (Subnetmap sn : subMapList) { + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()); + if (!ipVersion.isIpVersionChosen(ipVers)) { + ipVersion = ipVersion.addVersion(ipVers); } } - - try { - checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId); - LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(), - vpnId.getValue()); - } catch (Exception e) { - LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId - .getValue(), vpnId.getValue(), e); + if (ipVersion != IpVersionChoice.UNDEFINED) { + LOG.debug("associateRouterToVpn: Updating vpnInstance ip address family {} for VPN {} ", + ipVersion, vpnId); + neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true); + } + for (Subnetmap sn : subMapList) { + updateVpnForSubnet(routerId, vpnId, sn.getId(), true); } } @@ -2298,31 +2391,23 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even @SuppressWarnings("checkstyle:IllegalCatch") protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) { - List routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId); - boolean vpnInstanceIpVersionsRemoved = false; - IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED; - for (Uuid subnetId : routerSubnets) { - Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId); - if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) { - vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils - .getIpVersionFromString(sn.getSubnetIp())); - vpnInstanceIpVersionsRemoved = true; + clearFromVpnMaps(vpnId, routerId, null); + List subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId); + IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; + for (Subnetmap sn : subMapList) { + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()); + if (ipVersion.isIpVersionChosen(ipVers)) { + ipVersion = ipVersion.addVersion(ipVers); } - LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue()); - updateVpnForSubnet(vpnId, routerId, subnetId, false); + LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}", + routerId.getValue()); + updateVpnForSubnet(vpnId, routerId, sn.getId(), false); } - - if (vpnInstanceIpVersionsRemoved) { - neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false); - } - clearFromVpnMaps(vpnId, routerId, null); - try { - checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId); - LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(), - vpnId.getValue()); - } catch (Exception e) { - LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId - .getValue(), vpnId.getValue(), e); + if (ipVersion != IpVersionChoice.UNDEFINED) { + LOG.debug("dissociateRouterFromVpn; Updating vpnInstance with ip address family {} for VPN {} ", + ipVersion, vpnId); + neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, + false); } } @@ -2333,10 +2418,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * @param networkList List list of network Ids (Uuid), which will be associated. * @return list of formatted strings with detailed error messages. */ - @Nonnull - protected List associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List networkList) { + @NonNull + protected List associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List networkList) { List failedNwList = new ArrayList<>(); HashSet passedNwList = new HashSet<>(); + ConcurrentMap extNwMap = new ConcurrentHashMap<>(); + boolean isExternalNetwork = false; if (networkList.isEmpty()) { LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue()); failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty", @@ -2359,6 +2446,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even return failedNwList; } Set routeTargets = vpnManager.getRtListForVpn(vpnId.getValue()); + boolean isIpFamilyUpdated = false; + IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; for (Uuid nw : networkList) { Network network = neutronvpnUtils.getNeutronNetwork(nw); if (network == null) { @@ -2383,12 +2472,26 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even + "another VPN %s", nw.getValue(), networkVpnId.getValue())); continue; } - if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) { - LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}", - nw.getValue(), vpnId.getValue()); - failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s", - nw.getValue(), vpnId.getValue())); - continue; + /* Handle association of external network(s) to Internet BGP-VPN use case outside of the + * networkList iteration + */ + if (neutronvpnUtils.getIsExternal(network)) { + extNwMap.put(nw, network); + isExternalNetwork = true; + //Check whether router-gw is set with external network before external network to BGPVPN association + List routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw); + if (!routerList.isEmpty()) { + for (Uuid routerId : routerList) { + //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance + if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) { + ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6); + LOG.debug("associateNetworksToVpn: External network {} is already associated with " + + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 " + + "address family type in Internet VPN Instance {}", network, routerId, vpnId); + break; + } + } + } } List subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw); if (subnetmapList == null || subnetmapList.isEmpty()) { @@ -2398,6 +2501,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) { continue; } + for (Subnetmap subnetmap : subnetmapList) { + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()); + if (!ipVersion.isIpVersionChosen(ipVers)) { + ipVersion = ipVersion.addVersion(ipVers); + } + } + //Update vpnInstance for IP address family + if (ipVersion != IpVersionChoice.UNDEFINED && !isIpFamilyUpdated) { + LOG.debug("associateNetworksToVpn: Updating vpnInstance with ip address family {}" + + " for VPN {} ", ipVersion, vpnId); + neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true); + isIpFamilyUpdated = true; + } for (Subnetmap subnetmap : subnetmapList) { Uuid subnetId = subnetmap.getId(); Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId); @@ -2408,10 +2524,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even + " as it is already associated", subnetId.getValue(), vpnId.getValue())); continue; } - if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(subnetmap, vpnId)) { - neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), - NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()), true); - } if (!NeutronvpnUtils.getIsExternal(network)) { LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(), vpnId.getValue()); @@ -2422,43 +2534,70 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } passedNwList.add(nw); + //Handle association of external network(s) to Internet BGP-VPN Instance use case + if (!extNwMap.isEmpty() || extNwMap != null) { + for (Network extNw : extNwMap.values()) { + if (!associateExtNetworkToVpn(vpnId, extNw, vpnInstance.getBgpvpnType())) { + LOG.error("associateNetworksToVpn: Failed to associate Provider External Network {} with " + + "VPN {}", extNw, vpnId.getValue()); + failedNwList.add(String.format("Failed to associate Provider External Network %s with " + + "VPN %s", extNw, vpnId.getValue())); + continue; + } + } + } } - } catch (ReadFailedException e) { + } catch (ExecutionException | InterruptedException e) { LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(), networkList, e); failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(), networkList, e)); } - updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList)); - LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue()); + //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method. + if (!isExternalNetwork) { + updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList)); + } + LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue()); return failedNwList; } - private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) { + private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet, + VpnInstance.BgpvpnType bgpVpnType) { if (!addExternalNetworkToVpn(extNet, vpnId)) { return false; } - VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue()); - if (vpnOpDataEntry == null) { - LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue()); - return false; - } - if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) { - LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue()); - neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId); - } - for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) { + if (!bgpVpnType.equals(VpnInstance.BgpvpnType.InternetBGPVPN)) { + LOG.info("associateExtNetworkToVpn: External network {} is associated to VPN {}." + + "Hence set vpnInstance type to {} from {} ", extNet.key().getUuid().getValue(), + vpnId.getValue(), VpnInstance.BgpvpnType.InternetBGPVPN.getName(), + VpnInstance.BgpvpnType.BGPVPN.getName()); + neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.InternetBGPVPN, vpnId); + } + //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows + List extNwList = Collections.singletonList(extNet.key().getUuid()); + updateVpnMaps(vpnId, null, null, null, extNwList); + IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; + for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) { Subnetmap sm = neutronvpnUtils.getSubnetmap(snId); if (sm == null) { LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue()); continue; } - updateVpnInternetForSubnet(sm, vpnId, true); - if (!vpnOpDataEntry.isIpv6Configured() - && NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6) { - LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue()); - neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true); + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) { + continue; + } + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) { + updateVpnInternetForSubnet(sm, vpnId, true); } + if (!ipVersion.isIpVersionChosen(ipVers)) { + ipVersion = ipVersion.addVersion(ipVers); + } + } + if (ipVersion != IpVersionChoice.UNDEFINED) { + neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true); + LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue()); + neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true); } return true; } @@ -2470,10 +2609,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * @param networkList List list of network Ids (Uuid), which will be disassociated. * @return list of formatted strings with detailed error messages. */ - @Nonnull - protected List dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List networkList) { + @NonNull + protected List dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List networkList) { List failedNwList = new ArrayList<>(); HashSet passedNwList = new HashSet<>(); + ConcurrentMap extNwMap = new ConcurrentHashMap<>(); + IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; if (networkList.isEmpty()) { LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty"); failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty", @@ -2488,7 +2629,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } Network network = neutronvpnUtils.getNeutronNetwork(nw); if (network == null) { - LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS"); + LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue()); failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS", nw.getValue())); continue; @@ -2508,48 +2649,85 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even vpnId.getValue())); continue; } - if (NeutronvpnUtils.getIsExternal(network)) { - if (disassociateExtNetworkFromVpn(vpnId, network)) { - passedNwList.add(nw); - continue; - } else { - LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}", - nw.getValue(), vpnId.getValue()); - failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(), - vpnId.getValue())); - continue; + /* Handle disassociation of external network(s) from Internet BGP-VPN use case outside of the + * networkList iteration + */ + if (neutronvpnUtils.getIsExternal(network)) { + extNwMap.put(nw, network); + //Handle external-Nw to BGPVPN Disassociation and still ext-router is being set with external-Nw + List routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw); + if (!routerList.isEmpty()) { + for (Uuid routerId : routerList) { + //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance + if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) { + ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6); + LOG.debug("dissociateNetworksFromVpn: External network {} is still associated with " + + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 " + + "address family type in Internet VPN Instance {}", network, routerId, vpnId); + break; + } + } } } - Set routeTargets = vpnManager.getRtListForVpn(vpnId.getValue()); for (Uuid subnet : networkSubnets) { Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet); - if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(subnetmap, vpnId)) { - IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED; - IpVersionChoice ipVersion = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()); - neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), - ipVersionsToRemove.addVersion(ipVersion), false); + if (subnetmap == null) { + failedNwList.add(String.format("subnetmap %s not found for network %s", + subnet.getValue(), nw.getValue())); + LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when " + + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(), + vpnId.getValue()); + continue; + } + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()); + if (!ipVersion.isIpVersionChosen(ipVers)) { + ipVersion = ipVersion.addVersion(ipVers); + } + if (!NeutronvpnUtils.getIsExternal(network)) { + LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(), + vpnId.getValue()); + removeSubnetFromVpn(vpnId, subnetmap, null); + Set routeTargets = vpnManager.getRtListForVpn(vpnId.getValue()); + vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(), + vpnId.getValue()); + passedNwList.add(nw); + } + } + if (ipVersion != IpVersionChoice.UNDEFINED) { + LOG.debug("dissociateNetworksFromVpn: Updating vpnInstance with ip address family {}" + + " for VPN {}", ipVersion, vpnId); + neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false); + } + } + //Handle disassociation of external network(s) from Internet BGP-VPN Instance use case + if (!extNwMap.isEmpty() || extNwMap != null) { + for (Network extNw : extNwMap.values()) { + if (disassociateExtNetworkFromVpn(vpnId, extNw)) { + passedNwList.add(extNw.getUuid()); + } else { + LOG.error("dissociateNetworksFromVpn: Failed to withdraw External Provider Network {} from VPN {}", + extNw, vpnId.getValue()); + failedNwList.add(String.format("Failed to withdraw External Provider Network %s from VPN %s", + extNw, vpnId.getValue())); + continue; } - LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(), - vpnId.getValue()); - removeSubnetFromVpn(vpnId, subnet, null); - vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(), - vpnId.getValue()); - passedNwList.add(nw); } } clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList)); - LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(), - vpnId.getValue()); + LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully", + passedNwList, vpnId.getValue()); return failedNwList; } - private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) { + private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) { if (!removeExternalNetworkFromVpn(extNet)) { return false; } // check, if there is another Provider Networks associated with given VPN List vpnNets = getNetworksForVpn(vpnId); if (vpnNets != null) { + //Remove currently disassociated network from the list + vpnNets.remove(extNet.getUuid()); for (Uuid netId : vpnNets) { if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) { LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network " @@ -2558,20 +2736,35 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } } - LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}", - VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue()); - neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId); - for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) { + ///Set VPN Type is BGPVPN from InternetBGPVPN + LOG.info("disassociateExtNetworkFromVpn: Set BGP-VPN type with {} for VPN {} and update IPv6 address family. " + + "Since external network is disassociated from VPN {}", + VpnInstance.BgpvpnType.BGPVPN, extNet, vpnId.getValue()); + neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.BGPVPN, vpnId); + IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; + for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) { Subnetmap sm = neutronvpnUtils.getSubnetmap(snId); if (sm == null) { LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue()); continue; } - updateVpnInternetForSubnet(sm, vpnId, false); + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) { + continue; + } + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) { + updateVpnInternetForSubnet(sm, vpnId, false); + } + if (!ipVersion.isIpVersionChosen(ipVers)) { + ipVersion = ipVersion.addVersion(ipVers); + } + } + if (ipVersion != IpVersionChoice.UNDEFINED) { + neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false); + LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", + vpnId.getValue()); + neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false); } - neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false); - LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue()); - neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false); return true; } @@ -2591,7 +2784,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even try { if (neutronvpnUtils.getVpnMap(vpnId) != null) { LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(), - input.getNetworkId().toString()); + input.getNetworkId()); List netIds = input.getNetworkId(); if (netIds != null && !netIds.isEmpty()) { List failed = associateNetworksToVpn(vpnId, netIds); @@ -2611,6 +2804,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even result.set(RpcResultBuilder.success().build()); } } catch (Exception ex) { + LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex); result.set(RpcResultBuilder.failed().withError(ErrorType.APPLICATION, formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}", input.getVpnId().getValue(), ex.getMessage(), ex)).build()); @@ -2629,13 +2823,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.debug("associateRouter {}", input); StringBuilder returnMsg = new StringBuilder(); Uuid vpnId = input.getVpnId(); - List - routerIds = input.getRouterIds(); - Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!"); + Map keyRouterIdsMap = input.nonnullRouterIds(); + Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "associateRouter: RouterIds list is empty!"); Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!"); Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!"); for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input - .RouterIds routerId : routerIds) { + .RouterIds routerId : keyRouterIdsMap.values()) { VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId); Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId()); if (vpnMap != null) { @@ -2686,8 +2881,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even List fixedIPList = new ArrayList<>(); Port port = neutronvpnUtils.getNeutronPort(portId); if (port != null) { - List fixedIPs = port.getFixedIps(); - for (FixedIps ip : fixedIPs) { + for (FixedIps ip : port.nonnullFixedIps().values()) { fixedIPList.add(ip.getIpAddress().stringValue()); } } else { @@ -2730,7 +2924,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even try { if (neutronvpnUtils.getVpnMap(vpnId) != null) { LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(), - input.getNetworkId().toString()); + input.getNetworkId()); List netIds = input.getNetworkId(); if (netIds != null && !netIds.isEmpty()) { List failed = dissociateNetworksFromVpn(vpnId, netIds); @@ -2772,15 +2966,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.debug("dissociateRouter {}", input); StringBuilder returnMsg = new StringBuilder(); Uuid vpnId = input.getVpnId(); - List routerIdList = input.getRouterIds(); + Map keyRouterIdsMap = input.nonnullRouterIds(); String routerIdsString = ""; - Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!"); + Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "dissociateRouter: RouterIds list is empty!"); Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!"); - Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!"); + Preconditions.checkNotNull(keyRouterIdsMap, "dissociateRouter: keyRouterIdsMap not found!"); if (neutronvpnUtils.getVpnMap(vpnId) != null) { for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input - .RouterIds routerId : routerIdList) { + .RouterIds routerId : keyRouterIdsMap.values()) { try { if (routerId != null) { routerIdsString += routerId.getRouterId() + ", "; @@ -2830,13 +3025,25 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (vpnId != null) { // remove existing external vpn interfaces for (Uuid subnetId : routerSubnetIds) { - removeSubnetFromVpn(vpnId, subnetId, internetVpnId); + Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId); + if (subnetmap != null) { + removeSubnetFromVpn(vpnId, subnetmap, internetVpnId); + } else { + LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}", + subnetId, routerId.getValue()); + } } clearFromVpnMaps(vpnId, routerId, null); } else { // remove existing internal vpn interfaces for (Uuid subnetId : routerSubnetIds) { - removeSubnetFromVpn(routerId, subnetId, internetVpnId); + Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId); + if (subnetmap != null) { + removeSubnetFromVpn(routerId, subnetmap, internetVpnId); + } else { + LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}", + subnetId, routerId.getValue()); + } } } // delete entire vpnMaps node for internal VPN @@ -2850,6 +3057,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even return neutronvpnUtils.getNeutronSubnet(subnetId); } + @Nullable protected IpAddress getNeutronSubnetGateway(Uuid subnetId) { Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId); if (null != sn) { @@ -2883,9 +3091,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command. * * @return a List of String to be printed on screen - * @throws ReadFailedException if there was a problem reading from the data store + * @throws ExecutionException or InterruptedException if there was a problem reading from the data store */ - public List showNeutronPortsCLI() throws ReadFailedException { + public List showNeutronPortsCLI() throws ExecutionException, InterruptedException { List result = new ArrayList<>(); result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length", "IP Address")); @@ -2894,11 +3102,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even Optional ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier); if (ports.isPresent() && ports.get().getPort() != null) { - for (Port port : ports.get().getPort()) { - List fixedIPs = port.getFixedIps(); - if (fixedIPs != null && !fixedIPs.isEmpty()) { + for (Port port : ports.get().nonnullPort().values()) { + Map keyFixedIpsMap = port.getFixedIps(); + if (keyFixedIpsMap != null && !keyFixedIpsMap.isEmpty()) { List ipList = new ArrayList<>(); - for (FixedIps fixedIp : fixedIPs) { + for (FixedIps fixedIp : keyFixedIpsMap.values()) { IpAddress ipAddress = fixedIp.getIpAddress(); if (ipAddress.getIpv4Address() != null) { ipList.add(ipAddress.getIpv4Address().getValue()); @@ -2948,9 +3156,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even result.add(""); result.add("------------------------------------------------------------------------------------"); result.add(""); - List vpnList = rpcResult.getResult().getL3vpnInstances(); - for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn - .rev150602.VpnInstance vpn : vpnList) { + for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn : + rpcResult.getResult().nonnullL3vpnInstances()) { String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue() : "\" " + " \""; result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId, @@ -3002,7 +3209,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even return; } - ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { + LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { for (String elanInterface : extElanInterfaces) { createExternalVpnInterface(extNetId, elanInterface, tx); } @@ -3017,7 +3224,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.error("No external ports attached for external network {}", extNetId.getValue()); return; } - ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { + LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { for (String elanInterface : extElanInterfaces) { InstanceIdentifier vpnIfIdentifier = NeutronvpnUtils .buildVpnInterfaceIdentifier(elanInterface); @@ -3028,21 +3235,22 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } private void createExternalVpnInterface(Uuid vpnId, String infName, - TypedWriteTransaction wrtConfigTxn) { + TypedWriteTransaction wrtConfigTxn) { writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */, false /* not a router iface */, wrtConfigTxn); } // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") - private void writeVpnInterfaceToDs(@Nonnull Collection vpnIdList, String infName, Adjacencies adjacencies, - Uuid networkUuid, Boolean isRouterInterface, TypedWriteTransaction wrtConfigTxn) { + private void writeVpnInterfaceToDs(@NonNull Collection vpnIdList, String infName, + @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface, + TypedWriteTransaction wrtConfigTxn) { if (vpnIdList.isEmpty() || infName == null) { LOG.error("vpnid is empty or interface({}) is null", infName); return; } if (wrtConfigTxn == null) { - ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG, "Error writing VPN interface"); return; @@ -3063,7 +3271,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (networkUuid != null) { Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid); ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork); - NetworkAttributes.NetworkType networkType = (providerType != null) + NetworkAttributes.NetworkType networkType = providerType != null ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null; String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork); vpnb.setNetworkId(networkUuid).setNetworkType(networkType) @@ -3083,62 +3291,62 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies, - TypedWriteTransaction wrtConfigTxn) { + TypedWriteTransaction wrtConfigTxn) { if (vpnId == null || infName == null) { LOG.error("vpn id or interface is null"); return; } if (wrtConfigTxn == null) { LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null"); - ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { + LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx); }), LOG, "Error updating VPN interface with adjacencies"); return; } InstanceIdentifier vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName); - boolean isLockAcquired = false; - try { - isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS); - Optional optionalVpnInterface = SingleTransactionDataBroker - .syncReadOptional(dataBroker, LogicalDatastoreType - .CONFIGURATION, vpnIfIdentifier); - if (optionalVpnInterface.isPresent()) { - VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get()); - LOG.debug("Updating vpn interface {} with new adjacencies", infName); - if (adjacencies == null) { - if (isLockAcquired) { - interfaceLock.unlock(infName); + try (AcquireResult lock = tryInterfaceLock(infName)) { + if (!lock.wasAcquired()) { + // FIXME: why do we even bother with locking if we do not honor it?! + logTryLockFailure(infName); + } + + try { + Optional optionalVpnInterface = SingleTransactionDataBroker + .syncReadOptional(dataBroker, LogicalDatastoreType + .CONFIGURATION, vpnIfIdentifier); + if (optionalVpnInterface.isPresent()) { + VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get()); + LOG.debug("Updating vpn interface {} with new adjacencies", infName); + + if (adjacencies == null) { + return; } - return; - } - vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies); - if (optionalVpnInterface.get().getVpnInstanceNames() != null) { - List listVpnInstances = new ArrayList<>( - optionalVpnInterface.get().getVpnInstanceNames()); - if (listVpnInstances.isEmpty() || !VpnHelper - .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) { + vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies); + if (optionalVpnInterface.get().getVpnInstanceNames() != null) { + List listVpnInstances = new ArrayList<>( + optionalVpnInterface.get().getVpnInstanceNames().values()); + if (listVpnInstances.isEmpty() + || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) { + VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(), + AssociatedSubnetType.V4AndV6Subnets); + listVpnInstances.add(vpnInstance); + vpnIfBuilder.setVpnInstanceNames(listVpnInstances); + } + } else { VpnInstanceNames vpnInstance = VpnHelper - .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets); + .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets); + List listVpnInstances = new ArrayList<>(); listVpnInstances.add(vpnInstance); vpnIfBuilder.setVpnInstanceNames(listVpnInstances); } - } else { - VpnInstanceNames vpnInstance = VpnHelper - .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets); - List listVpnInstances = new ArrayList<>(); - listVpnInstances.add(vpnInstance); - vpnIfBuilder.setVpnInstanceNames(listVpnInstances); + LOG.info("Updating vpn interface {} with new adjacencies", infName); + wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build()); } - LOG.info("Updating vpn interface {} with new adjacencies", infName); - wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build()); - } - } catch (IllegalStateException | ReadFailedException ex) { - LOG.error("Update of vpninterface {} failed", infName, ex); - } finally { - if (isLockAcquired) { - interfaceLock.unlock(infName); + } catch (IllegalStateException | ExecutionException | InterruptedException ex) { + // FIXME: why are we catching IllegalStateException here? + LOG.error("Update of vpninterface {} failed", infName, ex); } } } @@ -3149,22 +3357,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even return help.toString(); } - private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws - InterruptedException { - RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId) - .setVpnId(vpnId).build(); - LOG.info("publishing notification upon association of router to VPN"); - notificationPublishService.putNotification(routerAssociatedToVpn); - } - - private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws - InterruptedException { - RouterDisassociatedFromVpn routerDisassociatedFromVpn = - new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build(); - LOG.info("publishing notification upon disassociation of router from VPN"); - notificationPublishService.putNotification(routerDisassociatedFromVpn); - } - protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) { floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName); } @@ -3207,7 +3399,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier, networks); return true; - } catch (TransactionCommitFailedException | ReadFailedException ex) { + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) { LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(), extNetId.getValue(), ex); } @@ -3236,7 +3428,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even extNetId.getValue()); SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks); return true; - } catch (TransactionCommitFailedException | ReadFailedException ex) { + } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) { LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ", extNetId.getValue(), ex); } @@ -3247,10 +3439,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even Optional existingVpnName = Optional.of(primaryRd); Optional vpnInstanceOpDataOptional; try { - vpnInstanceOpDataOptional = SingleTransactionDataBroker - .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, + vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, neutronvpnUtils.getVpnOpDataIdentifier(primaryRd)); - } catch (ReadFailedException e) { + } catch (ExecutionException | InterruptedException e) { LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}", primaryRd, e); /*Read failed. We don't know if a VPN exists or not. @@ -3260,26 +3451,72 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (vpnInstanceOpDataOptional.isPresent()) { existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName()); } else { - existingVpnName = Optional.absent(); + existingVpnName = Optional.empty(); } return existingVpnName; } - private String formatAndLog(Consumer logger, String template, Object arg) { + private static String formatAndLog(Consumer logger, String template, Object arg) { return logAndReturnMessage(logger, MessageFormatter.format(template, arg)); } - private String formatAndLog(Consumer logger, String template, Object arg1, Object arg2) { + private static String formatAndLog(Consumer logger, String template, Object arg1, Object arg2) { return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2)); } - private String formatAndLog(Consumer logger, String template, Object... args) { + private static String formatAndLog(Consumer logger, String template, Object... args) { return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args)); } - private String logAndReturnMessage(Consumer logger, FormattingTuple tuple) { + private static String logAndReturnMessage(Consumer logger, FormattingTuple tuple) { String message = tuple.getMessage(); logger.accept(message); return message; } + + protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId, + @NonNull Subnetmap subnetMap) { + updateVpnInternetForSubnet(subnetMap, internetVpnId, true); + neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true); + if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) { + neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true); + LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}", + subnetMap.getId().getValue(), internetVpnId.getValue()); + } + } + + protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId, + @NonNull Subnetmap subnetMap) { + updateVpnInternetForSubnet(subnetMap, internetVpnId, false); + neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false); + } + + protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) { + if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) { + LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule " + + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed", + internetVpnId.getValue(), routerId.getValue()); + neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW + ? true : false); + } + } + + @CheckReturnValue + private AcquireResult tryInterfaceLock(final String infName) { + return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS); + } + + @CheckReturnValue + private AcquireResult tryVpnLock(final Uuid vpnId) { + return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS); + } + + private static ReentrantLock lockForUuid(Uuid uuid) { + // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain + return JvmGlobalLocks.getLockForString(uuid.getValue()); + } + + private static void logTryLockFailure(Object objectId) { + LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable()); + } }