Remove nic allocation txn during Vm deploy. During Vm deploy failure, this will allow cleanup of any nics that are successfully provisioned (#7809)
diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index 2f3e128..82e13b5 100644
--- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -831,169 +831,165 @@
public void allocate(final VirtualMachineProfile vm, final LinkedHashMap<? extends Network, List<? extends NicProfile>> networks, final Map<String, Map<Integer, String>> extraDhcpOptions) throws InsufficientCapacityException,
ConcurrentOperationException {
- Transaction.execute(new TransactionCallbackWithExceptionNoReturn<InsufficientCapacityException>() {
- @Override
- public void doInTransactionWithoutResult(final TransactionStatus status) throws InsufficientCapacityException {
- if (s_logger.isTraceEnabled()) {
- s_logger.trace(String.format("allocating networks for %s(template %s); %d networks", vm.getInstanceName(), vm.getTemplate().getUuid(), networks.size()));
- }
- int deviceId = 0;
- int size;
- size = determineNumberOfNicsRequired();
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace(String.format("allocating networks for %s(template %s); %d networks", vm.getInstanceName(), vm.getTemplate().getUuid(), networks.size()));
+ }
+ int deviceId = 0;
+ int size;
+ size = determineNumberOfNicsRequired(vm, networks);
- final boolean[] deviceIds = new boolean[size];
- Arrays.fill(deviceIds, false);
+ final boolean[] deviceIds = new boolean[size];
+ Arrays.fill(deviceIds, false);
- List<Pair<Network, NicProfile>> profilesList = getOrderedNetworkNicProfileMapping(networks);
- final List<NicProfile> nics = new ArrayList<NicProfile>(size);
- NicProfile defaultNic = null;
- Network nextNetwork = null;
- for (Pair<Network, NicProfile> networkNicPair : profilesList) {
- nextNetwork = networkNicPair.first();
- Pair<NicProfile, Integer> newDeviceInfo = addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(networkNicPair.second(), deviceIds, deviceId, nextNetwork, nics, defaultNic);
- defaultNic = newDeviceInfo.first();
- deviceId = newDeviceInfo.second();
- }
- createExtraNics(size, nics, nextNetwork);
+ List<Pair<Network, NicProfile>> profilesList = getOrderedNetworkNicProfileMapping(networks);
+ final List<NicProfile> nics = new ArrayList<NicProfile>(size);
+ NicProfile defaultNic = null;
+ Network nextNetwork = null;
+ for (Pair<Network, NicProfile> networkNicPair : profilesList) {
+ nextNetwork = networkNicPair.first();
+ Pair<NicProfile, Integer> newDeviceInfo = addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(vm, extraDhcpOptions, networkNicPair.second(), deviceIds, deviceId, nextNetwork, nics, defaultNic);
+ defaultNic = newDeviceInfo.first();
+ deviceId = newDeviceInfo.second();
+ }
+ createExtraNics(vm,size, nics, nextNetwork);
- if (nics.size() == 1) {
- nics.get(0).setDefaultNic(true);
- }
- }
+ if (nics.size() == 1) {
+ nics.get(0).setDefaultNic(true);
+ }
+ }
- /**
- * private transaction 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)
- throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException {
- Pair<NicProfile, Integer> rc = new Pair<>(null, null);
- Boolean isDefaultNic = false;
- if (vm != null && requested != null && requested.isDefaultNic()) {
- isDefaultNic = true;
- }
+ /**
+ * Method to check and add devices to the nic list and update the info
+ */
+ private Pair<NicProfile, Integer> addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(VirtualMachineProfile vm, Map<String, Map<Integer, String>> extraDhcpOptions,
+ NicProfile requested, boolean[] deviceIds, int deviceId, Network nextNetwork, List<NicProfile> nics, NicProfile defaultNic)
+ throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException {
+ Pair<NicProfile, Integer> rc = new Pair<>(null, null);
+ Boolean isDefaultNic = false;
+ if (vm != null && requested != null && requested.isDefaultNic()) {
+ isDefaultNic = true;
+ }
- while (deviceIds[deviceId] && deviceId < deviceIds.length) {
- deviceId++;
- }
+ while (deviceIds[deviceId] && deviceId < deviceIds.length) {
+ deviceId++;
+ }
- final Pair<NicProfile, Integer> vmNicPair = allocateNic(requested, nextNetwork, isDefaultNic, deviceId, vm);
- NicProfile vmNic = null;
- if (vmNicPair != null) {
- vmNic = vmNicPair.first();
- 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);
+ final Pair<NicProfile, Integer> vmNicPair = allocateNic(requested, nextNetwork, isDefaultNic, deviceId, vm);
+ NicProfile vmNic = null;
+ if (vmNicPair != null) {
+ vmNic = vmNicPair.first();
+ if (vmNic == null) {
return rc;
}
+ deviceId = vmNicPair.second();
+ }
- /**
- * private transaction method to get oredered list of Network and NicProfile pair
- * @return ordered list of Network and NicProfile pair
- * @param networks the map od networks to nic profiles list
- */
- 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);
- }
- 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;
+ 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;
+ }
- /**
- * private transaction method to run over the objects and determine nic requirements
- * @return the total numer of nics required
- */
- private int determineNumberOfNicsRequired() {
- 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;
- }
- }
+ nics.add(vmNic);
+ vm.addNic(vmNic);
+ saveExtraDhcpOptions(nextNetwork.getUuid(), vmNic.getId(), extraDhcpOptions);
+ rc.first(defaultNic);
+ rc.second(deviceId);
+ return rc;
+ }
- List<OVFNetworkTO> netprereqs = templateDeployAsIsDetailsDao.listNetworkRequirementsByTemplateId(vm.getTemplate().getId());
- if (size < netprereqs.size()) {
- size = netprereqs.size();
- }
- return size;
+ /**
+ * Method to get oredered list of Network and NicProfile pair
+ * @return ordered list of Network and NicProfile pair
+ * @param networks the map od networks to nic profiles list
+ */
+ 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>();
}
-
- /**
- * private transaction 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(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);
- }
- }
+ if (requestedProfiles.isEmpty()) {
+ 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;
+ }
+
+ /**
+ * 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