Remove nic allocation txn during Vm deploy. During Vm deploy failure, this will allow cleanup of any nics that are successfully provisioned (#7809)

This commit is contained in:
kishankavala 2023-08-04 12:12:38 +05:30 committed by GitHub
parent b4032d9984
commit 57779a8586
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 143 additions and 147 deletions

View File

@ -831,169 +831,165 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
public void allocate(final VirtualMachineProfile vm, final LinkedHashMap<? extends Network, List<? extends NicProfile>> networks, final Map<String, Map<Integer, String>> extraDhcpOptions) throws InsufficientCapacityException, public void allocate(final VirtualMachineProfile vm, final LinkedHashMap<? extends Network, List<? extends NicProfile>> networks, final Map<String, Map<Integer, String>> extraDhcpOptions) throws InsufficientCapacityException,
ConcurrentOperationException { ConcurrentOperationException {
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<InsufficientCapacityException>() { if (s_logger.isTraceEnabled()) {
@Override s_logger.trace(String.format("allocating networks for %s(template %s); %d networks", vm.getInstanceName(), vm.getTemplate().getUuid(), networks.size()));
public void doInTransactionWithoutResult(final TransactionStatus status) throws InsufficientCapacityException { }
if (s_logger.isTraceEnabled()) { int deviceId = 0;
s_logger.trace(String.format("allocating networks for %s(template %s); %d networks", vm.getInstanceName(), vm.getTemplate().getUuid(), networks.size())); int size;
} size = determineNumberOfNicsRequired(vm, networks);
int deviceId = 0;
int size;
size = determineNumberOfNicsRequired();
final boolean[] deviceIds = new boolean[size]; final boolean[] deviceIds = new boolean[size];
Arrays.fill(deviceIds, false); Arrays.fill(deviceIds, false);
List<Pair<Network, NicProfile>> profilesList = getOrderedNetworkNicProfileMapping(networks); List<Pair<Network, NicProfile>> profilesList = getOrderedNetworkNicProfileMapping(networks);
final List<NicProfile> nics = new ArrayList<NicProfile>(size); final List<NicProfile> nics = new ArrayList<NicProfile>(size);
NicProfile defaultNic = null; NicProfile defaultNic = null;
Network nextNetwork = null; Network nextNetwork = null;
for (Pair<Network, NicProfile> networkNicPair : profilesList) { for (Pair<Network, NicProfile> networkNicPair : profilesList) {
nextNetwork = networkNicPair.first(); nextNetwork = networkNicPair.first();
Pair<NicProfile, Integer> newDeviceInfo = addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(networkNicPair.second(), deviceIds, deviceId, nextNetwork, nics, defaultNic); Pair<NicProfile, Integer> newDeviceInfo = addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(vm, extraDhcpOptions, networkNicPair.second(), deviceIds, deviceId, nextNetwork, nics, defaultNic);
defaultNic = newDeviceInfo.first(); defaultNic = newDeviceInfo.first();
deviceId = newDeviceInfo.second(); deviceId = newDeviceInfo.second();
} }
createExtraNics(size, nics, nextNetwork); createExtraNics(vm,size, nics, nextNetwork);
if (nics.size() == 1) { if (nics.size() == 1) {
nics.get(0).setDefaultNic(true); nics.get(0).setDefaultNic(true);
} }
} }
/** /**
* private transaction method to check and add devices to the nic list and update the info * Method to check and add devices to the nic list and update the info
*/ */
Pair<NicProfile, Integer> addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(NicProfile requested, boolean[] deviceIds, int deviceId, Network nextNetwork, List<NicProfile> nics, NicProfile defaultNic) private Pair<NicProfile, Integer> addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(VirtualMachineProfile vm, Map<String, Map<Integer, String>> extraDhcpOptions,
throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException { NicProfile requested, boolean[] deviceIds, int deviceId, Network nextNetwork, List<NicProfile> nics, NicProfile defaultNic)
Pair<NicProfile, Integer> rc = new Pair<>(null, null); throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException {
Boolean isDefaultNic = false; Pair<NicProfile, Integer> rc = new Pair<>(null, null);
if (vm != null && requested != null && requested.isDefaultNic()) { Boolean isDefaultNic = false;
isDefaultNic = true; if (vm != null && requested != null && requested.isDefaultNic()) {
} isDefaultNic = true;
}
while (deviceIds[deviceId] && deviceId < deviceIds.length) { while (deviceIds[deviceId] && deviceId < deviceIds.length) {
deviceId++; deviceId++;
} }
final Pair<NicProfile, Integer> vmNicPair = allocateNic(requested, nextNetwork, isDefaultNic, deviceId, vm); final Pair<NicProfile, Integer> vmNicPair = allocateNic(requested, nextNetwork, isDefaultNic, deviceId, vm);
NicProfile vmNic = null; NicProfile vmNic = null;
if (vmNicPair != null) { if (vmNicPair != null) {
vmNic = vmNicPair.first(); vmNic = vmNicPair.first();
if (vmNic == null) { if (vmNic == null) {
return rc;
}
deviceId = vmNicPair.second();
}
final int devId = vmNic.getDeviceId();
if (devId >= deviceIds.length) {
throw new IllegalArgumentException("Device id for nic is too large: " + vmNic);
}
if (deviceIds[devId]) {
throw new IllegalArgumentException("Conflicting device id for two different nics: " + vmNic);
}
deviceIds[devId] = true;
if (vmNic.isDefaultNic()) {
if (defaultNic != null) {
throw new IllegalArgumentException("You cannot specify two nics as default nics: nic 1 = " + defaultNic + "; nic 2 = " + vmNic);
}
defaultNic = vmNic;
}
nics.add(vmNic);
vm.addNic(vmNic);
saveExtraDhcpOptions(nextNetwork.getUuid(), vmNic.getId(), extraDhcpOptions);
rc.first(defaultNic);
rc.second(deviceId);
return rc; return rc;
} }
deviceId = vmNicPair.second();
}
/** final int devId = vmNic.getDeviceId();
* private transaction method to get oredered list of Network and NicProfile pair if (devId >= deviceIds.length) {
* @return ordered list of Network and NicProfile pair throw new IllegalArgumentException("Device id for nic is too large: " + vmNic);
* @param networks the map od networks to nic profiles list }
*/ if (deviceIds[devId]) {
private List<Pair<Network, NicProfile>> getOrderedNetworkNicProfileMapping(final LinkedHashMap<? extends Network, List<? extends NicProfile>> networks) { throw new IllegalArgumentException("Conflicting device id for two different nics: " + vmNic);
List<Pair<Network, NicProfile>> profilesList = new ArrayList<>(); }
for (final Map.Entry<? extends Network, List<? extends NicProfile>> network : networks.entrySet()) {
List<? extends NicProfile> requestedProfiles = network.getValue(); deviceIds[devId] = true;
if (requestedProfiles == null) {
requestedProfiles = new ArrayList<NicProfile>(); if (vmNic.isDefaultNic()) {
} if (defaultNic != null) {
if (requestedProfiles.isEmpty()) { throw new IllegalArgumentException("You cannot specify two nics as default nics: nic 1 = " + defaultNic + "; nic 2 = " + vmNic);
requestedProfiles.add(null);
}
for (final NicProfile requested : requestedProfiles) {
profilesList.add(new Pair<Network, NicProfile>(network.getKey(), requested));
}
}
profilesList.sort(new Comparator<Pair<Network, NicProfile>>() {
@Override
public int compare(Pair<Network, NicProfile> pair1, Pair<Network, NicProfile> pair2) {
int profile1Order = Integer.MAX_VALUE;
int profile2Order = Integer.MAX_VALUE;
if (pair1 != null && pair1.second() != null && pair1.second().getOrderIndex() != null) {
profile1Order = pair1.second().getOrderIndex();
}
if (pair2 != null && pair2.second() != null && pair2.second().getOrderIndex() != null) {
profile2Order = pair2.second().getOrderIndex();
}
return profile1Order - profile2Order;
}
});
return profilesList;
} }
defaultNic = vmNic;
}
/** nics.add(vmNic);
* private transaction method to run over the objects and determine nic requirements vm.addNic(vmNic);
* @return the total numer of nics required saveExtraDhcpOptions(nextNetwork.getUuid(), vmNic.getId(), extraDhcpOptions);
*/ rc.first(defaultNic);
private int determineNumberOfNicsRequired() { rc.second(deviceId);
int size = 0; return rc;
for (final Network ntwk : networks.keySet()) { }
final List<? extends NicProfile> profiles = networks.get(ntwk);
if (profiles != null && !profiles.isEmpty()) {
size = size + profiles.size();
} else {
size = size + 1;
}
}
List<OVFNetworkTO> netprereqs = templateDeployAsIsDetailsDao.listNetworkRequirementsByTemplateId(vm.getTemplate().getId()); /**
if (size < netprereqs.size()) { * Method to get oredered list of Network and NicProfile pair
size = netprereqs.size(); * @return ordered list of Network and NicProfile pair
} * @param networks the map od networks to nic profiles list
return size; */
private List<Pair<Network, NicProfile>> getOrderedNetworkNicProfileMapping(final LinkedHashMap<? extends Network, List<? extends NicProfile>> networks) {
List<Pair<Network, NicProfile>> profilesList = new ArrayList<>();
for (final Map.Entry<? extends Network, List<? extends NicProfile>> network : networks.entrySet()) {
List<? extends NicProfile> requestedProfiles = network.getValue();
if (requestedProfiles == null) {
requestedProfiles = new ArrayList<NicProfile>();
} }
if (requestedProfiles.isEmpty()) {
/** requestedProfiles.add(null);
* private transaction method to add nics as required }
* @param size the number needed for (final NicProfile requested : requestedProfiles) {
* @param nics the list of nics present profilesList.add(new Pair<Network, NicProfile>(network.getKey(), requested));
* @param finalNetwork the network to add the nics to }
* @throws InsufficientVirtualNetworkCapacityException great }
* @throws InsufficientAddressCapacityException also magnificent, as the name suggests profilesList.sort(new Comparator<Pair<Network, NicProfile>>() {
*/ @Override
private void createExtraNics(int size, List<NicProfile> nics, Network finalNetwork) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { public int compare(Pair<Network, NicProfile> pair1, Pair<Network, NicProfile> pair2) {
if (nics.size() != size) { int profile1Order = Integer.MAX_VALUE;
s_logger.warn("Number of nics " + nics.size() + " doesn't match number of requested nics " + size); int profile2Order = Integer.MAX_VALUE;
if (nics.size() > size) { if (pair1 != null && pair1.second() != null && pair1.second().getOrderIndex() != null) {
throw new CloudRuntimeException("Number of nics " + nics.size() + " doesn't match number of requested networks " + size); profile1Order = pair1.second().getOrderIndex();
} else {
if (finalNetwork == null) {
throw new CloudRuntimeException(String.format("can not assign network to %d remaining required NICs", size - nics.size()));
}
// create extra
for (int extraNicNum = nics.size(); extraNicNum < size; extraNicNum++) {
final Pair<NicProfile, Integer> vmNicPair = allocateNic(new NicProfile(), finalNetwork, false, extraNicNum, vm);
}
}
} }
if (pair2 != null && pair2.second() != null && pair2.second().getOrderIndex() != null) {
profile2Order = pair2.second().getOrderIndex();
}
return profile1Order - profile2Order;
} }
}); });
return profilesList;
}
/**
* private transaction method to run over the objects and determine nic requirements
* @return the total numer of nics required
*/
private int determineNumberOfNicsRequired(final VirtualMachineProfile vm, final LinkedHashMap<? extends Network, List<? extends NicProfile>> networks) {
int size = 0;
for (final Network ntwk : networks.keySet()) {
final List<? extends NicProfile> profiles = networks.get(ntwk);
if (profiles != null && !profiles.isEmpty()) {
size = size + profiles.size();
} else {
size = size + 1;
}
}
List<OVFNetworkTO> netprereqs = templateDeployAsIsDetailsDao.listNetworkRequirementsByTemplateId(vm.getTemplate().getId());
if (size < netprereqs.size()) {
size = netprereqs.size();
}
return size;
}
/**
* Method to add nics as required
* @param size the number needed
* @param nics the list of nics present
* @param finalNetwork the network to add the nics to
* @throws InsufficientVirtualNetworkCapacityException great
* @throws InsufficientAddressCapacityException also magnificent, as the name suggests
*/
private void createExtraNics(final VirtualMachineProfile vm, int size, List<NicProfile> nics, Network finalNetwork) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
if (nics.size() != size) {
s_logger.warn("Number of nics " + nics.size() + " doesn't match number of requested nics " + size);
if (nics.size() > size) {
throw new CloudRuntimeException("Number of nics " + nics.size() + " doesn't match number of requested networks " + size);
} else {
if (finalNetwork == null) {
throw new CloudRuntimeException(String.format("can not assign network to %d remaining required NICs", size - nics.size()));
}
// create extra
for (int extraNicNum = nics.size(); extraNicNum < size; extraNicNum++) {
final Pair<NicProfile, Integer> vmNicPair = allocateNic(new NicProfile(), finalNetwork, false, extraNicNum, vm);
}
}
}
} }
@Override @Override