diff --git a/INSTALL.md b/INSTALL.md index 45173c1aa03..6fc022b03e3 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -136,7 +136,7 @@ To create rpms, install the following extra packages: # yum -y install rpm-build # yum -y install ws-commons-util - # yum -y instal gcc + # yum -y install gcc # yum -y install glibc-devel # yum -y install MySQL-python diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java index 78d427164bb..06c3a946ce8 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java @@ -129,7 +129,7 @@ public interface NetworkOrchestrationService { void cleanupNics(VirtualMachineProfile vm); - void expungeNics(VirtualMachineProfile vm); + void removeNics(VirtualMachineProfile vm); List getNicProfiles(VirtualMachine vm); 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 8a3c07238c3..aa904b36114 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 @@ -2301,10 +2301,10 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra } @Override - public void expungeNics(final VirtualMachineProfile vm) { - final List nics = _nicDao.listByVmIdIncludingRemoved(vm.getId()); + public void removeNics(final VirtualMachineProfile vm) { + final List nics = _nicDao.listByVmId(vm.getId()); for (final NicVO nic : nics) { - _nicDao.expunge(nic.getId()); + _nicDao.remove(nic.getId()); } } @@ -2545,8 +2545,11 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra && (ntwkOff.getGuestType() == GuestType.Shared || (ntwkOff.getGuestType() == GuestType.Isolated && !_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))); if (cidr == null && ip6Cidr == null && cidrRequired) { - throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask are required when create network of" + " type " + Network.GuestType.Shared - + " and network of type " + GuestType.Isolated + " with service " + Service.SourceNat.getName() + " disabled"); + if (ntwkOff.getGuestType() == GuestType.Shared) { + throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask are required when create network of" + " type " + Network.GuestType.Shared); + } else { + throw new InvalidParameterValueException("gateway/netmask are required when create network of" + " type " + GuestType.Isolated + " with service " + Service.SourceNat.getName() + " disabled"); + } } checkL2OfferingServices(ntwkOff); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 309e1ad057a..d6d078ea355 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -2247,8 +2247,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) { guest.setBootType(GuestDef.BootType.UEFI); guest.setBootMode(GuestDef.BootMode.LEGACY); + guest.setMachineType("q35"); if (StringUtils.isNotBlank(customParams.get(GuestDef.BootType.UEFI.toString())) && "secure".equalsIgnoreCase(customParams.get(GuestDef.BootType.UEFI.toString()))) { - guest.setMachineType("q35"); guest.setBootMode(GuestDef.BootMode.SECURE); // setting to secure mode } } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index cb985bd9ae6..cf01b8db340 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -2955,7 +2955,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q _accountMgr.checkAccess(caller, null, true, vmInstance); currentVmOffering = _srvOfferingDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); - sc.addAnd("id", SearchCriteria.Op.NEQ, currentVmOffering.getId()); + if (! currentVmOffering.isDynamic()) { + sc.addAnd("id", SearchCriteria.Op.NEQ, currentVmOffering.getId()); + } // 1. Only return offerings with the same storage type sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, currentVmOffering.isUseLocalStorage()); diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index cc31eac1d2a..286fe2ec903 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -24,8 +24,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -1736,8 +1736,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return null; } } else { - s_logger.error("UpdateVmNicIpCmd is not supported in this network..."); - return null; + throw new InvalidParameterValueException("UpdateVmNicIpCmd is not supported in L2 network"); } s_logger.debug("Updating IPv4 address of NIC " + nicVO + " to " + ipaddr + "/" + nicVO.getIPv4Netmask() + " with gateway " + nicVO.getIPv4Gateway()); @@ -6454,7 +6453,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir _securityGroupMgr.removeInstanceFromGroups(cmd.getVmId()); // cleanup the network for the oldOwner _networkMgr.cleanupNics(vmOldProfile); - _networkMgr.expungeNics(vmOldProfile); + _networkMgr.removeNics(vmOldProfile); // security groups will be recreated for the new account, when the // VM is started List networkList = new ArrayList(); @@ -6516,34 +6515,25 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir s_logger.debug("AssignVM: Basic zone, adding security groups no " + securityGroupIdList.size() + " to " + vm.getInstanceName()); } else { + Set applicableNetworks = new LinkedHashSet<>(); + Map requestedIPv4ForNics = new HashMap<>(); + Map requestedIPv6ForNics = new HashMap<>(); if (zone.isSecurityGroupEnabled()) { // advanced zone with security groups // cleanup the old security groups _securityGroupMgr.removeInstanceFromGroups(cmd.getVmId()); - - Set applicableNetworks = new HashSet(); - String requestedIPv4ForDefaultNic = null; - String requestedIPv6ForDefaultNic = null; // if networkIdList is null and the first network of vm is shared network, then keep it if possible if (networkIdList == null || networkIdList.isEmpty()) { NicVO defaultNicOld = _nicDao.findDefaultNicForVM(vm.getId()); if (defaultNicOld != null) { NetworkVO defaultNetworkOld = _networkDao.findById(defaultNicOld.getNetworkId()); - if (defaultNetworkOld != null && defaultNetworkOld.getGuestType() == Network.GuestType.Shared && defaultNetworkOld.getAclType() == ACLType.Domain) { - try { - _networkModel.checkNetworkPermissions(newAccount, defaultNetworkOld); - applicableNetworks.add(defaultNetworkOld); - requestedIPv4ForDefaultNic = defaultNicOld.getIPv4Address(); - requestedIPv6ForDefaultNic = defaultNicOld.getIPv6Address(); - s_logger.debug("AssignVM: use old shared network " + defaultNetworkOld.getName() + " with old ip " + requestedIPv4ForDefaultNic + " on default nic of vm:" + vm.getInstanceName()); - } catch (PermissionDeniedException e) { - s_logger.debug("AssignVM: the shared network on old default nic can not be applied to new account"); - } + if (canAccountUseNetwork(newAccount, defaultNetworkOld)) { + applicableNetworks.add(defaultNetworkOld); + requestedIPv4ForNics.put(defaultNetworkOld.getId(), defaultNicOld.getIPv4Address()); + requestedIPv6ForNics.put(defaultNetworkOld.getId(), defaultNicOld.getIPv6Address()); + s_logger.debug("AssignVM: use old shared network " + defaultNetworkOld.getName() + " with old ip " + defaultNicOld.getIPv4Address() + " on default nic of vm:" + vm.getInstanceName()); } } } - // cleanup the network for the oldOwner - _networkMgr.cleanupNics(vmOldProfile); - _networkMgr.expungeNics(vmOldProfile); if (networkIdList != null && !networkIdList.isEmpty()) { // add any additional networks @@ -6566,10 +6556,24 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } + + if (network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Domain) { + NicVO nicOld = _nicDao.findByNtwkIdAndInstanceId(network.getId(), vm.getId()); + if (nicOld != null) { + requestedIPv4ForNics.put(network.getId(), nicOld.getIPv4Address()); + requestedIPv6ForNics.put(network.getId(), nicOld.getIPv6Address()); + s_logger.debug("AssignVM: use old shared network " + network.getName() + " with old ip " + nicOld.getIPv4Address() + " on nic of vm:" + vm.getInstanceName()); + } + } + s_logger.debug("AssignVM: Added network " + network.getName() + " to vm " + vm.getId()); applicableNetworks.add(network); } } + // cleanup the network for the oldOwner + _networkMgr.cleanupNics(vmOldProfile); + _networkMgr.removeNics(vmOldProfile); + // add the new nics LinkedHashMap> networks = new LinkedHashMap>(); int toggle = 0; @@ -6578,11 +6582,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir NicProfile defaultNic = new NicProfile(); if (toggle == 0) { defaultNic.setDefaultNic(true); - defaultNic.setRequestedIPv4(requestedIPv4ForDefaultNic); - defaultNic.setRequestedIPv6(requestedIPv6ForDefaultNic); defaultNetwork = appNet; toggle++; } + + defaultNic.setRequestedIPv4(requestedIPv4ForNics.get(appNet.getId())); + defaultNic.setRequestedIPv6(requestedIPv6ForNics.get(appNet.getId())); networks.put(appNet, new ArrayList(Arrays.asList(defaultNic))); } @@ -6645,27 +6650,20 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (securityGroupIdList != null && !securityGroupIdList.isEmpty()) { throw new InvalidParameterValueException("Can't move vm with security groups; security group feature is not enabled in this zone"); } - Set applicableNetworks = new HashSet(); // if networkIdList is null and the first network of vm is shared network, then keep it if possible if (networkIdList == null || networkIdList.isEmpty()) { NicVO defaultNicOld = _nicDao.findDefaultNicForVM(vm.getId()); if (defaultNicOld != null) { NetworkVO defaultNetworkOld = _networkDao.findById(defaultNicOld.getNetworkId()); - if (defaultNetworkOld != null && defaultNetworkOld.getGuestType() == Network.GuestType.Shared && defaultNetworkOld.getAclType() == ACLType.Domain) { - try { - _networkModel.checkNetworkPermissions(newAccount, defaultNetworkOld); - applicableNetworks.add(defaultNetworkOld); - } catch (PermissionDeniedException e) { - s_logger.debug("AssignVM: the shared network on old default nic can not be applied to new account"); - } + if (canAccountUseNetwork(newAccount, defaultNetworkOld)) { + applicableNetworks.add(defaultNetworkOld); + requestedIPv4ForNics.put(defaultNetworkOld.getId(), defaultNicOld.getIPv4Address()); + requestedIPv6ForNics.put(defaultNetworkOld.getId(), defaultNicOld.getIPv6Address()); + s_logger.debug("AssignVM: use old shared network " + defaultNetworkOld.getName() + " with old ip " + defaultNicOld.getIPv4Address() + " on default nic of vm:" + vm.getInstanceName()); } } } - // cleanup the network for the oldOwner - _networkMgr.cleanupNics(vmOldProfile); - _networkMgr.expungeNics(vmOldProfile); - if (networkIdList != null && !networkIdList.isEmpty()) { // add any additional networks for (Long networkId : networkIdList) { @@ -6685,6 +6683,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } + + if (network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Domain) { + NicVO nicOld = _nicDao.findByNtwkIdAndInstanceId(network.getId(), vm.getId()); + if (nicOld != null) { + requestedIPv4ForNics.put(network.getId(), nicOld.getIPv4Address()); + requestedIPv6ForNics.put(network.getId(), nicOld.getIPv6Address()); + s_logger.debug("AssignVM: use old shared network " + network.getName() + " with old ip " + nicOld.getIPv4Address() + " on nic of vm:" + vm.getInstanceName()); + } + } + s_logger.debug("AssignVM: Added network " + network.getName() + " to vm " + vm.getId()); applicableNetworks.add(network); } } else if (applicableNetworks.isEmpty()) { @@ -6748,6 +6756,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir applicableNetworks.add(defaultNetwork); } + // cleanup the network for the oldOwner + _networkMgr.cleanupNics(vmOldProfile); + _networkMgr.removeNics(vmOldProfile); + // add the new nics LinkedHashMap> networks = new LinkedHashMap>(); int toggle = 0; @@ -6757,6 +6769,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir defaultNic.setDefaultNic(true); toggle++; } + defaultNic.setRequestedIPv4(requestedIPv4ForNics.get(appNet.getId())); + defaultNic.setRequestedIPv6(requestedIPv6ForNics.get(appNet.getId())); networks.put(appNet, new ArrayList(Arrays.asList(defaultNic))); } VirtualMachine vmi = _itMgr.findById(vm.getId()); @@ -6769,6 +6783,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return vm; } + private boolean canAccountUseNetwork(Account newAccount, Network network) { + if (network != null && network.getAclType() == ACLType.Domain + && (network.getGuestType() == Network.GuestType.Shared + || network.getGuestType() == Network.GuestType.L2)) { + try { + _networkModel.checkNetworkPermissions(newAccount, network); + return true; + } catch (PermissionDeniedException e) { + s_logger.debug(String.format("AssignVM: %s network %s can not be used by new account %s", network.getGuestType(), network.getName(), newAccount.getAccountName())); + return false; + } + } + return false; + } + @Override public UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException { // Input validation diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 532f5f9e76c..501ca632802 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -517,6 +517,35 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { return storagePool; } + private Pair> getRootAndDataDisks(List disks, final Map dataDiskOfferingMap) { + UnmanagedInstanceTO.Disk rootDisk = null; + List dataDisks = new ArrayList<>(); + if (disks.size() == 1) { + rootDisk = disks.get(0); + return new Pair<>(rootDisk, dataDisks); + } + Set callerDiskIds = dataDiskOfferingMap.keySet(); + if (callerDiskIds.size() != disks.size() - 1) { + String msg = String.format("VM has total %d disks for which %d disk offering mappings provided. %d disks need a disk offering for import", disks.size(), callerDiskIds.size(), disks.size()-1); + LOGGER.error(String.format("%s. %s parameter can be used to provide disk offerings for the disks", msg, ApiConstants.DATADISK_OFFERING_LIST)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, msg); + } + List diskIdsWithoutOffering = new ArrayList<>(); + for (UnmanagedInstanceTO.Disk disk : disks) { + String diskId = disk.getDiskId(); + if (!callerDiskIds.contains(diskId)) { + diskIdsWithoutOffering.add(diskId); + rootDisk = disk; + } else { + dataDisks.add(disk); + } + } + if (diskIdsWithoutOffering.size() > 1) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM has total %d disks, disk offering mapping not provided for %d disks. Disk IDs that may need a disk offering - %s", disks.size(), diskIdsWithoutOffering.size()-1, String.join(", ", diskIdsWithoutOffering))); + } + return new Pair<>(rootDisk, dataDisks); + } + private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (serviceOffering == null && diskOffering == null) { @@ -942,17 +971,16 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { if (CollectionUtils.isEmpty(unmanagedInstanceDisks)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("No attached disks found for the unmanaged VM: %s", instanceName)); } - final UnmanagedInstanceTO.Disk rootDisk = unmanagedInstance.getDisks().get(0); + Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); + final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); + final List dataDisks = rootAndDataDisksPair.second(); if (rootDisk == null || Strings.isNullOrEmpty(rootDisk.getController())) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", instanceName)); } allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); - List dataDisks = new ArrayList<>(); try { checkUnmanagedDiskAndOfferingForImport(rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed); - if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present - dataDisks.addAll(unmanagedInstanceDisks); - dataDisks.remove(0); + if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed); allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); } diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index 48ff307138a..1b2b0b50234 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -580,10 +580,10 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches } /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#expungeNics(com.cloud.vm.VirtualMachineProfile) + * @see com.cloud.network.NetworkManager#removeNics(com.cloud.vm.VirtualMachineProfile) */ @Override - public void expungeNics(VirtualMachineProfile vm) { + public void removeNics(VirtualMachineProfile vm) { // TODO Auto-generated method stub }