Skip to content

Commit d95452e

Browse files
committed
Make vpc.max.networks dynamic and return a clear error at the limit
1 parent f03cffc commit d95452e

4 files changed

Lines changed: 37 additions & 10 deletions

File tree

‎engine/components-api/src/main/java/com/cloud/network/vpc/VpcManager.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ public interface VpcManager {
5757
true,
5858
ConfigKey.Scope.Global,
5959
null);
60+
ConfigKey<Integer> VpcMaxNetworks = new ConfigKey<>("Advanced",
61+
Integer.class,
62+
"vpc.max.networks",
63+
"3",
64+
"Maximum number of networks per VPC",
65+
true,
66+
ConfigKey.Scope.Global);
6067

6168
/**
6269
* Returns all the Guest networks that are part of VPC

‎server/src/main/java/com/cloud/configuration/Config.java‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,6 @@ public enum Config {
14961496
"3600",
14971497
"The interval (in seconds) between cleanup for Inactive VPCs",
14981498
null),
1499-
VpcMaxNetworks("Advanced", ManagementServer.class, Integer.class, "vpc.max.networks", "3", "Maximum number of networks per vpc", null),
15001499
DetailBatchQuerySize("Advanced", ManagementServer.class, Integer.class, "detail.batch.query.size", "2000", "Default entity detail batch query size for listing", null),
15011500
NetworkIPv6SearchRetryMax(
15021501
"Network",

‎server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,6 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
341341
Provider.JuniperContrailVpcRouter, Provider.Ovs, Provider.BigSwitchBcf, Provider.ConfigDrive, Provider.Nsx, Provider.Netris);
342342

343343
int _cleanupInterval;
344-
int _maxNetworks;
345344
SearchBuilder<IPAddressVO> IpAddressSearch;
346345

347346
protected final List<HypervisorType> hTypes = new ArrayList<HypervisorType>();
@@ -517,9 +516,6 @@ public void doInTransactionWithoutResult(final TransactionStatus status) {
517516
final String value = configs.get(Config.VpcCleanupInterval.key());
518517
_cleanupInterval = NumbersUtil.parseInt(value, 60 * 60); // 1 hour
519518

520-
final String maxNtwks = configs.get(Config.VpcMaxNetworks.key());
521-
_maxNetworks = NumbersUtil.parseInt(maxNtwks, 3); // max=3 is default
522-
523519
IpAddressSearch = _ipAddressDao.createSearchBuilder();
524520
IpAddressSearch.and("accountId", IpAddressSearch.entity().getAllocatedToAccountId(), Op.EQ);
525521
IpAddressSearch.and("dataCenterId", IpAddressSearch.entity().getDataCenterId(), Op.EQ);
@@ -2580,9 +2576,12 @@ public void doInTransactionWithoutResult(final TransactionStatus status) {
25802576

25812577
try {
25822578
// check number of active networks in vpc
2583-
if (_ntwkDao.countVpcNetworks(vpc.getId()) >= _maxNetworks) {
2584-
logger.warn(String.format("Failed to create a new VPC Guest Network because the number of networks per VPC has reached its maximum capacity of [%s]. Increase it by modifying global config [%s].", _maxNetworks, Config.VpcMaxNetworks));
2585-
throw new CloudRuntimeException(String.format("Number of networks per VPC cannot surpass [%s].", _maxNetworks));
2579+
final int maxNetworks = VpcMaxNetworks.value();
2580+
if (_ntwkDao.countVpcNetworks(vpc.getId()) >= maxNetworks) {
2581+
logger.warn("Failed to create a new network in VPC [{}] because it has reached the maximum of [{}] networks for {}. "
2582+
+ "Increase it by modifying the global setting [{}].", vpc, maxNetworks, _accountMgr.getAccount(vpc.getAccountId()), VpcMaxNetworks.key());
2583+
throw new InvalidParameterValueException(String.format("VPC %s has reached the maximum of %d networks. "
2584+
+ "Delete an unused network or contact your platform administrator to raise the limit.", vpc.getName(), maxNetworks));
25862585
}
25872586

25882587
// 1) CIDR is required
@@ -3721,7 +3720,8 @@ public String getConfigComponentName() {
37213720
public ConfigKey<?>[] getConfigKeys() {
37223721
return new ConfigKey<?>[]{
37233722
VpcTierNamePrepend,
3724-
VpcTierNamePrependDelimiter
3723+
VpcTierNamePrependDelimiter,
3724+
VpcMaxNetworks
37253725
};
37263726
}
37273727

‎server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import org.apache.cloudstack.extension.Extension;
7777
import org.apache.cloudstack.extension.ExtensionHelper;
7878
import org.apache.cloudstack.framework.config.ConfigKey;
79+
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
7980
import org.apache.cloudstack.network.Ipv4GuestSubnetNetworkMap;
8081
import org.apache.cloudstack.network.RoutedIpv4Manager;
8182
import org.junit.After;
@@ -362,7 +363,6 @@ protected Set<Network.Provider> prepareVpcManagerForCheckingCapabilityPerService
362363
@Test
363364
public void testCreateVpcNetwork() throws InsufficientCapacityException, ResourceAllocationException {
364365
final long VPC_ID = 201L;
365-
manager._maxNetworks = 3;
366366
VpcVO vpcMockVO = Mockito.mock(VpcVO.class);
367367
Vpc vpcMock = Mockito.mock(Vpc.class);
368368
Account accountMock = Mockito.mock(Account.class);
@@ -400,6 +400,27 @@ public void testCreateVpcNetwork() throws InsufficientCapacityException, Resourc
400400
null, null, null, null, null, new Pair<>(1000, 1000), null);
401401
}
402402

403+
@Test
404+
public void validateNewVpcGuestNetworkTestLimitReadFromDynamicSetting() {
405+
final long vpcId = 301L;
406+
Vpc vpcMock = Mockito.mock(Vpc.class);
407+
Mockito.when(vpcMock.getId()).thenReturn(vpcId);
408+
Mockito.when(vpcDao.acquireInLockTable(vpcId)).thenReturn(Mockito.mock(VpcVO.class));
409+
Mockito.when(networkDao.countVpcNetworks(vpcId)).thenReturn(2L);
410+
ConfigDepotImpl configDepot = Mockito.mock(ConfigDepotImpl.class);
411+
Mockito.when(configDepot.getConfigStringValue(VpcManager.VpcMaxNetworks.key(), ConfigKey.Scope.Global, null)).thenReturn("2");
412+
413+
Object originalDepot = ReflectionTestUtils.getField(VpcManager.VpcMaxNetworks, "s_depot");
414+
ReflectionTestUtils.setField(VpcManager.VpcMaxNetworks, "s_depot", configDepot);
415+
try {
416+
InvalidParameterValueException e = Assert.assertThrows(InvalidParameterValueException.class,
417+
() -> manager.validateNewVpcGuestNetwork("10.10.10.0/24", "10.10.10.1", Mockito.mock(Account.class), vpcMock, "cs1cloud.internal"));
418+
assertTrue(e.getMessage().contains("maximum of 2 networks"));
419+
} finally {
420+
ReflectionTestUtils.setField(VpcManager.VpcMaxNetworks, "s_depot", originalDepot);
421+
}
422+
}
423+
403424
@Test
404425
public void testUpdateVpcNetwork() throws ResourceUnavailableException, InsufficientCapacityException {
405426
long vpcId = 1L;

0 commit comments

Comments
 (0)