Enforce distinct hostnames network (#10212)

* Check for unique hostnames for all networks in the vpc

* Address comments
This commit is contained in:
Vishesh 2025-10-13 12:38:31 +05:30 committed by GitHub
parent cc6ee906d5
commit 0b9afe77ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 125 additions and 14 deletions

View File

@ -18,6 +18,7 @@ package com.cloud.network.dao;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.cloud.network.Network;
import com.cloud.network.Network.GuestType;
@ -47,6 +48,12 @@ public interface NetworkDao extends GenericDao<NetworkVO, Long>, StateDao<State,
int getOtherPersistentNetworksCount(long id, String broadcastURI, boolean isPersistent);
List<NetworkVO> listByNetworkDomains(Set<String> uniqueNtwkDomains);
List<NetworkVO> listByNetworkDomainsAndAccountIds(Set<String> uniqueNtwkDomains, Set<Long> accountIds);
List<NetworkVO> listByNetworkDomainsAndDomainIds(Set<String> uniqueNtwkDomains, Set<Long> domainIds);
/**
* Retrieves the next available mac address in this network configuration.
*

View File

@ -86,6 +86,7 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long>implements Ne
GenericSearchBuilder<NetworkVO, Long> GarbageCollectedSearch;
SearchBuilder<NetworkVO> PrivateNetworkSearch;
SearchBuilder<NetworkVO> NetworkDomainSearch;
@Inject
ResourceTagDao _tagsDao;
@ -198,6 +199,12 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long>implements Ne
PersistentNetworkSearch.join("persistent", persistentNtwkOffJoin, PersistentNetworkSearch.entity().getNetworkOfferingId(), persistentNtwkOffJoin.entity().getId(), JoinType.INNER);
PersistentNetworkSearch.done();
NetworkDomainSearch = createSearchBuilder();
NetworkDomainSearch.and("networkDomains", NetworkDomainSearch.entity().getNetworkDomain(), Op.IN);
NetworkDomainSearch.and("accounts", NetworkDomainSearch.entity().getAccountId(), Op.IN);
NetworkDomainSearch.and("domains", NetworkDomainSearch.entity().getDomainId(), Op.IN);
NetworkDomainSearch.done();
PhysicalNetworkSearch = createSearchBuilder();
PhysicalNetworkSearch.and("physicalNetworkId", PhysicalNetworkSearch.entity().getPhysicalNetworkId(), Op.EQ);
PhysicalNetworkSearch.done();
@ -428,6 +435,29 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long>implements Ne
return search(sc, null);
}
@Override
public List<NetworkVO> listByNetworkDomains(Set<String> uniqueNtwkDomains) {
SearchCriteria<NetworkVO> sc = NetworkDomainSearch.create();
sc.setParameters("networkDomains", uniqueNtwkDomains.toArray());
return search(sc, null);
}
@Override
public List<NetworkVO> listByNetworkDomainsAndAccountIds(Set<String> uniqueNtwkDomains, Set<Long> accountIds) {
SearchCriteria<NetworkVO> sc = NetworkDomainSearch.create();
sc.setParameters("networkDomains", uniqueNtwkDomains.toArray());
sc.setParameters("accounts", accountIds.toArray());
return search(sc, null);
}
@Override
public List<NetworkVO> listByNetworkDomainsAndDomainIds(Set<String> uniqueNtwkDomains, Set<Long> domainIds) {
SearchCriteria<NetworkVO> sc = NetworkDomainSearch.create();
sc.setParameters("networkDomains", uniqueNtwkDomains.toArray());
sc.setParameters("domains", domainIds.toArray());
return search(sc, null);
}
@Override
public String getNextAvailableMacAddress(final long networkConfigId, Integer zoneMacIdentifier) {
final SequenceFetcher fetch = SequenceFetcher.getInstance();

View File

@ -83,6 +83,12 @@ public interface UserVmManager extends UserVmService {
"If set to true, tags specified in `resource.limit.host.tags` are also included in vm.strict.host.tags.",
true);
ConfigKey<String> VmDistinctHostNameScope = new ConfigKey<>(String.class, "vm.distinct.hostname.scope", ConfigKey.CATEGORY_ADVANCED,
"network",
"Defines the scope for enforcing unique VM hostnames which determines the resource boundary within which VM hostnames must be unique. Possible values: global, domain, subdomain, account, network.",
true, ConfigKey.Scope.Global, null, "VM distinct hostname scope", null, null, null, ConfigKey.Kind.Select,
"global,domain,subdomain,account,network");
ConfigKey<Boolean> EnableAdditionalVmConfig = new ConfigKey<>(
"Advanced",
Boolean.class,
@ -92,6 +98,7 @@ public interface UserVmManager extends UserVmService {
true,
ConfigKey.Scope.Account);
static final int MAX_USER_DATA_LENGTH_BYTES = 2048;
public static final String CKS_NODE = "cksnode";

View File

@ -4698,23 +4698,75 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
}
private void checkIfHostNameUniqueInNtwkDomain(String hostName, List<? extends Network> networkList) {
// Check that hostName is unique in the network domain
Map<String, List<Long>> ntwkDomains = new HashMap<String, List<Long>>();
private List<NetworkVO> getNetworksWithSameNetworkDomainInDomains(List<NetworkVO> networkList, boolean checkSubDomains) {
Set<String> uniqueNtwkDomains = networkList.stream().map(NetworkVO::getNetworkDomain).collect(Collectors.toSet());
Set<Long> domainIdList = new HashSet<>();
for (Network network : networkList) {
String ntwkDomain = network.getNetworkDomain();
if (!ntwkDomains.containsKey(ntwkDomain)) {
List<Long> ntwkIds = new ArrayList<Long>();
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
} else {
List<Long> ntwkIds = ntwkDomains.get(ntwkDomain);
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
domainIdList.add(network.getDomainId());
}
Set<Long> finalDomainIdSet = new HashSet<>(domainIdList);
if (checkSubDomains) {
for (Long domainId : domainIdList) {
DomainVO domain = _domainDao.findById(domainId);
List<Long> childDomainIds = _domainDao.getDomainChildrenIds(domain.getPath());
finalDomainIdSet.addAll(childDomainIds);
}
}
return _networkDao.listByNetworkDomainsAndDomainIds(uniqueNtwkDomains, finalDomainIdSet);
}
for (Entry<String, List<Long>> ntwkDomain : ntwkDomains.entrySet()) {
private List<NetworkVO> getNetworksForCheckUniqueHostName(List<NetworkVO> networkList) {
List<NetworkVO> finalNetworkList;
Set<String> uniqueNtwkDomains;
switch (VmDistinctHostNameScope.value()) {
case "global":
uniqueNtwkDomains = networkList.stream().map(NetworkVO::getNetworkDomain).collect(Collectors.toSet());
finalNetworkList = _networkDao.listByNetworkDomains(uniqueNtwkDomains);
break;
case "domain":
finalNetworkList = getNetworksWithSameNetworkDomainInDomains(networkList, false);
break;
case "subdomain":
finalNetworkList = getNetworksWithSameNetworkDomainInDomains(networkList, true);
break;
case "account":
uniqueNtwkDomains = networkList.stream().map(NetworkVO::getNetworkDomain).collect(Collectors.toSet());
Set<Long> accountIds = networkList.stream().map(Network::getAccountId).collect(Collectors.toSet());
finalNetworkList = _networkDao.listByNetworkDomainsAndAccountIds(uniqueNtwkDomains, accountIds);
break;
default:
Set<Long> vpcIds = networkList.stream().map(Network::getVpcId).filter(Objects::nonNull).collect(Collectors.toSet());
finalNetworkList = new ArrayList<>(networkList);
for (Long vpcId : vpcIds) {
finalNetworkList.addAll(_networkDao.listByVpc(vpcId));
}
break;
}
return finalNetworkList;
}
private Map<String, Set<Long>> getNetworkIdPerNetworkDomain(List<NetworkVO> networkList) {
Map<String, Set<Long>> ntwkDomains = new HashMap<>();
List<NetworkVO> updatedNetworkList = getNetworksForCheckUniqueHostName(networkList);
for (Network network : updatedNetworkList) {
String ntwkDomain = network.getNetworkDomain();
Set<Long> ntwkIds;
if (!ntwkDomains.containsKey(ntwkDomain)) {
ntwkIds = new HashSet<>();
} else {
ntwkIds = ntwkDomains.get(ntwkDomain);
}
ntwkIds.add(network.getId());
ntwkDomains.put(ntwkDomain, ntwkIds);
}
return ntwkDomains;
}
private void checkIfHostNameUniqueInNtwkDomain(String hostName, List<NetworkVO> networkList) {
// Check that hostName is unique
Map<String, Set<Long>> ntwkDomains = getNetworkIdPerNetworkDomain(networkList);
for (Entry<String, Set<Long>> ntwkDomain : ntwkDomains.entrySet()) {
for (Long ntwkId : ntwkDomain.getValue()) {
// * get all vms hostNames in the network
List<String> hostNames = _vmInstanceDao.listDistinctHostNames(ntwkId);
@ -9284,7 +9336,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return new ConfigKey<?>[] {EnableDynamicallyScaleVm, AllowDiskOfferingChangeDuringScaleVm, AllowUserExpungeRecoverVm, VmIpFetchWaitInterval, VmIpFetchTrialMax,
VmIpFetchThreadPoolMax, VmIpFetchTaskWorkers, AllowDeployVmIfGivenHostFails, EnableAdditionalVmConfig, DisplayVMOVFProperties,
KvmAdditionalConfigAllowList, XenServerAdditionalConfigAllowList, VmwareAdditionalConfigAllowList, DestroyRootVolumeOnVmDestruction,
EnforceStrictResourceLimitHostTagCheck, StrictHostTags, AllowUserForceStopVm};
EnforceStrictResourceLimitHostTagCheck, StrictHostTags, AllowUserForceStopVm, VmDistinctHostNameScope};
}
@Override

View File

@ -29,6 +29,7 @@ import com.cloud.utils.db.SearchBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@DB()
public class MockNetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements NetworkDao {
@ -265,4 +266,18 @@ public class MockNetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implemen
return null;
}
@Override
public List<NetworkVO> listByNetworkDomains(Set<String> uniqueNtwkDomains) {
return List.of();
}
@Override
public List<NetworkVO> listByNetworkDomainsAndAccountIds(Set<String> uniqueNtwkDomains, Set<Long> accountIds) {
return List.of();
}
@Override
public List<NetworkVO> listByNetworkDomainsAndDomainIds(Set<String> uniqueNtwkDomains, Set<Long> domainIds) {
return List.of();
}
}