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 2f3e128bcaa..82e13b5c5b8 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 class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra public void allocate(final VirtualMachineProfile vm, final LinkedHashMap> networks, final Map> extraDhcpOptions) throws InsufficientCapacityException, ConcurrentOperationException { - Transaction.execute(new TransactionCallbackWithExceptionNoReturn() { - @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> profilesList = getOrderedNetworkNicProfileMapping(networks); - final List nics = new ArrayList(size); - NicProfile defaultNic = null; - Network nextNetwork = null; - for (Pair networkNicPair : profilesList) { - nextNetwork = networkNicPair.first(); - Pair newDeviceInfo = addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(networkNicPair.second(), deviceIds, deviceId, nextNetwork, nics, defaultNic); - defaultNic = newDeviceInfo.first(); - deviceId = newDeviceInfo.second(); - } - createExtraNics(size, nics, nextNetwork); + List> profilesList = getOrderedNetworkNicProfileMapping(networks); + final List nics = new ArrayList(size); + NicProfile defaultNic = null; + Network nextNetwork = null; + for (Pair networkNicPair : profilesList) { + nextNetwork = networkNicPair.first(); + Pair 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 addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(NicProfile requested, boolean[] deviceIds, int deviceId, Network nextNetwork, List nics, NicProfile defaultNic) - throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException { - Pair 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 addRequestedNicToNicListWithDeviceNumberAndRetrieveDefaultDevice(VirtualMachineProfile vm, Map> extraDhcpOptions, + NicProfile requested, boolean[] deviceIds, int deviceId, Network nextNetwork, List nics, NicProfile defaultNic) + throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapacityException { + Pair 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 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 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> getOrderedNetworkNicProfileMapping(final LinkedHashMap> networks) { - List> profilesList = new ArrayList<>(); - for (final Map.Entry> network : networks.entrySet()) { - List requestedProfiles = network.getValue(); - if (requestedProfiles == null) { - requestedProfiles = new ArrayList(); - } - if (requestedProfiles.isEmpty()) { - requestedProfiles.add(null); - } - for (final NicProfile requested : requestedProfiles) { - profilesList.add(new Pair(network.getKey(), requested)); - } - } - profilesList.sort(new Comparator>() { - @Override - public int compare(Pair pair1, Pair 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 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 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> getOrderedNetworkNicProfileMapping(final LinkedHashMap> networks) { + List> profilesList = new ArrayList<>(); + for (final Map.Entry> network : networks.entrySet()) { + List requestedProfiles = network.getValue(); + if (requestedProfiles == null) { + requestedProfiles = new ArrayList(); } - - /** - * 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 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 vmNicPair = allocateNic(new NicProfile(), finalNetwork, false, extraNicNum, vm); - } - } + if (requestedProfiles.isEmpty()) { + requestedProfiles.add(null); + } + for (final NicProfile requested : requestedProfiles) { + profilesList.add(new Pair(network.getKey(), requested)); + } + } + profilesList.sort(new Comparator>() { + @Override + public int compare(Pair pair1, Pair 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> networks) { + int size = 0; + for (final Network ntwk : networks.keySet()) { + final List profiles = networks.get(ntwk); + if (profiles != null && !profiles.isEmpty()) { + size = size + profiles.size(); + } else { + size = size + 1; + } + } + + List 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 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 vmNicPair = allocateNic(new NicProfile(), finalNetwork, false, extraNicNum, vm); + } + } + } } @Override