X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=neutronvpn%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Fneutronvpn%2FNeutronvpnManager.java;h=cb943282bdd575366907e210ea85d4639bba01aa;hb=691e944fb808d38a0cc860059acac003584419ca;hp=5fdd9231c0e5ebad3655b97667a4ec7605da0186;hpb=46a42576072bde8a9763a9de7a3982be432d604d;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 5fdd9231c0..cb943282bd 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 @@ -10,6 +10,7 @@ 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.netvirt.neutronvpn.api.utils.NeutronUtils.requireNonNullElse; import com.google.common.base.Optional; import com.google.common.base.Preconditions; @@ -35,8 +36,8 @@ import java.util.concurrent.ConcurrentHashMap; 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; @@ -45,13 +46,16 @@ 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.OptimisticLockFailedException; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; -import org.opendaylight.genius.infra.Datastore; +import org.opendaylight.genius.infra.Datastore.Configuration; 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; @@ -131,10 +135,6 @@ 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; @@ -160,6 +160,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.A 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; @@ -214,7 +215,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even 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; @@ -237,15 +239,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,10 +268,12 @@ 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) { + @Nullable NetworkAttributes.NetworkType networkType, long segmentationId) { try { InstanceIdentifier subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId); - synchronized (subnetId.getValue().intern()) { + final ReentrantLock lock = lockForUuid(subnetId); + lock.lock(); + try { LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString()); Optional sn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier); @@ -275,6 +289,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even subnetId.getValue()); SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier, subnetmapBuilder.build()); + } finally { + lock.unlock(); } } catch (TransactionCommitFailedException | ReadFailedException e) { LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue()); @@ -289,206 +305,215 @@ 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); } + Subnetmap subnetmap = builder.build(); + LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue()); + SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap); + return subnetmap; } catch (ReadFailedException | TransactionCommitFailedException 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("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ", subnetId.getValue()); - SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap); + return; } + LOG.debug("WithRouterFixedIP: 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 (ReadFailedException | TransactionCommitFailedException e) { LOG.error("WithRouterFixedIP: 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()); + 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 portList = builder.getPortList(); + if (null == portList) { + portList = new ArrayList<>(); } - 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 directPortList = builder.getDirectPortList(); + if (null == directPortList) { + directPortList = new ArrayList<>(); } - 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) { 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 = 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) { 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()) { + 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()); } } catch (ReadFailedException | TransactionCommitFailedException 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 +524,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(); } } @@ -640,7 +666,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - protected 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) @@ -695,7 +722,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List networkIds) { + private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List networkIds) { boolean isLockAcquired = false; InstanceIdentifier vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class) .child(VpnMap.class, new VpnMapKey(vpnId)) @@ -789,15 +816,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface, - TypedWriteTransaction wrtConfigTxn, - Subnetmap sn, VpnInterface vpnIface) { + TypedWriteTransaction wrtConfigTxn, + @Nullable Subnetmap sn, @Nullable VpnInterface vpnIface) { List adjList = new ArrayList<>(); if (vpnIface != null) { adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency(); } String infName = port.getUuid().getValue(); LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName); - for (FixedIps ip : port.getFixedIps()) { + for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.emptyList())) { String ipValue = ip.getIpAddress().stringValue(); String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128"; if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) { @@ -839,19 +866,21 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } 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, null, 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; @@ -870,7 +899,9 @@ 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(); + List vpnAdjsList = + requireNonNullElse(optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency(), + Collections.emptyList()); List updatedAdjsList = new ArrayList<>(); boolean isIpFromAnotherSubnet = false; for (Adjacency adj : vpnAdjsList) { @@ -894,8 +925,8 @@ 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<>(); @@ -932,7 +963,7 @@ 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( txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, @@ -978,7 +1009,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port, - TypedWriteTransaction writeConfigTxn, + TypedWriteTransaction writeConfigTxn, Subnetmap sm) { if (vpnId == null || port == null) { return; @@ -1023,8 +1054,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even mipToQuery, infName, vpnId.getValue()); } } - List ips = port.getFixedIps(); - for (FixedIps ip : ips) { + for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.emptyList())) { String ipValue = ip.getIpAddress().stringValue(); //skip IPv4 address if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) { @@ -1049,9 +1079,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - 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; } @@ -1105,13 +1136,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build(); vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies); } - List ips = port.getFixedIps(); - for (FixedIps ip : ips) { + for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.emptyList())) { String ipValue = ip.getIpAddress().stringValue(); if (oldVpnId != null) { neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), ipValue, writeConfigTxn); } + if ((NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6) + && (isInternetVpn == true)) { + continue; + } + neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port .getMacAddress().getValue(), isSubnetIp, writeConfigTxn); } @@ -1128,8 +1163,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List rd, List irt, - List ert, Uuid router, List networks) { + public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List rd, + @Nullable List irt, @Nullable List ert, @Nullable Uuid router, + @Nullable List networks) { IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router); @@ -1173,7 +1209,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * @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, + List ertList, @Nullable List routerIdsList, @Nullable List networkList, VpnInstance.Type type, long l3vni) throws Exception { IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED; @@ -1381,7 +1417,8 @@ 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 : requireNonNullElse(optionalVpns.get().getVpnInstance(), + Collections.emptyList())) { // eliminating implicitly created (router and VLAN provider external network specific) VPNs // from getL3VPN output if (vpn.getIpv4Family().getRouteDistinguisher() != null) { @@ -1502,10 +1539,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even int failurecount = 0; int warningcount = 0; - List vpns = input.getId(); + List vpns = requireNonNullElse(input.getId(), Collections.emptyList()); for (Uuid vpn : vpns) { - RpcError error; - String msg; try { LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue()); InstanceIdentifier vpnIdentifier = @@ -1639,7 +1674,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } - protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) { + protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @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(), @@ -1734,7 +1769,7 @@ 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 { removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm); @@ -1754,7 +1789,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even tx -> { if (isBeingAssociated) { updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port), - true, false, tx); + true, false, tx, true); } else { removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm); } @@ -1763,6 +1798,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even } } + @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()); @@ -1780,8 +1816,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * associated with internet BGP-VPN. */ if (vpnExtUuid != null) { - //Update V6 Internet default route match with new VPN metadata - neutronvpnUtils.updateVpnInstanceWithFallback(vpnExtUuid, isBeingAssociated); + /* 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 ! @@ -1789,7 +1832,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> updateVpnInterface(newVpnId, oldVpnId, neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()), - isBeingAssociated, true, tx)); + isBeingAssociated, true, tx, false)); Futures.addCallback(future, new FutureCallback() { @Override public void onSuccess(Void result) { @@ -1804,7 +1847,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> updateVpnInterface(newVpnId, oldVpnId, neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false, - tx)))); + tx, false)))); } } } @@ -1827,59 +1870,61 @@ 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); + 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); + 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); + } 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 = 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))); } } - } catch (ReadFailedException | TransactionCommitFailedException e) { - LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e); } + } catch (ReadFailedException | TransactionCommitFailedException e) { + LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e); + } finally { + lock.unlock(); } } @@ -2238,18 +2283,18 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even // read VPNMaps VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId); List routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null; + List routerUuidList = new ArrayList<>(); // 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 - dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds()); + for (RouterIds router : routerIdsList) { + Uuid routerId = router.getRouterId(); + routerUuidList.add(routerId); + dissociateRouterFromVpn(vpnId, routerId); } } + if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) { + dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds()); + } // remove entire vpnMaps node deleteVpnMapsNode(vpnId); @@ -2266,29 +2311,22 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even @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()); - IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; + 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) { - updateVpnForSubnet(routerId, vpnId, sn.getId(), true); IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()); if (!ipVersion.isIpVersionChosen(ipVers)) { ipVersion = ipVersion.addVersion(ipVers); } } if (ipVersion != IpVersionChoice.UNDEFINED) { - LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", ipVersion, - vpnId); + LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ", + ipVersion, vpnId); neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true); } - - 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); + for (Subnetmap sn : subMapList) { + updateVpnForSubnet(routerId, vpnId, sn.getId(), true); } } @@ -2311,31 +2349,24 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even @SuppressWarnings("checkstyle:IllegalCatch") protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) { + clearFromVpnMaps(vpnId, routerId, null); List subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId); IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; for (Subnetmap sn : subMapList) { - IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()); + 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()); + LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}", + routerId.getValue()); updateVpnForSubnet(vpnId, routerId, sn.getId(), false); } if (ipVersion != IpVersionChoice.UNDEFINED) { - LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", + LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ", ipVersion, vpnId); neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, 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); - } } /** @@ -2349,6 +2380,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even protected List associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List networkList) { List failedNwList = new ArrayList<>(); HashSet passedNwList = new HashSet<>(); + 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", @@ -2402,6 +2434,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even nw.getValue(), vpnId.getValue())); continue; } + if (NeutronvpnUtils.getIsExternal(network)) { + isExternalNetwork = true; + } List subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw); if (subnetmapList == null || subnetmapList.isEmpty()) { passedNwList.add(nw); @@ -2411,6 +2446,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even continue; } IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; + for (Subnetmap subnetmap : subnetmapList) { + IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()); + if (!ipVersion.isIpVersionChosen(ipVers)) { + ipVersion = ipVersion.addVersion(ipVers); + } + } + if (ipVersion != IpVersionChoice.UNDEFINED) { + LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}" + + " for VPN {} ", ipVersion, vpnId); + neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true); + } for (Subnetmap subnetmap : subnetmapList) { Uuid subnetId = subnetmap.getId(); Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId); @@ -2421,10 +2467,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even + " as it is already associated", subnetId.getValue(), vpnId.getValue())); continue; } - IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()); - if (!ipVersion.isIpVersionChosen(ipVers)) { - ipVersion = ipVersion.addVersion(ipVers); - } if (!NeutronvpnUtils.getIsExternal(network)) { LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(), vpnId.getValue()); @@ -2434,11 +2476,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even passedNwList.add(nw); } } - if (ipVersion != IpVersionChoice.UNDEFINED) { - LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", - ipVersion, vpnId); - neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true); - } passedNwList.add(nw); } } catch (ReadFailedException e) { @@ -2447,7 +2484,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even 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)); + //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.toString(), vpnId.getValue()); return failedNwList; } @@ -2465,6 +2505,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue()); neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, 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); @@ -2472,7 +2515,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue()); continue; } - IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) { + continue; + } if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) { updateVpnInternetForSubnet(sm, vpnId, true); } @@ -2480,10 +2526,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even ipVersion = ipVersion.addVersion(ipVers); } } - if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) { + 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(vpnId, true); + neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true); } return true; } @@ -2536,7 +2582,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even 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()); @@ -2545,30 +2590,32 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even continue; } } - Set routeTargets = vpnManager.getRtListForVpn(vpnId.getValue()); IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; for (Uuid subnet : networkSubnets) { Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet); - IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()); + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()); if (!ipVersion.isIpVersionChosen(ipVers)) { ipVersion = ipVersion.addVersion(ipVers); } - 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); + if (!NeutronvpnUtils.getIsExternal(network)) { + LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(), + vpnId.getValue()); + removeSubnetFromVpn(vpnId, subnet, null); + Set routeTargets = vpnManager.getRtListForVpn(vpnId.getValue()); + vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(), + vpnId.getValue()); + passedNwList.add(nw); + } } if (ipVersion != IpVersionChoice.UNDEFINED) { - LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}", - ipVersion, vpnId); + LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}" + + " for VPN {}", ipVersion, vpnId); neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false); } } 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.toString(), vpnId.getValue()); return failedNwList; } @@ -2600,7 +2647,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue()); continue; } - IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) { + continue; + } if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) { updateVpnInternetForSubnet(sm, vpnId, false); } @@ -2608,11 +2658,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even ipVersion = ipVersion.addVersion(ipVers); } } - if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) { + 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(vpnId, false); + neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false); } return true; } @@ -2728,8 +2778,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 : requireNonNullElse(port.getFixedIps(), Collections.emptyList())) { fixedIPList.add(ip.getIpAddress().stringValue()); } } else { @@ -2892,6 +2941,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) { @@ -2936,7 +2986,7 @@ 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()) { + for (Port port : requireNonNullElse(ports.get().getPort(), Collections.emptyList())) { List fixedIPs = port.getFixedIps(); if (fixedIPs != null && !fixedIPs.isEmpty()) { List ipList = new ArrayList<>(); @@ -2990,9 +3040,10 @@ 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 : + requireNonNullElse(rpcResult.getResult().getL3vpnInstances(), + Collections.emptyList())) { String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue() : "\" " + " \""; result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId, @@ -3070,15 +3121,16 @@ 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; @@ -3105,7 +3157,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) @@ -3125,7 +3177,7 @@ 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; @@ -3191,22 +3243,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); } @@ -3307,19 +3343,19 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even 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; @@ -3328,24 +3364,32 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId, @Nonnull Subnetmap subnetMap) { updateVpnInternetForSubnet(subnetMap, internetVpnId, true); - if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange( - IpVersionChoice.IPV6, routerId, 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(), internetVpnId.getValue()); + subnetMap.getId().getValue(), internetVpnId.getValue()); } - neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, true); } protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId, @Nonnull Subnetmap subnetMap) { updateVpnInternetForSubnet(subnetMap, internetVpnId, false); - if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange( - IpVersionChoice.IPV6, routerId, false)) { - neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, false); - LOG.info("removeV6PrivateSubnetToExtNetwork: withdraw IPv6 Private subnet {} from Internet VPN {}", - subnetMap.getId(), internetVpnId.getValue()); + 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); } - neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, false); + } + + 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()); } }