This is an automated email from the ASF dual-hosted git repository.
sureshanaparti pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.22 by this push:
new d31b5ff94e9 network: scope routed network/VPC subnets to a zone
(#14421)
d31b5ff94e9 is described below
commit d31b5ff94e9b8480d83e85efcae60aa6f2e7c90f
Author: prashanthr2 <[email protected]>
AuthorDate: Fri Oct 23 09:45:09 2026 +0100
network: scope routed network/VPC subnets to a zone (#14421)
* network: scope routed network/VPC subnets to a zone
The ip4_guest_subnet_network_map table had no zone column, so the subnet
bookkeeping for routed networks and VPCs was global. Creating a routed VPC
or network with a CIDR already used in another zone failed with
"The subnet is in use", even though the two zones are independent.
Add a nullable data_center_id column to ip4_guest_subnet_network_map and
scope the subnet lookup and the parentless overlap check by zone, so the
same CIDR can be used once per zone. Existing rows are backfilled from
their parent zone subnet, VPC or network.
Fixes #14419
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017rnv8vT6LQSKfwkzp8tvg9
* network: list and report routed subnets by their own zone
listIpv4SubnetsForGuestNetwork resolved the zoneid filter through
dc_ip4_guest_subnets, so a subnet with no parent never matched, and a zone
with no zone-level subnet returned an empty list. The response derived the
zone the same way, leaving parentless subnets with no zone at all.
Now that the record carries its zone, filter on data_center_id directly and
fall back to it when building the response.
Addresses review feedback on #14419.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017rnv8vT6LQSKfwkzp8tvg9
---------
Co-authored-by: Prashanth Reddy <[email protected]>
Co-authored-by: Claude Opus 5 <[email protected]>
---
.../network/Ipv4GuestSubnetNetworkMap.java | 2 +
.../network/Ipv4GuestSubnetNetworkMapVO.java | 15 ++++-
.../network/dao/Ipv4GuestSubnetNetworkMapDao.java | 4 +-
.../dao/Ipv4GuestSubnetNetworkMapDaoImpl.java | 8 ++-
.../resources/META-INF/db/schema-42210to42220.sql | 20 ++++++
.../cloudstack/network/RoutedIpv4ManagerImpl.java | 30 ++++-----
.../network/RoutedIpv4ManagerImplTest.java | 74 +++++++++++++++++++---
7 files changed, 121 insertions(+), 32 deletions(-)
diff --git
a/api/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMap.java
b/api/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMap.java
index 569ed22c164..1ab1b8527ec 100644
---
a/api/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMap.java
+++
b/api/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMap.java
@@ -36,6 +36,8 @@ public interface Ipv4GuestSubnetNetworkMap extends Identity,
InternalIdentity {
Long getParentId();
+ Long getDataCenterId();
+
String getSubnet();
Long getVpcId();
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMapVO.java
b/engine/schema/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMapVO.java
index cc726ba3d35..d8f88a13a90 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMapVO.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/network/Ipv4GuestSubnetNetworkMapVO.java
@@ -46,6 +46,9 @@ public class Ipv4GuestSubnetNetworkMapVO implements
Ipv4GuestSubnetNetworkMap {
@Column(name = "parent_id")
private Long parentId;
+ @Column(name = "data_center_id")
+ private Long dataCenterId;
+
@Column(name = "subnet")
private String subnet;
@@ -72,8 +75,9 @@ public class Ipv4GuestSubnetNetworkMapVO implements
Ipv4GuestSubnetNetworkMap {
uuid = UUID.randomUUID().toString();
}
- protected Ipv4GuestSubnetNetworkMapVO(Long parentId, String subnet, Long
networkId, Ipv4GuestSubnetNetworkMap.State state) {
+ protected Ipv4GuestSubnetNetworkMapVO(Long parentId, Long dataCenterId,
String subnet, Long networkId, Ipv4GuestSubnetNetworkMap.State state) {
this.parentId = parentId;
+ this.dataCenterId = dataCenterId;
this.subnet = subnet;
this.networkId = networkId;
this.state = state;
@@ -95,6 +99,15 @@ public class Ipv4GuestSubnetNetworkMapVO implements
Ipv4GuestSubnetNetworkMap {
return parentId;
}
+ @Override
+ public Long getDataCenterId() {
+ return dataCenterId;
+ }
+
+ public void setDataCenterId(Long dataCenterId) {
+ this.dataCenterId = dataCenterId;
+ }
+
@Override
public String getSubnet() {
return subnet;
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDao.java
b/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDao.java
index c3f860009db..be149003a96 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDao.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDao.java
@@ -31,8 +31,8 @@ public interface Ipv4GuestSubnetNetworkMapDao extends
GenericDao<Ipv4GuestSubnet
Ipv4GuestSubnetNetworkMapVO findFirstAvailable(long parentId, long
cidrSize);
Ipv4GuestSubnetNetworkMapVO findByNetworkId(long networkId);
Ipv4GuestSubnetNetworkMapVO findByVpcId(long vpcId);
- Ipv4GuestSubnetNetworkMapVO findBySubnet(String subnet);
+ Ipv4GuestSubnetNetworkMapVO findBySubnetAndDataCenterId(String subnet,
Long dataCenterId);
List<Ipv4GuestSubnetNetworkMapVO>
findSubnetsInStates(Ipv4GuestSubnetNetworkMap.State... states);
void deleteByParentId(long parentId);
- List<Ipv4GuestSubnetNetworkMapVO> listAllNoParent();
+ List<Ipv4GuestSubnetNetworkMapVO> listAllNoParentByDataCenterId(Long
dataCenterId);
}
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDaoImpl.java
b/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDaoImpl.java
index 95e53448907..7e778e16b40 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDaoImpl.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/network/dao/Ipv4GuestSubnetNetworkMapDaoImpl.java
@@ -63,6 +63,7 @@ public class Ipv4GuestSubnetNetworkMapDaoImpl extends
GenericDaoBase<Ipv4GuestSu
ParentIdSearch.done();
NoParentSearch = createSearchBuilder();
NoParentSearch.and("parentId", NoParentSearch.entity().getParentId(),
SearchCriteria.Op.NULL);
+ NoParentSearch.and("dataCenterId",
NoParentSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
NoParentSearch.done();
NetworkIdSearch = createSearchBuilder();
NetworkIdSearch.and("networkId",
NetworkIdSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
@@ -70,6 +71,7 @@ public class Ipv4GuestSubnetNetworkMapDaoImpl extends
GenericDaoBase<Ipv4GuestSu
NetworkIdSearch.done();
SubnetSearch = createSearchBuilder();
SubnetSearch.and("subnet", SubnetSearch.entity().getSubnet(),
SearchCriteria.Op.EQ);
+ SubnetSearch.and("dataCenterId",
SubnetSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
SubnetSearch.done();
StatesSearch = createSearchBuilder();
StatesSearch.and("state", StatesSearch.entity().getState(),
SearchCriteria.Op.IN);
@@ -142,9 +144,10 @@ public class Ipv4GuestSubnetNetworkMapDaoImpl extends
GenericDaoBase<Ipv4GuestSu
}
@Override
- public Ipv4GuestSubnetNetworkMapVO findBySubnet(String subnet) {
+ public Ipv4GuestSubnetNetworkMapVO findBySubnetAndDataCenterId(String
subnet, Long dataCenterId) {
SearchCriteria<Ipv4GuestSubnetNetworkMapVO> sc = SubnetSearch.create();
sc.setParameters("subnet", subnet);
+ sc.setParameters("dataCenterId", dataCenterId);
return findOneBy(sc);
}
@@ -163,8 +166,9 @@ public class Ipv4GuestSubnetNetworkMapDaoImpl extends
GenericDaoBase<Ipv4GuestSu
}
@Override
- public List<Ipv4GuestSubnetNetworkMapVO> listAllNoParent() {
+ public List<Ipv4GuestSubnetNetworkMapVO>
listAllNoParentByDataCenterId(Long dataCenterId) {
SearchCriteria<Ipv4GuestSubnetNetworkMapVO> sc =
NoParentSearch.create();
+ sc.setParameters("dataCenterId", dataCenterId);
return listBy(sc, null);
}
}
diff --git
a/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql
b/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql
index 5e4db5ffd0b..557c165539d 100644
--- a/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql
+++ b/engine/schema/src/main/resources/META-INF/db/schema-42210to42220.sql
@@ -43,3 +43,23 @@ UPDATE op_dc_vnet_alloc a
a.reservation_id = NULL,
a.taken = NULL
WHERE n.removed IS NOT NULL;
+
+-- Scope routed network/VPC subnets to a zone, so that the same CIDR can be
used in more than one zone. See #14419.
+CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.ip4_guest_subnet_network_map',
'data_center_id', 'bigint unsigned DEFAULT NULL COMMENT "zone it belongs to"');
+
+UPDATE `cloud`.`ip4_guest_subnet_network_map` m
+ JOIN `cloud`.`dc_ip4_guest_subnets` p ON p.id = m.parent_id
+ SET m.data_center_id = p.data_center_id
+WHERE m.data_center_id IS NULL;
+
+UPDATE `cloud`.`ip4_guest_subnet_network_map` m
+ JOIN `cloud`.`vpc` v ON v.id = m.vpc_id
+ SET m.data_center_id = v.zone_id
+WHERE m.data_center_id IS NULL;
+
+UPDATE `cloud`.`ip4_guest_subnet_network_map` m
+ JOIN `cloud`.`networks` n ON n.id = m.network_id
+ SET m.data_center_id = n.data_center_id
+WHERE m.data_center_id IS NULL;
+
+CALL
`cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`('cloud.ip4_guest_subnet_network_map',
'fk_ip4_guest_subnet_network_map__data_center_id', '(`data_center_id`)',
'`data_center`(`id`)');
diff --git
a/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java
b/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java
index ee888a61adc..3befa9d6431 100644
---
a/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java
+++
b/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java
@@ -109,7 +109,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements
RoutedIpv4Manager {
@@ -519,12 +518,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (zoneId != null) {
- List<DataCenterIpv4GuestSubnetVO> subnets =
dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId);
- if (CollectionUtils.isEmpty(subnets)) {
- return new ArrayList<>();
- }
- List<Long> parentIds =
subnets.stream().map(DataCenterIpv4GuestSubnetVO::getId).collect(Collectors.toList());
- sc.addAnd("parentId", SearchCriteria.Op.IN, parentIds.toArray());
+ sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
}
if (parentId != null) {
sc.addAnd("parentId", SearchCriteria.Op.EQ, parentId);
@@ -554,7 +548,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
response.setState(subnet.getState().name());
response.setId(subnet.getUuid());
response.setAllocatedTime(subnet.getAllocated());
- Long zoneId = null;
+ Long zoneId = subnet.getDataCenterId();
if (subnet.getNetworkId() != null) {
Network network =
ApiDBUtils.findNetworkById(subnet.getNetworkId());
response.setNetworkId(network.getUuid());
@@ -650,7 +644,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
}
protected void getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(String
networkCidr, Long ownerDomainId, Long ownerAccountId, Long zoneId) {
- Ipv4GuestSubnetNetworkMapVO subnetMap =
ipv4GuestSubnetNetworkMapDao.findBySubnet(networkCidr);
+ Ipv4GuestSubnetNetworkMapVO subnetMap =
ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(networkCidr, zoneId);
if (subnetMap != null) {
// check if the subnet is in use
if (subnetMap.getNetworkId() != null || subnetMap.getVpcId() !=
null) {
@@ -672,7 +666,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
// Create new record without networkId
final Long parentId = parent != null ? parent.getId() : null;
- subnetMap = new Ipv4GuestSubnetNetworkMapVO(parentId,
NetUtils.transformCidr(networkCidr), null, State.Free);
+ subnetMap = new Ipv4GuestSubnetNetworkMapVO(parentId, zoneId,
NetUtils.transformCidr(networkCidr), null, State.Free);
ipv4GuestSubnetNetworkMapDao.persist(subnetMap);
}
@@ -698,7 +692,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
}
}
// check conflicts
- List<Ipv4GuestSubnetNetworkMapVO> subnetsForNetworkNoParents =
ipv4GuestSubnetNetworkMapDao.listAllNoParent();
+ List<Ipv4GuestSubnetNetworkMapVO> subnetsForNetworkNoParents =
ipv4GuestSubnetNetworkMapDao.listAllNoParentByDataCenterId(zoneId);
checkConflicts(subnetsForNetworkNoParents, networkCidr);
return null;
}
@@ -730,7 +724,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
protected Ipv4GuestSubnetNetworkMap
createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, Integer
networkCidrSize) {
String networkCidr = createIpv4SubnetStringFromParentSubnet(parent,
networkCidrSize);
// create DB record
- Ipv4GuestSubnetNetworkMapVO subnetMap = new
Ipv4GuestSubnetNetworkMapVO(parent.getId(),
NetUtils.transformCidr(networkCidr), null, State.Free);
+ Ipv4GuestSubnetNetworkMapVO subnetMap = new
Ipv4GuestSubnetNetworkMapVO(parent.getId(), parent.getDataCenterId(),
NetUtils.transformCidr(networkCidr), null, State.Free);
return ipv4GuestSubnetNetworkMapDao.persist(subnetMap);
}
@@ -767,19 +761,19 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
}
// Allocate a subnet automatically
- String networkCidr = getFreeNetworkCidr(subnetsInFreeIpRanges,
networkCidrSize);
+ String networkCidr = getFreeNetworkCidr(subnetsInFreeIpRanges,
networkCidrSize, parent.getDataCenterId());
if (networkCidr == null) {
throw new InvalidParameterValueException("Failed to automatically
allocate a subnet with specified cidrsize");
}
return networkCidr;
}
- private String getFreeNetworkCidr(List<Pair<Long, Integer>>
subnetsInFreeIpRanges, int networkCidrSize) {
+ private String getFreeNetworkCidr(List<Pair<Long, Integer>>
subnetsInFreeIpRanges, int networkCidrSize, Long dataCenterId) {
for (int cidrSize = networkCidrSize; cidrSize >= 1; cidrSize--) {
for (Pair<Long, Integer> freeSubnet : subnetsInFreeIpRanges) {
if (freeSubnet.second().equals(cidrSize)) {
String networkCidr = String.format("%s/%s",
NetUtils.long2Ip(freeSubnet.first()), networkCidrSize);
- if (ipv4GuestSubnetNetworkMapDao.findBySubnet(networkCidr)
== null) {
+ if
(ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(networkCidr,
dataCenterId) == null) {
return networkCidr;
}
}
@@ -798,7 +792,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
checkConflicts(existingSubnets, networkCidr);
// create DB record
- Ipv4GuestSubnetNetworkMapVO subnetMap = new
Ipv4GuestSubnetNetworkMapVO(parent.getId(),
NetUtils.transformCidr(networkCidr), null, State.Free);
+ Ipv4GuestSubnetNetworkMapVO subnetMap = new
Ipv4GuestSubnetNetworkMapVO(parent.getId(), parent.getDataCenterId(),
NetUtils.transformCidr(networkCidr), null, State.Free);
return ipv4GuestSubnetNetworkMapDao.persist(subnetMap);
}
@@ -807,7 +801,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
if (network == null || network.getCidr() == null) {
return;
}
- Ipv4GuestSubnetNetworkMapVO subnetMap =
ipv4GuestSubnetNetworkMapDao.findBySubnet(network.getCidr());
+ Ipv4GuestSubnetNetworkMapVO subnetMap =
ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(network.getCidr(),
network.getDataCenterId());
if (subnetMap != null) {
if (network.getId() > 0L) {
subnetMap.setNetworkId(network.getId());
@@ -823,7 +817,7 @@ public class RoutedIpv4ManagerImpl extends
ComponentLifecycleBase implements Rou
if (vpc == null || vpc.getCidr() == null) {
return;
}
- Ipv4GuestSubnetNetworkMapVO subnetMap =
ipv4GuestSubnetNetworkMapDao.findBySubnet(vpc.getCidr());
+ Ipv4GuestSubnetNetworkMapVO subnetMap =
ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(vpc.getCidr(),
vpc.getZoneId());
if (subnetMap != null) {
if (vpc != null && vpc.getId() > 0L) {
subnetMap.setVpcId(vpc.getId());
diff --git
a/server/src/test/java/org/apache/cloudstack/network/RoutedIpv4ManagerImplTest.java
b/server/src/test/java/org/apache/cloudstack/network/RoutedIpv4ManagerImplTest.java
index 81110dd3f53..9f2c8eaab97 100644
---
a/server/src/test/java/org/apache/cloudstack/network/RoutedIpv4ManagerImplTest.java
+++
b/server/src/test/java/org/apache/cloudstack/network/RoutedIpv4ManagerImplTest.java
@@ -52,6 +52,7 @@ import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserVO;
+import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
@@ -60,6 +61,7 @@ import
org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForZoneCm
import
org.apache.cloudstack.api.command.admin.network.DedicateIpv4SubnetForZoneCmd;
import
org.apache.cloudstack.api.command.admin.network.DeleteIpv4SubnetForGuestNetworkCmd;
import
org.apache.cloudstack.api.command.admin.network.DeleteIpv4SubnetForZoneCmd;
+import
org.apache.cloudstack.api.command.admin.network.ListIpv4SubnetsForGuestNetworkCmd;
import
org.apache.cloudstack.api.command.admin.network.ReleaseDedicatedIpv4SubnetForZoneCmd;
import
org.apache.cloudstack.api.command.admin.network.UpdateIpv4SubnetForZoneCmd;
import
org.apache.cloudstack.api.command.admin.network.bgp.ChangeBgpPeersForNetworkCmd;
@@ -89,6 +91,7 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -496,9 +499,46 @@ public class RoutedIpv4ManagerImplTest {
Assert.assertEquals("ipv4subnetforguestnetwork",
response.getObjectName());
}
+ @Test
+ public void
testCreateIpv4SubnetForGuestNetworkResponseWithoutParentOrOwner() {
+ when(ipv4GuestSubnetNetworkMap.getSubnet()).thenReturn(subnet);
+
when(ipv4GuestSubnetNetworkMap.getState()).thenReturn(ipv4GuestSubnetNetworkMapState);
+ when(ipv4GuestSubnetNetworkMap.getDataCenterId()).thenReturn(zoneId);
+ when(ipv4GuestSubnetNetworkMap.getNetworkId()).thenReturn(null);
+ when(ipv4GuestSubnetNetworkMap.getVpcId()).thenReturn(null);
+ when(ipv4GuestSubnetNetworkMap.getParentId()).thenReturn(null);
+ apiDBUtilsMocked.when(() ->
ApiDBUtils.findZoneById(zoneId)).thenReturn(zone);
+ when(zone.getName()).thenReturn(zoneName);
+ when(zone.getUuid()).thenReturn(zoneUuid);
+
+ Ipv4SubnetForGuestNetworkResponse response =
routedIpv4Manager.createIpv4SubnetForGuestNetworkResponse(ipv4GuestSubnetNetworkMap);
+
+ // the subnet has no parent, network or VPC, so the zone can only come
from the subnet itself
+ Assert.assertEquals(zoneUuid, response.getZoneId());
+ Assert.assertEquals(zoneName, response.getZoneName());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testListIpv4GuestSubnetsForGuestNetworkByZone() {
+ ListIpv4SubnetsForGuestNetworkCmd cmd =
Mockito.mock(ListIpv4SubnetsForGuestNetworkCmd.class);
+ when(cmd.getZoneId()).thenReturn(zoneId);
+ SearchCriteria<Ipv4GuestSubnetNetworkMapVO> sc =
Mockito.mock(SearchCriteria.class);
+
when(ipv4GuestSubnetNetworkMapDao.createSearchCriteria()).thenReturn(sc);
+ when(ipv4GuestSubnetNetworkMapDao.search(sc,
null)).thenReturn(Arrays.asList(ipv4GuestSubnetNetworkMap));
+
+ List<Ipv4GuestSubnetNetworkMap> result =
routedIpv4Manager.listIpv4GuestSubnetsForGuestNetwork(cmd);
+
+ Assert.assertEquals(1, result.size());
+ verify(sc).addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
+ // the zone is taken from the subnet itself, not resolved through the
zone's parent subnets,
+ // so subnets created without a zone subnet are no longer missing from
the result
+ verify(dataCenterIpv4GuestSubnetDao,
Mockito.never()).listByDataCenterId(Mockito.anyLong());
+ }
+
@Test
public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidr1()
{
-
when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(subnet,
zoneId)).thenReturn(ipv4GuestSubnetNetworkMap);
when(ipv4GuestSubnetNetworkMap.getNetworkId()).thenReturn(null);
when(ipv4GuestSubnetNetworkMap.getVpcId()).thenReturn(null);
when(ipv4GuestSubnetNetworkMap.getParentId()).thenReturn(zoneSubnetId);
@@ -511,7 +551,7 @@ public class RoutedIpv4ManagerImplTest {
@Test
public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidr2()
{
-
when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(null);
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(subnet,
zoneId)).thenReturn(null);
routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(subnet,
domainId, accountId, zoneId);
@@ -520,7 +560,7 @@ public class RoutedIpv4ManagerImplTest {
@Test
public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidr3()
{
-
when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(null);
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(subnet,
zoneId)).thenReturn(null);
when(routedIpv4Manager.getParentOfNetworkCidr(zoneId,
subnet)).thenReturn(subnetVO);
when(subnetVO.getDomainId()).thenReturn(domainId);
when(subnetVO.getAccountId()).thenReturn(accountId);
@@ -530,6 +570,20 @@ public class RoutedIpv4ManagerImplTest {
verify(ipv4GuestSubnetNetworkMapDao).persist(any(Ipv4GuestSubnetNetworkMapVO.class));
}
+ @Test
+ public void
testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidrInAnotherZone() {
+ Long otherZoneId = zoneId + 1L;
+ // The same subnet is already allocated in another zone, which must
not block this zone
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(subnet,
otherZoneId)).thenReturn(null);
+
+
routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(subnet,
domainId, accountId, otherZoneId);
+
+ ArgumentCaptor<Ipv4GuestSubnetNetworkMapVO> captor =
ArgumentCaptor.forClass(Ipv4GuestSubnetNetworkMapVO.class);
+ verify(ipv4GuestSubnetNetworkMapDao).persist(captor.capture());
+ Assert.assertEquals(otherZoneId, captor.getValue().getDataCenterId());
+ Assert.assertEquals(subnet, captor.getValue().getSubnet());
+ }
+
@Test
public void
testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidrSize1() {
Ipv4GuestSubnetNetworkMap result =
routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(cidrSize,
domainId, accountId, zoneId);
@@ -629,8 +683,8 @@ public class RoutedIpv4ManagerImplTest {
when(subnetVO.getId()).thenReturn(zoneSubnetId);
when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
- Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap1 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.0/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
- Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap2 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.64/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap1 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, zoneId, "172.16.1.0/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap2 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, zoneId, "172.16.1.64/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
when(ipv4GuestSubnetNetworkMapDao.listByParent(zoneSubnetId)).thenReturn(Arrays.asList(ipv4GuestSubnetNetworkMap1,
ipv4GuestSubnetNetworkMap2));
when(subnetVO.getSubnet()).thenReturn("172.16.1.0/24");
@@ -643,8 +697,8 @@ public class RoutedIpv4ManagerImplTest {
networkCidr =
routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 25);
Assert.assertEquals("172.16.1.128/25", networkCidr);
- Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap3 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.16/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
- Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap4 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.128/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap3 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, zoneId, "172.16.1.16/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap4 = new
Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, zoneId, "172.16.1.128/28", null,
Ipv4GuestSubnetNetworkMap.State.Free);
when(ipv4GuestSubnetNetworkMapDao.listByParent(zoneSubnetId)).thenReturn(Arrays.asList(ipv4GuestSubnetNetworkMap1,
ipv4GuestSubnetNetworkMap2,
ipv4GuestSubnetNetworkMap3, ipv4GuestSubnetNetworkMap4));
networkCidr =
routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 28);
@@ -665,7 +719,8 @@ public class RoutedIpv4ManagerImplTest {
public void testAssignIpv4SubnetToNetwork() {
when(network.getId()).thenReturn(networkId);
when(network.getCidr()).thenReturn(subnet);
-
when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(network.getDataCenterId()).thenReturn(zoneId);
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(subnet,
zoneId)).thenReturn(ipv4GuestSubnetNetworkMap);
when(ipv4GuestSubnetNetworkMap.getId()).thenReturn(ipv4GuestSubnetNetworkMapId);
routedIpv4Manager.assignIpv4SubnetToNetwork(network);
@@ -677,7 +732,8 @@ public class RoutedIpv4ManagerImplTest {
public void testAssignIpv4SubnetToVpc() {
when(vpc.getId()).thenReturn(vpcId);
when(vpc.getCidr()).thenReturn(subnet);
-
when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(vpc.getZoneId()).thenReturn(zoneId);
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnetAndDataCenterId(subnet,
zoneId)).thenReturn(ipv4GuestSubnetNetworkMap);
when(ipv4GuestSubnetNetworkMap.getId()).thenReturn(ipv4GuestSubnetNetworkMapId);
routedIpv4Manager.assignIpv4SubnetToVpc(vpc);