Fix for race when automatically assigning IP to Vms (#9240)

* Fix for race when automatically assigning IP to Vms

* code refactor
This commit is contained in:
Abhisar Sinha 2024-06-28 17:11:16 +05:30 committed by GitHub
parent d4446ee09d
commit 646c894ec6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 78 additions and 27 deletions

View File

@ -62,6 +62,7 @@ public class NicProfile implements InternalIdentity, Serializable {
String iPv4Dns1;
String iPv4Dns2;
String requestedIPv4;
boolean ipv4AllocationRaceCheck;
// IPv6
String iPv6Address;
@ -405,6 +406,13 @@ public class NicProfile implements InternalIdentity, Serializable {
this.mtu = mtu;
}
public boolean getIpv4AllocationRaceCheck() {
return this.ipv4AllocationRaceCheck;
}
public void setIpv4AllocationRaceCheck(boolean ipv4AllocationRaceCheck) {
this.ipv4AllocationRaceCheck = ipv4AllocationRaceCheck;
}
//
// OTHER METHODS

View File

@ -1020,42 +1020,84 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
}
private NicVO persistNicAfterRaceCheck(final NicVO nic, final Long networkId, final NicProfile profile, int deviceId) {
return Transaction.execute(new TransactionCallback<NicVO>() {
@Override
public NicVO doInTransaction(TransactionStatus status) {
NicVO vo = _nicDao.findByIp4AddressAndNetworkId(profile.getIPv4Address(), networkId);
if (vo == null) {
applyProfileToNic(nic, profile, deviceId);
vo = _nicDao.persist(nic);
return vo;
} else {
return null;
}
}
});
}
private NicVO checkForRaceAndAllocateNic(final NicProfile requested, final Network network, final Boolean isDefaultNic, int deviceId, final VirtualMachineProfile vm)
throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
final NetworkVO ntwkVO = _networksDao.findById(network.getId());
s_logger.debug("Allocating nic for vm " + vm.getVirtualMachine() + " in network " + network + " with requested profile " + requested);
final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, ntwkVO.getGuruName());
NicVO vo = null;
boolean retryIpAllocation;
do {
retryIpAllocation = false;
final NicProfile profile = guru.allocate(network, requested, vm);
if (profile == null) {
return null;
}
if (isDefaultNic != null) {
profile.setDefaultNic(isDefaultNic);
}
if (requested != null && requested.getMode() == null) {
profile.setMode(requested.getMode());
} else {
profile.setMode(network.getMode());
}
vo = new NicVO(guru.getName(), vm.getId(), network.getId(), vm.getType());
DataCenterVO dcVo = _dcDao.findById(network.getDataCenterId());
if (dcVo.getNetworkType() == NetworkType.Basic) {
configureNicProfileBasedOnRequestedIp(requested, profile, network);
}
if (profile.getIpv4AllocationRaceCheck()) {
vo = persistNicAfterRaceCheck(vo, network.getId(), profile, deviceId);
} else {
applyProfileToNic(vo, profile, deviceId);
vo = _nicDao.persist(vo);
}
if (vo == null) {
if (requested.getRequestedIPv4() != null) {
throw new InsufficientVirtualNetworkCapacityException("Unable to acquire requested Guest IP address " + requested.getRequestedIPv4() + " for network " + network, DataCenter.class, dcVo.getId());
} else {
requested.setIPv4Address(null);
}
retryIpAllocation = true;
}
} while (retryIpAllocation);
return vo;
}
@DB
@Override
public Pair<NicProfile, Integer> allocateNic(final NicProfile requested, final Network network, final Boolean isDefaultNic, int deviceId, final VirtualMachineProfile vm)
throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException, ConcurrentOperationException {
final NetworkVO ntwkVO = _networksDao.findById(network.getId());
s_logger.debug("Allocating nic for vm " + vm.getVirtualMachine() + " in network " + network + " with requested profile " + requested);
final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, ntwkVO.getGuruName());
if (requested != null && requested.getMode() == null) {
requested.setMode(network.getMode());
}
final NicProfile profile = guru.allocate(network, requested, vm);
if (profile == null) {
return null;
}
if (isDefaultNic != null) {
profile.setDefaultNic(isDefaultNic);
}
if (requested != null && requested.getMode() == null) {
profile.setMode(requested.getMode());
} else {
profile.setMode(network.getMode());
}
NicVO vo = new NicVO(guru.getName(), vm.getId(), network.getId(), vm.getType());
DataCenterVO dcVo = _dcDao.findById(network.getDataCenterId());
if (dcVo.getNetworkType() == NetworkType.Basic) {
configureNicProfileBasedOnRequestedIp(requested, profile, network);
}
deviceId = applyProfileToNic(vo, profile, deviceId);
vo = _nicDao.persist(vo);
NicVO vo = checkForRaceAndAllocateNic(requested, network, isDefaultNic, deviceId, vm);
final Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId());
final NicProfile vmNic = new NicProfile(vo, network, vo.getBroadcastUri(), vo.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network),

View File

@ -441,6 +441,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur
} else {
guestIp = _ipAddrMgr.acquireGuestIpAddress(network, nic.getRequestedIPv4());
}
nic.setIpv4AllocationRaceCheck(true);
}
if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP" + " address for network " + network, DataCenter.class,