mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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:
parent
d4446ee09d
commit
646c894ec6
@ -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
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user