From 801f8422d4311007260e3782dce1366f7bf13cbd Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Mon, 21 Jun 2021 18:12:27 -0300 Subject: [PATCH 01/22] Refactor method createVMFromSpec --- .../resource/LibvirtComputingResource.java | 458 ++++++++++++------ 1 file changed, 308 insertions(+), 150 deletions(-) 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 8b7932652c0b..7fe5ac340a49 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 @@ -209,6 +209,67 @@ public class LibvirtComputingResource extends ServerResourceBase implements ServerResource, VirtualRouterDeployer { private static final Logger s_logger = Logger.getLogger(LibvirtComputingResource.class); + private static final String LEGACY = "legacy"; + private static final String SECURE = "secure"; + + /** + * Machine type. + */ + private static final String PC = "pc"; + private static final String VIRT = "virt"; + + /** + * Possible devices to add to VM. + */ + private static final String TABLET = "tablet"; + private static final String USB = "usb"; + private static final String MOUSE = "mouse"; + private static final String KEYBOARD = "keyboard"; + + /** + * Policies used by VM. + */ + private static final String RESTART = "restart"; + private static final String DESTROY = "destroy"; + + private static final String KVMCLOCK = "kvmclock"; + private static final String HYPERVCLOCK = "hypervclock"; + private static final String WINDOWS = "Windows"; + private static final String Q35 = "q35"; + private static final String PTY = "pty"; + private static final String VNC = "vnc"; + + /** + * Acronym of System Management Mode. Perform low-level system management operations while an OS is running. + */ + private static final String SMM = "smm"; + /** + * Acronym of Advanced Configuration and Power Interface.
+ * Provides an open standard that operating systems can use to discover and configure + * computer hardware components, to perform power management. + */ + private static final String ACPI = "acpi"; + /** + * Acronym of Advanced Programmable Interrupt Controllers.
+ * With an I/O APIC, operating systems can use more than 16 interrupt requests (IRQs) + * and therefore avoid IRQ sharing for improved reliability. + */ + private static final String APIC = "apic"; + /** + * Acronym of Physical Address Extension. Feature implemented in modern x86 processors.
+ * PAE extends memory addressing capabilities, allowing more than 4 GB of random access memory (RAM) to be used. + */ + private static final String PAE = "pae"; + /** + * Libvirt only suport guest cpu mode in versions from 0.9.10. + */ + private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_MODE = 9010; + private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_TUNE = 9000; + /** + * Verify if guest is ARM64 + */ + private static final String AARCH64 = "aarch64"; + private String _modifyVlanPath; private String _versionstringpath; private String _patchScriptPath; @@ -2227,8 +2288,13 @@ protected void enlightenWindowsVm(VirtualMachineTO vmTO, FeaturesDef features) { } } + /** + * Creates VM KVM definitions from virtual machine transfer object specifications. + */ public LibvirtVMDef createVMFromSpec(final VirtualMachineTO vmTO) { - final LibvirtVMDef vm = new LibvirtVMDef(); + s_logger.debug(String.format("Creating VM from specifications [%s]", vmTO.toString())); + + LibvirtVMDef vm = new LibvirtVMDef(); vm.setDomainName(vmTO.getName()); String uuid = vmTO.getUuid(); uuid = getUuid(uuid); @@ -2239,211 +2305,303 @@ public LibvirtVMDef createVMFromSpec(final VirtualMachineTO vmTO) { Map customParams = vmTO.getDetails(); boolean isUefiEnabled = false; boolean isSecureBoot = false; - String bootMode =null; + String bootMode = null; + if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) { isUefiEnabled = true; - bootMode = customParams.get(GuestDef.BootType.UEFI.toString()); - if (StringUtils.isNotBlank(bootMode) && "secure".equalsIgnoreCase(bootMode)) { + s_logger.debug(String.format("Enabled UEFI for VM UUID [%s].", uuid)); + + if (isSecureMode(customParams.get(GuestDef.BootType.UEFI.toString()))) { + s_logger.debug(String.format("Enabled Secure Boot for VM UUID [%s].", uuid)); isSecureBoot = true; } } Map extraConfig = vmTO.getExtraConfig(); if (dpdkSupport && (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA) || !extraConfig.containsKey(DpdkHelper.DPDK_HUGE_PAGES))) { - s_logger.info("DPDK is enabled but it needs extra configurations for CPU NUMA and Huge Pages for VM deployment"); + s_logger.info(String.format("DPDK is enabled for VM [%s], but it needs extra configurations for CPU NUMA and Huge Pages for VM deployment.", vmTO.toString())); } + configureVM(vmTO, vm, customParams, isUefiEnabled, isSecureBoot, bootMode, extraConfig, uuid); + return vm; + } - final GuestDef guest = new GuestDef(); + /** + * Configure created VM from specification, adding the necessary components to VM. + */ + private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map customParams, boolean isUefiEnabled, boolean isSecureBoot, String bootMode, + Map extraConfig, String uuid) { + s_logger.debug(String.format("Configuring VM with UUID [%s].", uuid)); - if (HypervisorType.LXC == _hypervisorType && VirtualMachine.Type.User == vmTO.getType()) { - // LXC domain is only valid for user VMs. Use KVM for system VMs. - guest.setGuestType(GuestDef.GuestType.LXC); - vm.setHvsType(HypervisorType.LXC.toString().toLowerCase()); - } else { - guest.setGuestType(GuestDef.GuestType.KVM); - vm.setHvsType(HypervisorType.KVM.toString().toLowerCase()); - vm.setLibvirtVersion(_hypervisorLibvirtVersion); - vm.setQemuVersion(_hypervisorQemuVersion); + GuestDef guest = createGuestFromSpec(vmTO, vm, uuid, customParams); + if (isUefiEnabled) { + configureGuestIfUefiEnabled(isSecureBoot, bootMode, guest); } - guest.setGuestArch(_guestCpuArch != null ? _guestCpuArch : vmTO.getArch()); - guest.setMachineType(_guestCpuArch != null && _guestCpuArch.equals("aarch64") ? "virt" : "pc"); - guest.setBootType(GuestDef.BootType.BIOS); - 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.setBootMode(GuestDef.BootMode.SECURE); // setting to secure mode - } + + vm.addComp(guest); + vm.addComp(createGuestResourceDef(vmTO)); + + int vcpus = vmTO.getCpus(); + if (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA)) { + vm.addComp(createCpuModeDef(vmTO, vcpus)); } - guest.setUuid(uuid); - guest.setBootOrder(GuestDef.BootOrder.CDROM); - guest.setBootOrder(GuestDef.BootOrder.HARDISK); - if (isUefiEnabled) { - if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) { - guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE)); - } + if (_hypervisorLibvirtVersion >= MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_TUNE) { + vm.addComp(createCpuTuneDef(vmTO)); + } - if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY) != null && "legacy".equalsIgnoreCase(bootMode)) { - guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY)); - } + FeaturesDef features = createFeaturesDef(customParams, isUefiEnabled, isSecureBoot); + enlightenWindowsVm(vmTO, features); + vm.addComp(features); - if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH) != null) { - guest.setNvram(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH)); - } + vm.addComp(createTermPolicy()); + vm.addComp(createClockDef(vmTO)); + vm.addComp(createDevicesDef(vmTO, guest, vcpus, isUefiEnabled)); - if (isSecureBoot) { - if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) { - guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE)); - } - } else { - if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY) != null) { - guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY)); - } - } + // Add extra configuration to User VM Domain XML before starting + if (MapUtils.isNotEmpty(extraConfig) && VirtualMachine.Type.User.equals(vmTO.getType())) { + s_logger.debug(String.format("Appending extra configuration data [%s] to guest VM [%s] domain XML.", extraConfig, vmTO.toString())); + addExtraConfigComponent(extraConfig, vm); + } + } + + /** + * Add devices components to VM. + */ + protected DevicesDef createDevicesDef(VirtualMachineTO vmTO, GuestDef guest, int vcpus, boolean isUefiEnabled) { + DevicesDef devices = new DevicesDef(); + devices.setEmulatorPath(_hypervisorPath); + devices.setGuestType(guest.getGuestType()); + devices.addDevice(createSerialDef()); + + if (_rngEnable) { + devices.addDevice(createRngDef()); } - vm.addComp(guest); + devices.addDevice(createChannelDef(vmTO)); + devices.addDevice(createWatchDogDef()); + devices.addDevice(createVideoDef()); + devices.addDevice(createConsoleDef()); + devices.addDevice(createGraphicDef(vmTO)); + devices.addDevice(createTabletInputDef()); - final GuestResourceDef grd = new GuestResourceDef(); + if (isGuestAarch64()) { + createArm64UsbDef(devices); + } - if (vmTO.getMinRam() != vmTO.getMaxRam() && !_noMemBalloon) { - grd.setMemBalloning(true); - grd.setCurrentMem(vmTO.getMinRam() / 1024); - grd.setMemorySize(vmTO.getMaxRam() / 1024); - } else { - grd.setMemorySize(vmTO.getMaxRam() / 1024); + DiskDef.DiskBus busT = getDiskModelFromVMDetail(vmTO); + if (busT == null) { + busT = getGuestDiskModel(vmTO.getPlatformEmulator(), isUefiEnabled); } - final int vcpus = vmTO.getCpus(); - grd.setVcpuNum(vcpus); - vm.addComp(grd); - if (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA)) { - final CpuModeDef cmd = new CpuModeDef(); - cmd.setMode(_guestCpuMode); - cmd.setModel(_guestCpuModel); - if (vmTO.getType() == VirtualMachine.Type.User) { - cmd.setFeatures(_cpuFeatures); - } - setCpuTopology(cmd, vcpus, vmTO.getDetails()); - vm.addComp(cmd); + if (busT == DiskDef.DiskBus.SCSI) { + devices.addDevice(createSCSIDef(vcpus)); } + return devices; + } - if (_hypervisorLibvirtVersion >= 9000) { - final CpuTuneDef ctd = new CpuTuneDef(); - /** - A 4.0.X/4.1.X management server doesn't send the correct JSON - command for getMinSpeed, it only sends a 'speed' field. + protected WatchDogDef createWatchDogDef() { + return new WatchDogDef(_watchDogAction, _watchDogModel); + } - So if getMinSpeed() returns null we fall back to getSpeed(). + /* + * Add an explicit USB devices for ARM64 + */ + protected void createArm64UsbDef(DevicesDef devices) { + devices.addDevice(new InputDef(KEYBOARD, USB)); + devices.addDevice(new InputDef(MOUSE, USB)); + devices.addDevice(new LibvirtVMDef.USBDef((short)0, 0, 5, 0, 0)); + } - This way a >4.1 agent can work communicate a <=4.1 management server + protected InputDef createTabletInputDef() { + return new InputDef(TABLET, USB); + } - This change is due to the overcommit feature in 4.2 - */ - if (vmTO.getMinSpeed() != null) { - ctd.setShares(vmTO.getCpus() * vmTO.getMinSpeed()); - } else { - ctd.setShares(vmTO.getCpus() * vmTO.getSpeed()); - } + /** + * Add the VNC port passwd here, get the passwd from the vmInstance. + */ + protected GraphicDef createGraphicDef(VirtualMachineTO vmTO) { + return new GraphicDef(VNC, (short)0, true, vmTO.getVncAddr(), vmTO.getVncPassword(), null); + } - setQuotaAndPeriod(vmTO, ctd); + /** + * Add a VirtIO channel for the Qemu Guest Agent tools. + */ + protected ChannelDef createChannelDef(VirtualMachineTO vmTO) { + File virtIoChannel = Paths.get(_qemuSocketsPath.getPath(), vmTO.getName() + "." + _qemuGuestAgentSocketName).toFile(); + return new ChannelDef(_qemuGuestAgentSocketName, ChannelDef.ChannelType.UNIX, virtIoChannel); + } - vm.addComp(ctd); - } + /** + * If we're using virtio scsi, then we need to add a virtual scsi controller. + */ + protected SCSIDef createSCSIDef(int vcpus) { + return new SCSIDef((short)0, 0, 0, 9, 0, vcpus); + } - final FeaturesDef features = new FeaturesDef(); - features.addFeatures("pae"); - features.addFeatures("apic"); - features.addFeatures("acpi"); - if (isUefiEnabled && isSecureMode(customParams.get(GuestDef.BootType.UEFI.toString()))) { - features.addFeatures("smm"); - } + protected ConsoleDef createConsoleDef() { + return new ConsoleDef(PTY, null, null, (short)0); + } - //KVM hyperv enlightenment features based on OS Type - enlightenWindowsVm(vmTO, features); + protected VideoDef createVideoDef() { + return new VideoDef(_videoHw, _videoRam); + } - vm.addComp(features); + protected RngDef createRngDef() { + return new RngDef(_rngPath, _rngBackendModel, _rngRateBytes, _rngRatePeriod); + } - final TermPolicy term = new TermPolicy(); - term.setCrashPolicy("destroy"); - term.setPowerOffPolicy("destroy"); - term.setRebootPolicy("restart"); - vm.addComp(term); + protected SerialDef createSerialDef() { + return new SerialDef(PTY, null, (short)0); + } - final ClockDef clock = new ClockDef(); - if (vmTO.getOs().startsWith("Windows")) { + protected ClockDef createClockDef(final VirtualMachineTO vmTO) { + ClockDef clock = new ClockDef(); + if (org.apache.commons.lang.StringUtils.startsWith(vmTO.getOs(), WINDOWS)) { clock.setClockOffset(ClockDef.ClockOffset.LOCALTIME); - clock.setTimer("hypervclock", null, null); - } else if (vmTO.getType() != VirtualMachine.Type.User || isGuestPVEnabled(vmTO.getOs())) { - if (_hypervisorLibvirtVersion >= 9 * 1000 + 10) { - clock.setTimer("kvmclock", null, null, _noKvmClock); - } + clock.setTimer(HYPERVCLOCK, null, null); + } else if ((vmTO.getType() != VirtualMachine.Type.User || isGuestPVEnabled(vmTO.getOs())) && _hypervisorLibvirtVersion >= MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_MODE) { + clock.setTimer(KVMCLOCK, null, null, _noKvmClock); } + return clock; + } - vm.addComp(clock); + protected TermPolicy createTermPolicy() { + TermPolicy term = new TermPolicy(); + term.setCrashPolicy(DESTROY); + term.setPowerOffPolicy(DESTROY); + term.setRebootPolicy(RESTART); + return term; + } - final DevicesDef devices = new DevicesDef(); - devices.setEmulatorPath(_hypervisorPath); - devices.setGuestType(guest.getGuestType()); + protected FeaturesDef createFeaturesDef(Map customParams, boolean isUefiEnabled, boolean isSecureBoot) { + FeaturesDef features = new FeaturesDef(); + features.addFeatures(PAE); + features.addFeatures(APIC); + features.addFeatures(ACPI); + if (isUefiEnabled && isSecureBoot) { + features.addFeatures(SMM); + } + return features; + } - final SerialDef serial = new SerialDef("pty", null, (short)0); - devices.addDevice(serial); + /** + * A 4.0.X/4.1.X management server doesn't send the correct JSON + * command for getMinSpeed, it only sends a 'speed' field.
+ * So, to create a cpu tune, if getMinSpeed() returns null we fall back to getSpeed().
+ * This way a >4.1 agent can work communicate a <=4.1 management server.
+ * This change is due to the overcommit feature in 4.2. + */ + protected CpuTuneDef createCpuTuneDef(VirtualMachineTO vmTO) { + CpuTuneDef ctd = new CpuTuneDef(); + int shares = vmTO.getCpus() * (vmTO.getMinSpeed() != null ? vmTO.getMinSpeed() : vmTO.getSpeed()); + ctd.setShares(shares); + setQuotaAndPeriod(vmTO, ctd); + return ctd; + } - if (_rngEnable) { - final RngDef rngDevice = new RngDef(_rngPath, _rngBackendModel, _rngRateBytes, _rngRatePeriod); - devices.addDevice(rngDevice); + private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) { + final CpuModeDef cmd = new CpuModeDef(); + cmd.setMode(_guestCpuMode); + cmd.setModel(_guestCpuModel); + if (VirtualMachine.Type.User.equals(vmTO.getType())) { + cmd.setFeatures(_cpuFeatures); } + setCpuTopology(cmd, vcpus, vmTO.getDetails()); + return cmd; + } - /* Add a VirtIO channel for the Qemu Guest Agent tools */ - File virtIoChannel = Paths.get(_qemuSocketsPath.getPath(), vmTO.getName() + "." + _qemuGuestAgentSocketName).toFile(); - devices.addDevice(new ChannelDef(_qemuGuestAgentSocketName, ChannelDef.ChannelType.UNIX, virtIoChannel)); - - devices.addDevice(new WatchDogDef(_watchDogAction, _watchDogModel)); + /** + * Creates guest resources based in VM specification. + */ + protected GuestResourceDef createGuestResourceDef(VirtualMachineTO vmTO) { + GuestResourceDef grd = new GuestResourceDef(); - final VideoDef videoCard = new VideoDef(_videoHw, _videoRam); - devices.addDevice(videoCard); + grd.setMemorySize(vmTO.getMaxRam() / 1024); + if (vmTO.getMinRam() != vmTO.getMaxRam() && !_noMemBalloon) { + grd.setMemBalloning(true); + grd.setCurrentMem(vmTO.getMinRam() / 1024); + } + grd.setVcpuNum(vmTO.getCpus()); + return grd; + } - final ConsoleDef console = new ConsoleDef("pty", null, null, (short)0); - devices.addDevice(console); + private void configureGuestIfUefiEnabled(boolean isSecureBoot, String bootMode, GuestDef guest) { + setGuestLoader(bootMode, SECURE, guest, GuestDef.GUEST_LOADER_SECURE); + setGuestLoader(bootMode, LEGACY, guest, GuestDef.GUEST_LOADER_LEGACY); - //add the VNC port passwd here, get the passwd from the vmInstance. - final String passwd = vmTO.getVncPassword(); - final GraphicDef grap = new GraphicDef("vnc", (short)0, true, vmTO.getVncAddr(), passwd, null); - devices.addDevice(grap); + if (isUefiPropertieNotNull(GuestDef.GUEST_NVRAM_PATH)) { + guest.setNvram(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH)); + } - final InputDef input = new InputDef("tablet", "usb"); - devices.addDevice(input); + if (isSecureBoot && isUefiPropertieNotNull(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE) && SECURE.equalsIgnoreCase(bootMode)) { + guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE)); + } else if (isUefiPropertieNotNull(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY)) { + guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY)); + } + } - // Add an explicit USB devices for ARM64 - if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { - devices.addDevice(new InputDef("keyboard", "usb")); - devices.addDevice(new InputDef("mouse", "usb")); - devices.addDevice(new LibvirtVMDef.USBDef((short)0, 0, 5, 0, 0)); + private void setGuestLoader(String bootMode, String mode, GuestDef guest, String propertie) { + if (isUefiPropertieNotNull(propertie) && mode.equalsIgnoreCase(bootMode)) { + guest.setLoader(_uefiProperties.getProperty(propertie)); } + } - DiskDef.DiskBus busT = getDiskModelFromVMDetail(vmTO); + private boolean isUefiPropertieNotNull(String propertie) { + return _uefiProperties.getProperty(propertie) != null; + } - if (busT == null) { - busT = getGuestDiskModel(vmTO.getPlatformEmulator(), isUefiEnabled); - } + private boolean isGuestAarch64() { + return AARCH64.equals(_guestCpuArch); + } - // If we're using virtio scsi, then we need to add a virtual scsi controller - if (busT == DiskDef.DiskBus.SCSI) { - final SCSIDef sd = new SCSIDef((short)0, 0, 0, 9, 0, vcpus); - devices.addDevice(sd); - } + /** + * Create a guest definition from a VM specification. + */ + protected GuestDef createGuestFromSpec(VirtualMachineTO vmTO, LibvirtVMDef vm, String uuid, Map customParams) { + GuestDef guest = new GuestDef(); - vm.addComp(devices); + configureGuestAndVMHypervisorType(vmTO, vm, guest); + guest.setGuestArch(_guestCpuArch != null ? _guestCpuArch : vmTO.getArch()); + guest.setMachineType(isGuestAarch64() ? VIRT : PC); + guest.setBootType(GuestDef.BootType.BIOS); + if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) { + guest.setBootType(GuestDef.BootType.UEFI); + guest.setBootMode(GuestDef.BootMode.LEGACY); + guest.setMachineType(Q35); + if (SECURE.equalsIgnoreCase(customParams.get(GuestDef.BootType.UEFI.toString()))) { + guest.setBootMode(GuestDef.BootMode.SECURE); + } + } + guest.setUuid(uuid); + guest.setBootOrder(GuestDef.BootOrder.CDROM); + guest.setBootOrder(GuestDef.BootOrder.HARDISK); + return guest; + } - // Add extra configuration to User VM Domain XML before starting - if (vmTO.getType().equals(VirtualMachine.Type.User) && MapUtils.isNotEmpty(extraConfig)) { - s_logger.info("Appending extra configuration data to guest VM domain XML"); - addExtraConfigComponent(extraConfig, vm); + protected void configureGuestAndVMHypervisorType(VirtualMachineTO vmTO, LibvirtVMDef vm, GuestDef guest) { + if (HypervisorType.LXC == _hypervisorType && VirtualMachine.Type.User.equals(vmTO.getType())) { + configureGuestAndUserVMToUseLXC(vm, guest); + } else { + configureGuestAndSystemVMToUseKVM(vm, guest); } + } - return vm; + /** + * KVM domain is only valid for system VMs. Use LXC for user VMs. + */ + private void configureGuestAndSystemVMToUseKVM(LibvirtVMDef vm, GuestDef guest) { + guest.setGuestType(GuestDef.GuestType.KVM); + vm.setHvsType(HypervisorType.KVM.toString().toLowerCase()); + vm.setLibvirtVersion(_hypervisorLibvirtVersion); + vm.setQemuVersion(_hypervisorQemuVersion); + } + + /** + * LXC domain is only valid for user VMs. Use KVM for system VMs. + */ + private void configureGuestAndUserVMToUseLXC(LibvirtVMDef vm, GuestDef guest) { + guest.setGuestType(GuestDef.GuestType.LXC); + vm.setHvsType(HypervisorType.LXC.toString().toLowerCase()); } /** From 220672f8becbbe2aa0031557614d62ef8d7fdf01 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Mon, 21 Jun 2021 18:12:35 -0300 Subject: [PATCH 02/22] Add unit tests --- .../LibvirtComputingResourceTest.java | 552 +++++++++++++++--- 1 file changed, 471 insertions(+), 81 deletions(-) diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 84d08531c2bf..1bed1e85c02e 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -79,6 +79,7 @@ import org.mockito.BDDMockito; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.Spy; import org.mockito.invocation.InvocationOnMock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; @@ -160,11 +161,27 @@ import com.cloud.agent.api.to.VolumeTO; import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import com.cloud.exception.InternalErrorException; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.kvm.resource.KVMHABase.NfsStoragePool; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ChannelDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ClockDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ConsoleDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.CpuTuneDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DevicesDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.FeaturesDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GraphicDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestDef.GuestType; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestResourceDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InputDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SCSIDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VideoDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef; import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtRequestWrapper; import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper; import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; @@ -201,6 +218,8 @@ public class LibvirtComputingResourceTest { VirtualMachineTO vmTO; @Mock LibvirtVMDef vmDef; + @Spy + private LibvirtComputingResource libvirtComputingResourceSpy = Mockito.spy(LibvirtComputingResource.class); String hyperVisorType = "kvm"; Random random = new Random(); @@ -214,6 +233,7 @@ public class LibvirtComputingResourceTest { @Before public void setup() throws Exception { + libvirtComputingResourceSpy._qemuSocketsPath = new File("/var/run/qemu"); Scanner scanner = new Scanner(memInfo); PowerMockito.whenNew(Scanner.class).withAnyArguments().thenReturn(scanner); } @@ -240,15 +260,13 @@ public void testCreateVMFromSpecLegacy() { final String vncAddr = ""; final String vncPassword = "mySuperSecretPassword"; - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); - final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, speed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); to.setArch("x86_64"); to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + to.setVcpuMaxLimit(cpus + 1); - final LibvirtVMDef vm = lcr.createVMFromSpec(to); + final LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); verifyVm(to, vm); @@ -273,15 +291,13 @@ public void testCreateVMFromSpecWithTopology6() { final String vncAddr = ""; final String vncPassword = "mySuperSecretPassword"; - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); - final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); to.setArch("x86_64"); to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + to.setVcpuMaxLimit(cpus + 1); - final LibvirtVMDef vm = lcr.createVMFromSpec(to); + final LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); verifyVm(to, vm); @@ -292,28 +308,8 @@ public void testCreateVMFromSpecWithTopology6() { */ @Test public void testCreateVMFromSpecWithTopology4() { - final int id = random.nextInt(65534); - final String name = "test-instance-1"; - - final int cpus = 8; - final int minSpeed = 1024; - final int maxSpeed = 2048; - final int minRam = 256 * 1024; - final int maxRam = 512 * 1024; - - final String os = "Ubuntu"; - - final String vncAddr = ""; - final String vncPassword = "mySuperSecretPassword"; - - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); - - final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); - to.setVncAddr(vncAddr); - to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); - - final LibvirtVMDef vm = lcr.createVMFromSpec(to); + VirtualMachineTO to = createDefaultVM(false); + LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); verifyVm(to, vm); @@ -328,59 +324,388 @@ public void testCreateVMFromSpecWithTopology4() { */ @Test public void testCreateVMFromSpec() { - final int id = random.nextInt(65534); - final String name = "test-instance-1"; + VirtualMachineTO to = createDefaultVM(false); + final LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); + vm.setHvsType(hyperVisorType); - final int cpus = random.nextInt(2) + 1; - final int minSpeed = 1024; - final int maxSpeed = 2048; - final int minRam = 256 * 1024; - final int maxRam = 512 * 1024; + verifyVm(to, vm); + } - final String os = "Ubuntu"; + @Test + public void testCreateGuestFromSpecWithoutCustomParam() { + VirtualMachineTO to = createDefaultVM(false); + LibvirtVMDef vm = new LibvirtVMDef(); + GuestDef guestDef = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), null); + verifySysInfo(guestDef, "smbios", to.getUuid(), "pc"); + Assert.assertEquals(GuestDef.BootType.BIOS, guestDef.getBootType()); + Assert.assertNull(guestDef.getBootMode()); + } - final String vncAddr = ""; - final String vncPassword = "mySuperSecretPassword"; + @Test + public void testCreateGuestFromSpecWithCustomParamAndUefi() { + VirtualMachineTO to = createDefaultVM(false); - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); + Map extraConfig = new HashMap<>(); + extraConfig.put(GuestDef.BootType.UEFI.toString(), "legacy"); - final VirtualMachineTO to = - new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); - to.setVncAddr(vncAddr); + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestDef = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), extraConfig); + verifySysInfo(guestDef, "smbios", to.getUuid(), "q35"); + Assert.assertEquals(GuestDef.BootType.UEFI, guestDef.getBootType()); + Assert.assertEquals(GuestDef.BootMode.LEGACY, guestDef.getBootMode()); + } + + @Test + public void testCreateGuestFromSpecWithCustomParamUefiAndSecure() { + VirtualMachineTO to = createDefaultVM(false); + + Map extraConfig = new HashMap<>(); + extraConfig.put(GuestDef.BootType.UEFI.toString(), "secure"); + + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestDef = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), extraConfig); + verifySysInfo(guestDef, "smbios", to.getUuid(), "q35"); + Assert.assertEquals(GuestDef.BootType.UEFI, guestDef.getBootType()); + Assert.assertEquals(GuestDef.BootMode.SECURE, guestDef.getBootMode()); + } + + @Test + public void testCreateGuestResourceDef() { + VirtualMachineTO to = createDefaultVM(false); + + GuestResourceDef guestResourceDef = libvirtComputingResourceSpy.createGuestResourceDef(to); + verifyGuestResourceDef(guestResourceDef, to); + } + + @Test + public void testCreateDevicesDef() { + VirtualMachineTO to = createDefaultVM(false); + + GuestDef guest = new GuestDef(); + guest.setGuestType(GuestType.KVM); + + DevicesDef devicesDef = libvirtComputingResourceSpy.createDevicesDef(to, guest, to.getCpus() + 1, false); + verifyDevices(devicesDef, to); + } + + @Test + public void testCreateDevicesWithSCSIDisk() { + VirtualMachineTO to = createDefaultVM(false); + to.setDetails(new HashMap<>()); + libvirtComputingResourceSpy._guestCpuArch = "aarch64"; + + GuestDef guest = new GuestDef(); + guest.setGuestType(GuestType.KVM); + + DevicesDef devicesDef = libvirtComputingResourceSpy.createDevicesDef(to, guest, to.getCpus() + 1, false); + verifyDevices(devicesDef, to); + + Document domainDoc = parse(devicesDef.toString()); + assertNodeExists(domainDoc, "/devices/controller[@type='scsi']"); + assertNodeExists(domainDoc, "/devices/controller[@model='virtio-scsi']"); + assertNodeExists(domainDoc, "/devices/controller/address[@type='pci']"); + assertNodeExists(domainDoc, "/devices/controller/driver[@queues='" + (to.getCpus() + 1) + "']"); + } + + @Test + public void testConfigureGuestAndSystemVMToUseKVM() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._hypervisorLibvirtVersion = 100; + libvirtComputingResourceSpy._hypervisorQemuVersion = 10; + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestFromSpec = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), null); + Assert.assertEquals(GuestDef.GuestType.KVM, guestFromSpec.getGuestType()); + Assert.assertEquals(HypervisorType.KVM.toString().toLowerCase(), vm.getHvsType()); + } + + @Test + public void testConfigureGuestAndUserVMToUseLXC() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._hypervisorType = HypervisorType.LXC; + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestFromSpec = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), null); + Assert.assertEquals(GuestDef.GuestType.LXC, guestFromSpec.getGuestType()); + Assert.assertEquals(HypervisorType.LXC.toString().toLowerCase(), vm.getHvsType()); + } + + @Test + public void testCreateCpuTuneDefWithoutQuotaAndPeriod() { + VirtualMachineTO to = createDefaultVM(false); + + CpuTuneDef cpuTuneDef = libvirtComputingResourceSpy.createCpuTuneDef(to); + Document domainDoc = parse(cpuTuneDef.toString()); + assertXpath(domainDoc, "/cputune/shares/text()", String.valueOf(cpuTuneDef.getShares())); + } + + @Test + public void testCreateCpuTuneDefWithQuotaAndPeriod() { + VirtualMachineTO to = createDefaultVM(true); + to.setCpuQuotaPercentage(10.0); + + CpuTuneDef cpuTuneDef = libvirtComputingResourceSpy.createCpuTuneDef(to); + Document domainDoc = parse(cpuTuneDef.toString()); + assertXpath(domainDoc, "/cputune/shares/text()", String.valueOf(cpuTuneDef.getShares())); + assertXpath(domainDoc, "/cputune/quota/text()", String.valueOf(cpuTuneDef.getQuota())); + assertXpath(domainDoc, "/cputune/period/text()", String.valueOf(cpuTuneDef.getPeriod())); + } + + @Test + public void testCreateCpuTuneDefWithMinQuota() { + VirtualMachineTO to = createDefaultVM(true); + to.setCpuQuotaPercentage(0.01); + + CpuTuneDef cpuTuneDef = libvirtComputingResourceSpy.createCpuTuneDef(to); + Document domainDoc = parse(cpuTuneDef.toString()); + assertXpath(domainDoc, "/cputune/shares/text()", String.valueOf(cpuTuneDef.getShares())); + assertXpath(domainDoc, "/cputune/quota/text()", "1000"); + assertXpath(domainDoc, "/cputune/period/text()", String.valueOf(cpuTuneDef.getPeriod())); + } + + @Test + public void testCreateDefaultClockDef() { + VirtualMachineTO to = createDefaultVM(false); + + ClockDef clockDef = libvirtComputingResourceSpy.createClockDef(to); + Document domainDoc = parse(clockDef.toString()); + + assertXpath(domainDoc, "/clock/@offset", "utc"); + } + + @Test + public void testCreateClockDefWindows() { + VirtualMachineTO to = createDefaultVM(false); + to.setOs("Windows"); + + ClockDef clockDef = libvirtComputingResourceSpy.createClockDef(to); + Document domainDoc = parse(clockDef.toString()); + + assertXpath(domainDoc, "/clock/@offset", "localtime"); + assertXpath(domainDoc, "/clock/timer/@name", "hypervclock"); + assertXpath(domainDoc, "/clock/timer/@present", "yes"); + } + + @Test + public void testCreateClockDefKvmclock() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._hypervisorLibvirtVersion = 9020; + + ClockDef clockDef = libvirtComputingResourceSpy.createClockDef(to); + Document domainDoc = parse(clockDef.toString()); + + assertXpath(domainDoc, "/clock/@offset", "utc"); + assertXpath(domainDoc, "/clock/timer/@name", "kvmclock"); + } + + @Test + public void testCreateTermPolicy() { + TermPolicy termPolicy = libvirtComputingResourceSpy.createTermPolicy(); + + String xml = "\n" + termPolicy.toString() + ""; + Document domainDoc = parse(xml); + + assertXpath(domainDoc, "/terms/on_reboot/text()", "restart"); + assertXpath(domainDoc, "/terms/on_poweroff/text()", "destroy"); + assertXpath(domainDoc, "/terms/on_crash/text()", "destroy"); + } + + @Test + public void testCreateFeaturesDef() { + VirtualMachineTO to = createDefaultVM(false); + FeaturesDef featuresDef = libvirtComputingResourceSpy.createFeaturesDef(null, false, false); + + String xml = "" + featuresDef.toString() + ""; + Document domainDoc = parse(xml); + + verifyFeatures(domainDoc); + } + + @Test + public void testCreateFeaturesDefWithUefi() { + VirtualMachineTO to = createDefaultVM(false); + HashMap extraConfig = new HashMap<>(); + extraConfig.put(GuestDef.BootType.UEFI.toString(), ""); + + FeaturesDef featuresDef = libvirtComputingResourceSpy.createFeaturesDef(extraConfig, true, true); + + String xml = "" + featuresDef.toString() + ""; + Document domainDoc = parse(xml); + + verifyFeatures(domainDoc); + } + + @Test + public void testCreateWatchDog() { + WatchDogDef watchDogDef = libvirtComputingResourceSpy.createWatchDogDef(); + verifyWatchDogDevices(parse(watchDogDef.toString()), ""); + } + + @Test + public void testCreateArm64UsbDef() { + DevicesDef devicesDef = new DevicesDef(); + + libvirtComputingResourceSpy.createArm64UsbDef(devicesDef); + Document domainDoc = parse(devicesDef.toString()); + + assertXpath(domainDoc, "/devices/controller/@type", "usb"); + assertXpath(domainDoc, "/devices/controller/@model", "qemu-xhci"); + assertXpath(domainDoc, "/devices/controller/address/@type", "pci"); + assertNodeExists(domainDoc, "/devices/input[@type='keyboard']"); + assertNodeExists(domainDoc, "/devices/input[@bus='usb']"); + assertNodeExists(domainDoc, "/devices/input[@type='mouse']"); + assertNodeExists(domainDoc, "/devices/input[@bus='usb']"); + } + + @Test + public void testCreateInputDef() { + InputDef inputDef = libvirtComputingResourceSpy.createTabletInputDef(); + verifyTabletInputDevice(parse(inputDef.toString()), ""); + } + + @Test + public void testCreateGraphicDef() { + VirtualMachineTO to = createDefaultVM(false); + GraphicDef graphicDef = libvirtComputingResourceSpy.createGraphicDef(to); + verifyGraphicsDevices(to, parse(graphicDef.toString()), ""); + } + + @Test + public void testCreateChannelDef() { + VirtualMachineTO to = createDefaultVM(false); + ChannelDef channelDef = libvirtComputingResourceSpy.createChannelDef(to); + verifyChannelDevices(to, parse(channelDef.toString()), ""); + } + + @Test + public void testCreateSCSIDef() { + VirtualMachineTO to = createDefaultVM(false); + + SCSIDef scsiDef = libvirtComputingResourceSpy.createSCSIDef(to.getCpus()); + Document domainDoc = parse(scsiDef.toString()); + verifyScsi(to, domainDoc, ""); + } + + @Test + public void testCreateConsoleDef() { + VirtualMachineTO to = createDefaultVM(false); + ConsoleDef consoleDef = libvirtComputingResourceSpy.createConsoleDef(); + verifyConsoleDevices(parse(consoleDef.toString()), ""); + } + + @Test + public void testCreateVideoDef() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._videoRam = 200; + libvirtComputingResourceSpy._videoHw = "vGPU"; + + VideoDef videoDef = libvirtComputingResourceSpy.createVideoDef(); + Document domainDoc = parse(videoDef.toString()); + assertXpath(domainDoc, "/video/model/@type", "vGPU"); + assertXpath(domainDoc, "/video/model/@vram", "200"); + } + + @Test + public void testCreateRngDef() { + VirtualMachineTO to = createDefaultVM(false); + RngDef rngDef = libvirtComputingResourceSpy.createRngDef(); + Document domainDoc = parse(rngDef.toString()); + + assertXpath(domainDoc, "/rng/@model", "virtio"); + assertXpath(domainDoc, "/rng/rate/@period", "1000"); + assertXpath(domainDoc, "/rng/rate/@bytes", "2048"); + assertXpath(domainDoc, "/rng/backend/@model", "random"); + assertXpath(domainDoc, "/rng/backend/text()", "/dev/random"); + } + + @Test + public void testCreateSerialDef() { + VirtualMachineTO to = createDefaultVM(false); + SerialDef serialDef = libvirtComputingResourceSpy.createSerialDef(); + verifySerialDevices(parse(serialDef.toString()), ""); + } + + private VirtualMachineTO createDefaultVM(boolean limitCpuUse) { + int id = random.nextInt(65534); + String name = "test-instance-1"; + + int cpus = random.nextInt(2) + 1; + int minSpeed = 1024; + int maxSpeed = 2048; + int minRam = 256 * 1024; + int maxRam = 512 * 1024; + + String os = "Ubuntu"; + String vncAddr = ""; + String vncPassword = "mySuperSecretPassword"; + + final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, limitCpuUse, + vncPassword); to.setArch("x86_64"); + to.setVncAddr(vncAddr); to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + to.setVcpuMaxLimit(cpus + 1); - final LibvirtVMDef vm = lcr.createVMFromSpec(to); - vm.setHvsType(hyperVisorType); + return to; + } - verifyVm(to, vm); + private void verifyGuestResourceDef(GuestResourceDef guestResourceDef, VirtualMachineTO to) { + String xml = "" + guestResourceDef.toString() + ""; + Document domainDoc = parse(xml); + + String minRam = String.valueOf(to.getMinRam() / 1024); + verifyMemory(to, domainDoc, minRam); + assertNodeExists(domainDoc, "/domain/vcpu"); + verifyMemballoonDevices(domainDoc); + verifyVcpu(to, domainDoc); } - private void verifyVm(final VirtualMachineTO to, final LibvirtVMDef vm) { - final Document domainDoc = parse(vm.toString()); - assertXpath(domainDoc, "/domain/@type", vm.getHvsType()); - assertXpath(domainDoc, "/domain/name/text()", to.getName()); - assertXpath(domainDoc, "/domain/uuid/text()", to.getUuid()); - assertXpath(domainDoc, "/domain/description/text()", to.getOs()); - assertXpath(domainDoc, "/domain/clock/@offset", "utc"); - assertNodeExists(domainDoc, "/domain/features/pae"); - assertNodeExists(domainDoc, "/domain/features/apic"); - assertNodeExists(domainDoc, "/domain/features/acpi"); - assertXpath(domainDoc, "/domain/devices/serial/@type", "pty"); - assertXpath(domainDoc, "/domain/devices/serial/target/@port", "0"); - assertXpath(domainDoc, "/domain/devices/graphics/@type", "vnc"); - assertXpath(domainDoc, "/domain/devices/graphics/@listen", to.getVncAddr()); - assertXpath(domainDoc, "/domain/devices/graphics/@autoport", "yes"); - assertXpath(domainDoc, "/domain/devices/graphics/@passwd", to.getVncPassword()); + private void verifyVm(VirtualMachineTO to, LibvirtVMDef vm) { + Document domainDoc = parse(vm.toString()); + verifyHeader(domainDoc, vm.getHvsType(), to.getName(), to.getUuid(), to.getOs()); + verifyFeatures(domainDoc); + verifyClock(domainDoc); + verifySerialDevices(domainDoc, "/domain/devices"); + verifyGraphicsDevices(to, domainDoc, "/domain/devices"); + verifyConsoleDevices(domainDoc, "/domain/devices"); + verifyTabletInputDevice(domainDoc, "/domain/devices"); + verifyChannelDevices(to, domainDoc, "/domain/devices"); + + String minRam = String.valueOf(to.getMinRam() / 1024); + verifyMemory(to, domainDoc, minRam); + assertNodeExists(domainDoc, "/domain/cpu"); + + verifyMemballoonDevices(domainDoc); + verifyVcpu(to, domainDoc); + verifyOsType(domainDoc); + verifyOsBoot(domainDoc); + verifyPoliticOn_(domainDoc); + verifyWatchDogDevices(domainDoc, "/domain/devices"); + } + + private void verifyMemballoonDevices(Document domainDoc) { + assertXpath(domainDoc, "/domain/devices/memballoon/@model", "virtio"); + } - assertXpath(domainDoc, "/domain/devices/console/@type", "pty"); - assertXpath(domainDoc, "/domain/devices/console/target/@port", "0"); - assertXpath(domainDoc, "/domain/devices/input/@type", "tablet"); - assertXpath(domainDoc, "/domain/devices/input/@bus", "usb"); + private void verifyVcpu(VirtualMachineTO to, Document domainDoc) { + assertXpath(domainDoc, "/domain/vcpu/text()", String.valueOf(to.getCpus())); + } - assertNodeExists(domainDoc, "/domain/devices/channel"); - assertXpath(domainDoc, "/domain/devices/channel/@type", ChannelDef.ChannelType.UNIX.toString()); + private void verifyMemory(VirtualMachineTO to, Document domainDoc, String minRam) { + assertXpath(domainDoc, "/domain/memory/text()", String.valueOf(to.getMaxRam() / 1024)); + assertXpath(domainDoc, "/domain/currentMemory/text()", minRam); + } + + private void verifyWatchDogDevices(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/watchdog/@model", "i6300esb"); + assertXpath(domainDoc, prefix + "/watchdog/@action", "none"); + } + + private void verifyChannelDevices(VirtualMachineTO to, Document domainDoc, String prefix) { + assertNodeExists(domainDoc, prefix + "/channel"); + assertXpath(domainDoc, prefix + "/channel/@type", ChannelDef.ChannelType.UNIX.toString()); /* The configure() method of LibvirtComputingResource has not been called, so the default path for the sockets @@ -389,28 +714,93 @@ The configure() method of LibvirtComputingResource has not been called, so the d Calling configure is also not possible since that looks for certain files on the system which are not present during testing */ - assertXpath(domainDoc, "/domain/devices/channel/source/@path", "/var/run/qemu/" + to.getName() + ".org.qemu.guest_agent.0"); - assertXpath(domainDoc, "/domain/devices/channel/target/@name", "org.qemu.guest_agent.0"); + assertXpath(domainDoc, prefix + "/channel/source/@path", "/var/run/qemu/" + to.getName() + ".org.qemu.guest_agent.0"); + assertXpath(domainDoc, prefix + "/channel/target/@name", "org.qemu.guest_agent.0"); + } - assertXpath(domainDoc, "/domain/memory/text()", String.valueOf( to.getMaxRam() / 1024 )); - assertXpath(domainDoc, "/domain/currentMemory/text()", String.valueOf( to.getMinRam() / 1024 )); + private void verifyTabletInputDevice(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/input/@type", "tablet"); + assertXpath(domainDoc, prefix + "/input/@bus", "usb"); + } - assertXpath(domainDoc, "/domain/devices/memballoon/@model", "virtio"); - assertXpath(domainDoc, "/domain/vcpu/text()", String.valueOf(to.getCpus())); + private void verifyConsoleDevices(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/console/@type", "pty"); + assertXpath(domainDoc, prefix + "/console/target/@port", "0"); + } - assertXpath(domainDoc, "/domain/os/type/@machine", "pc"); - assertXpath(domainDoc, "/domain/os/type/text()", "hvm"); + private void verifyScsi(VirtualMachineTO to, Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/controller/@type", "scsi"); + assertXpath(domainDoc, prefix + "/controller/@model", "virtio-scsi"); + assertXpath(domainDoc, prefix + "/controller/address/@type", "pci"); + assertXpath(domainDoc, prefix + "/controller/driver/@queues", String.valueOf(to.getCpus())); + } - assertNodeExists(domainDoc, "/domain/cpu"); + private void verifyClock(Document domainDoc) { + assertXpath(domainDoc, "/domain/clock/@offset", "utc"); + } + + private void verifyGraphicsDevices(VirtualMachineTO to, Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/graphics/@type", "vnc"); + assertXpath(domainDoc, prefix + "/graphics/@listen", to.getVncAddr()); + assertXpath(domainDoc, prefix + "/graphics/@autoport", "yes"); + assertXpath(domainDoc, prefix + "/graphics/@passwd", to.getVncPassword()); + } + + private void verifySerialDevices(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/serial/@type", "pty"); + assertXpath(domainDoc, prefix + "/serial/target/@port", "0"); + } + + private void verifyOsBoot(Document domainDoc) { assertNodeExists(domainDoc, "/domain/os/boot[@dev='cdrom']"); assertNodeExists(domainDoc, "/domain/os/boot[@dev='hd']"); + } + + private void verifyOsType(Document domainDoc) { + assertXpath(domainDoc, "/domain/os/type/@machine", "pc"); + assertXpath(domainDoc, "/domain/os/type/text()", "hvm"); + } + private void verifyPoliticOn_(Document domainDoc) { assertXpath(domainDoc, "/domain/on_reboot/text()", "restart"); assertXpath(domainDoc, "/domain/on_poweroff/text()", "destroy"); assertXpath(domainDoc, "/domain/on_crash/text()", "destroy"); + } + + private void verifyFeatures(Document domainDoc) { + assertNodeExists(domainDoc, "/domain/features/pae"); + assertNodeExists(domainDoc, "/domain/features/apic"); + assertNodeExists(domainDoc, "/domain/features/acpi"); + } + + private void verifyHeader(Document domainDoc, String hvsType, String name, String uuid, String os) { + assertXpath(domainDoc, "/domain/@type", hvsType); + assertXpath(domainDoc, "/domain/name/text()", name); + assertXpath(domainDoc, "/domain/uuid/text()", uuid); + assertXpath(domainDoc, "/domain/description/text()", os); + } + + private void verifyDevices(DevicesDef devicesDef, VirtualMachineTO to) { + Document domainDoc = parse(devicesDef.toString()); + + verifyWatchDogDevices(domainDoc, "/devices"); + verifyConsoleDevices(domainDoc, "/devices"); + verifySerialDevices(domainDoc, "/devices"); + verifyGraphicsDevices(to, domainDoc, "/devices"); + verifyChannelDevices(to, domainDoc, "/devices"); + verifyTabletInputDevice(domainDoc, "/devices"); + } + + private void verifySysInfo(GuestDef guestDef, String type, String uuid, String machine) { + // Need put because the string of guestdef generate two root element in XML, raising a error in parse. + String xml = "\n" + guestDef.toString() + ""; - assertXpath(domainDoc, "/domain/devices/watchdog/@model", "i6300esb"); - assertXpath(domainDoc, "/domain/devices/watchdog/@action", "none"); + Document domainDoc = parse(xml); + assertXpath(domainDoc, "/guestdef/sysinfo/@type", type); + assertNodeExists(domainDoc, "/guestdef/sysinfo/system/entry[@name='manufacturer']"); + assertNodeExists(domainDoc, "/guestdef/sysinfo/system/entry[@name='product']"); + assertXpath(domainDoc, "/guestdef/sysinfo/system/entry[@name='uuid']/text()", uuid); + assertXpath(domainDoc, "/guestdef/os/type/@machine", machine); } static Document parse(final String input) { From e19f2a5cc64b13d0779b52ea2670c414c0172aeb Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Wed, 23 Jun 2021 12:17:53 -0300 Subject: [PATCH 03/22] Fix test --- .../LibvirtComputingResourceTest.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 1bed1e85c02e..d098f49d91a1 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -308,7 +308,24 @@ public void testCreateVMFromSpecWithTopology6() { */ @Test public void testCreateVMFromSpecWithTopology4() { - VirtualMachineTO to = createDefaultVM(false); + final int id = random.nextInt(65534); + final String name = "test-instance-1"; + + final int cpus = 8; + final int minSpeed = 1024; + final int maxSpeed = 2048; + final int minRam = 256 * 1024; + final int maxRam = 512 * 1024; + + final String os = "Ubuntu"; + + final String vncAddr = ""; + final String vncPassword = "mySuperSecretPassword"; + + final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); + to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); From 631532b90442e66e121c52b6c9839717cb267ab2 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 24 Jun 2021 11:54:22 -0300 Subject: [PATCH 04/22] Extract if block to method for add extra configs to VM Domain XML --- .../hypervisor/kvm/resource/LibvirtComputingResource.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 7fe5ac340a49..ac822beec178 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 @@ -2357,7 +2357,13 @@ private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map extraConfig) { if (MapUtils.isNotEmpty(extraConfig) && VirtualMachine.Type.User.equals(vmTO.getType())) { s_logger.debug(String.format("Appending extra configuration data [%s] to guest VM [%s] domain XML.", extraConfig, vmTO.toString())); addExtraConfigComponent(extraConfig, vm); From 827fd22574f15e1cdf62b97b3566c69a137d7f1d Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Wed, 30 Jun 2021 17:21:39 -0300 Subject: [PATCH 05/22] Split travis tests trying to isolate which test is causing an error --- .travis.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2174ddb1428e..fef9c8f0578f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,21 +52,25 @@ env: smoke/test_async_job smoke/test_backup_recovery_dummy smoke/test_create_list_domain_account_project - smoke/test_create_network - smoke/test_deploy_vgpu_enabled_vm + smoke/test_create_network" + + - TESTS="smoke/test_deploy_vgpu_enabled_vm smoke/test_deploy_vm_extra_config_data smoke/test_deploy_vm_iso smoke/test_deploy_vm_root_resize smoke/test_deploy_vm_with_userdata - smoke/test_deploy_vms_with_varied_deploymentplanners - smoke/test_diagnostics + smoke/test_deploy_vms_with_varied_deploymentplanners" + + - TESTS="smoke/test_diagnostics smoke/test_disk_offerings smoke/test_dynamicroles smoke/test_global_settings - smoke/test_guest_vlan_range - smoke/test_host_annotations + smoke/test_guest_vlan_range" + + - TESTS="smoke/test_host_annotations smoke/test_host_maintenance smoke/test_hostha_simulator" + - TESTS="smoke/test_internal_lb smoke/test_iso From b1bbc53b0ccd04fda726128046b94bc32035f47b Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 1 Jul 2021 11:49:06 -0300 Subject: [PATCH 06/22] Override toString() method --- .../main/java/com/cloud/agent/api/to/VirtualMachineTO.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java index c4729383dd4f..dabe6977d243 100644 --- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java @@ -413,4 +413,9 @@ public DeployAsIsInfoTO getDeployAsIsInfo() { public void setDeployAsIsInfo(DeployAsIsInfoTO deployAsIsInfo) { this.deployAsIsInfo = deployAsIsInfo; } + + @Override + public String toString() { + return String.format("VM {\"id\": %s, \"name\": \"%s\", \"uuid\": \"%s\", \"type\": \"%s\"}", id, name, uuid, type); + } } From ff482d9718346099480d1433927953bea371dca1 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 1 Jul 2021 11:50:56 -0300 Subject: [PATCH 07/22] Update documentation --- .../resource/LibvirtComputingResource.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) 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 ac822beec178..7d202ffc7adb 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 @@ -261,12 +261,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv */ private static final String PAE = "pae"; /** - * Libvirt only suport guest cpu mode in versions from 0.9.10. + * Libvirt supports guest CPU mode since 0.9.10. */ private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_MODE = 9010; + /** + * The CPU tune element provides details of the CPU tunable parameters for the domain.
+ * It is supported since Libvirt 0.9.0 + */ private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_TUNE = 9000; /** - * Verify if guest is ARM64 + * Constant that defines ARM64 (aarch64) guest architectures. */ private static final String AARCH64 = "aarch64"; @@ -2326,7 +2330,7 @@ public LibvirtVMDef createVMFromSpec(final VirtualMachineTO vmTO) { } /** - * Configure created VM from specification, adding the necessary components to VM. + * Configures created VM from specification, adding the necessary components to VM. */ private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map customParams, boolean isUefiEnabled, boolean isSecureBoot, String bootMode, Map extraConfig, String uuid) { @@ -2361,7 +2365,7 @@ private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map extraConfig) { if (MapUtils.isNotEmpty(extraConfig) && VirtualMachine.Type.User.equals(vmTO.getType())) { @@ -2371,7 +2375,7 @@ private void addExtraConfigsToVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map + * The respective Virtio SCSI XML definition is generated only if the VM's Disk Bus is of ISCSI. */ protected SCSIDef createSCSIDef(int vcpus) { return new SCSIDef((short)0, 0, 0, 9, 0, vcpus); @@ -2561,7 +2566,7 @@ private boolean isGuestAarch64() { } /** - * Create a guest definition from a VM specification. + * Creates a guest definition from a VM specification. */ protected GuestDef createGuestFromSpec(VirtualMachineTO vmTO, LibvirtVMDef vm, String uuid, Map customParams) { GuestDef guest = new GuestDef(); @@ -2611,7 +2616,7 @@ private void configureGuestAndUserVMToUseLXC(LibvirtVMDef vm, GuestDef guest) { } /** - * Add extra configurations (if any) as a String component to the domain XML + * Adds extra configurations (if any) as a String component to the domain XML */ protected void addExtraConfigComponent(Map extraConfig, LibvirtVMDef vm) { if (MapUtils.isNotEmpty(extraConfig)) { From f9f2de765cf24aef9ba580d4fe5bb3b80ac2ad81 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 1 Jul 2021 12:00:07 -0300 Subject: [PATCH 08/22] Fix checkstyle error (line with trailing spaces) --- api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java index dabe6977d243..5f03b2772fce 100644 --- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java @@ -413,7 +413,7 @@ public DeployAsIsInfoTO getDeployAsIsInfo() { public void setDeployAsIsInfo(DeployAsIsInfoTO deployAsIsInfo) { this.deployAsIsInfo = deployAsIsInfo; } - + @Override public String toString() { return String.format("VM {\"id\": %s, \"name\": \"%s\", \"uuid\": \"%s\", \"type\": \"%s\"}", id, name, uuid, type); From fb37ef5c6fd0c3b6bfbfb9aa537ff740e2cf8c72 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 1 Jul 2021 16:57:53 -0300 Subject: [PATCH 09/22] Change VirtualMachineTO print of object --- api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java index 5f03b2772fce..8a30b5ef9fee 100644 --- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java @@ -416,6 +416,6 @@ public void setDeployAsIsInfo(DeployAsIsInfoTO deployAsIsInfo) { @Override public String toString() { - return String.format("VM {\"id\": %s, \"name\": \"%s\", \"uuid\": \"%s\", \"type\": \"%s\"}", id, name, uuid, type); + return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type); } } From 7f49350a2d776ba80e48d7d7420e5f2c14f32840 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Fri, 2 Jul 2021 11:14:45 -0300 Subject: [PATCH 10/22] Add try except to find message error. Remove after test --- .../smoke/test_deploy_vm_root_resize.py | 293 +++++++++--------- 1 file changed, 149 insertions(+), 144 deletions(-) diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py index f3b42a389b95..62a4a5fe4573 100644 --- a/test/integration/smoke/test_deploy_vm_root_resize.py +++ b/test/integration/smoke/test_deploy_vm_root_resize.py @@ -206,114 +206,116 @@ def test_00_deploy_vm_root_resize(self): # 2. root disk has new size per listVolumes # 3. Rejects non-supported hypervisor types """ - - newrootsize = (self.template.size >> 30) + 2 - if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' - or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): - - accounts = Account.list(self.apiclient, id=self.account.id) - self.assertEqual(validateList(accounts)[0], PASS, - "accounts list validation failed") - initialResourceCount = int(accounts[0].primarystoragetotal) - - if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - else: - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - - list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) - self.debug( - "Verify listVirtualMachines response for virtual machine: %s" \ - % self.virtual_machine.id - ) - - res=validateList(list_vms) - self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " - "response") - self.cleanup.append(self.virtual_machine) - - vm = list_vms[0] - self.assertEqual( - vm.id, - self.virtual_machine.id, - "Virtual Machine ids do not match" - ) - self.assertEqual( - vm.name, - self.virtual_machine.name, - "Virtual Machine names do not match" - ) - self.assertEqual( - vm.state, - "Running", - msg="VM is not in Running state" - ) - - # get root vol from created vm, verify it is correct size - list_volume_response = list_volumes( - self.apiclient, - virtualmachineid=self.virtual_machine.id, - type='ROOT', - listall=True - ) - res=validateList(list_volume_response) - self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " - "response") - rootvolume = list_volume_response[0] - success = False - if rootvolume is not None and rootvolume.size == (newrootsize << 30): - success = True - - self.assertEqual( - success, - True, - "Check if the root volume resized appropriately" - ) - - response = matchResourceCount( - self.apiclient, (initialResourceCount + newrootsize), - RESOURCE_PRIMARY_STORAGE, - accountid=self.account.id) - self.assertEqual(response[0], PASS, response[1]) - else: - self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) - newrootsize = (self.template.size >> 30) + 2 - success = False - try: - self.virtual_machine = VirtualMachine.create( - self.apiclient, - self.testdata["virtual_machine"], - accountid=self.account.name, - zoneid=self.zone.id, - domainid=self.account.domainid, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - except Exception as ex: - if re.search("Hypervisor \S+ does not support rootdisksize override", str(ex)): - success = True - else: - self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - - self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) - + try: + newrootsize = (self.template.size >> 30) + 2 + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): + + accounts = Account.list(self.apiclient, id=self.account.id) + self.assertEqual(validateList(accounts)[0], PASS, + "accounts list validation failed") + initialResourceCount = int(accounts[0].primarystoragetotal) + + if self.hypervisor=="vmware": + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + res=validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") + self.cleanup.append(self.virtual_machine) + + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + + # get root vol from created vm, verify it is correct size + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + res=validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") + rootvolume = list_volume_response[0] + success = False + if rootvolume is not None and rootvolume.size == (newrootsize << 30): + success = True + + self.assertEqual( + success, + True, + "Check if the root volume resized appropriately" + ) + + response = matchResourceCount( + self.apiclient, (initialResourceCount + newrootsize), + RESOURCE_PRIMARY_STORAGE, + accountid=self.account.id) + self.assertEqual(response[0], PASS, response[1]) + else: + self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) + newrootsize = (self.template.size >> 30) + 2 + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if re.search("Hypervisor \S+ does not support rootdisksize override", str(ex)): + success = True + else: + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) + except Exception as ex: + print(ex) + @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="false") def test_01_deploy_vm_root_resize(self): """Test proper failure to deploy virtual machine with rootdisksize of 0 @@ -358,42 +360,45 @@ def test_01_deploy_vm_root_resize(self): def test_02_deploy_vm_root_resize(self): """Test proper failure to deploy virtual machine with rootdisksize less than template size """ - newrootsize = (self.template.size >> 30) - 1 - success=False - self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") - - if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' - or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): - try: - if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - else: - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - except Exception as ex: - if "rootdisksize override is smaller than template size" in str(ex): - success = True - else: - self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - - self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") - else: - self.debug("test 02 does not support hypervisor type " + self.hypervisor) + try: + newrootsize = (self.template.size >> 30) - 1 + success=False + self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") + + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): + try: + if self.hypervisor=="vmware": + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if "rootdisksize override is smaller than template size" in str(ex): + success = True + else: + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") + else: + self.debug("test 02 does not support hypervisor type " + self.hypervisor) + except Exception as ex: + print(ex) From 62f8a2c5e59d86e98e1247abf9ecb9a923769cbf Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Fri, 2 Jul 2021 18:36:18 -0300 Subject: [PATCH 11/22] Fix indent --- .../smoke/test_deploy_vm_root_resize.py | 294 +++++++++--------- 1 file changed, 147 insertions(+), 147 deletions(-) diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py index 62a4a5fe4573..37afd713650b 100644 --- a/test/integration/smoke/test_deploy_vm_root_resize.py +++ b/test/integration/smoke/test_deploy_vm_root_resize.py @@ -206,116 +206,116 @@ def test_00_deploy_vm_root_resize(self): # 2. root disk has new size per listVolumes # 3. Rejects non-supported hypervisor types """ - try: - newrootsize = (self.template.size >> 30) + 2 - if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' - or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): - - accounts = Account.list(self.apiclient, id=self.account.id) - self.assertEqual(validateList(accounts)[0], PASS, - "accounts list validation failed") - initialResourceCount = int(accounts[0].primarystoragetotal) - - if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - else: - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - - list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) - self.debug( - "Verify listVirtualMachines response for virtual machine: %s" \ - % self.virtual_machine.id - ) - - res=validateList(list_vms) - self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " - "response") - self.cleanup.append(self.virtual_machine) - - vm = list_vms[0] - self.assertEqual( - vm.id, - self.virtual_machine.id, - "Virtual Machine ids do not match" - ) - self.assertEqual( - vm.name, - self.virtual_machine.name, - "Virtual Machine names do not match" - ) - self.assertEqual( - vm.state, - "Running", - msg="VM is not in Running state" - ) - - # get root vol from created vm, verify it is correct size - list_volume_response = list_volumes( - self.apiclient, - virtualmachineid=self.virtual_machine.id, - type='ROOT', - listall=True - ) - res=validateList(list_volume_response) - self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " - "response") - rootvolume = list_volume_response[0] - success = False - if rootvolume is not None and rootvolume.size == (newrootsize << 30): - success = True - - self.assertEqual( - success, - True, - "Check if the root volume resized appropriately" - ) - - response = matchResourceCount( - self.apiclient, (initialResourceCount + newrootsize), - RESOURCE_PRIMARY_STORAGE, - accountid=self.account.id) - self.assertEqual(response[0], PASS, response[1]) - else: - self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) - newrootsize = (self.template.size >> 30) + 2 - success = False - try: - self.virtual_machine = VirtualMachine.create( - self.apiclient, - self.testdata["virtual_machine"], - accountid=self.account.name, - zoneid=self.zone.id, - domainid=self.account.domainid, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - except Exception as ex: - if re.search("Hypervisor \S+ does not support rootdisksize override", str(ex)): - success = True - else: - self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - - self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) - except Exception as ex: - print(ex) - + try: + newrootsize = (self.template.size >> 30) + 2 + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): + + accounts = Account.list(self.apiclient, id=self.account.id) + self.assertEqual(validateList(accounts)[0], PASS, + "accounts list validation failed") + initialResourceCount = int(accounts[0].primarystoragetotal) + + if self.hypervisor=="vmware": + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + res=validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") + self.cleanup.append(self.virtual_machine) + + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + + # get root vol from created vm, verify it is correct size + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + res=validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") + rootvolume = list_volume_response[0] + success = False + if rootvolume is not None and rootvolume.size == (newrootsize << 30): + success = True + + self.assertEqual( + success, + True, + "Check if the root volume resized appropriately" + ) + + response = matchResourceCount( + self.apiclient, (initialResourceCount + newrootsize), + RESOURCE_PRIMARY_STORAGE, + accountid=self.account.id) + self.assertEqual(response[0], PASS, response[1]) + else: + self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) + newrootsize = (self.template.size >> 30) + 2 + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if re.search("Hypervisor \S+ does not support rootdisksize override", str(ex)): + success = True + else: + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) + except Exception as ex: + print(ex) + @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="false") def test_01_deploy_vm_root_resize(self): """Test proper failure to deploy virtual machine with rootdisksize of 0 @@ -361,44 +361,44 @@ def test_02_deploy_vm_root_resize(self): """Test proper failure to deploy virtual machine with rootdisksize less than template size """ try: - newrootsize = (self.template.size >> 30) - 1 - success=False - self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") - - if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' - or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): - try: - if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - else: - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - except Exception as ex: - if "rootdisksize override is smaller than template size" in str(ex): - success = True - else: - self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - - self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") - else: - self.debug("test 02 does not support hypervisor type " + self.hypervisor) + newrootsize = (self.template.size >> 30) - 1 + success=False + self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") + + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): + try: + if self.hypervisor=="vmware": + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if "rootdisksize override is smaller than template size" in str(ex): + success = True + else: + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") + else: + self.debug("test 02 does not support hypervisor type " + self.hypervisor) except Exception as ex: - print(ex) + print(ex) From 3a5dde98b34b9041d3f03d8665599d34da5537c3 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Mon, 5 Jul 2021 10:54:53 -0300 Subject: [PATCH 12/22] Trying to understanding why is happening in this code --- test/integration/smoke/test_deploy_vm_root_resize.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py index 37afd713650b..ac54726bfbd0 100644 --- a/test/integration/smoke/test_deploy_vm_root_resize.py +++ b/test/integration/smoke/test_deploy_vm_root_resize.py @@ -207,6 +207,7 @@ def test_00_deploy_vm_root_resize(self): # 3. Rejects non-supported hypervisor types """ try: + print(f'Self template is {self.template}') newrootsize = (self.template.size >> 30) + 2 if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): @@ -314,7 +315,7 @@ def test_00_deploy_vm_root_resize(self): self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) except Exception as ex: - print(ex) + print(f'Error is {ex}') @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="false") def test_01_deploy_vm_root_resize(self): @@ -361,6 +362,7 @@ def test_02_deploy_vm_root_resize(self): """Test proper failure to deploy virtual machine with rootdisksize less than template size """ try: + print(f'Self template is {self.template}') newrootsize = (self.template.size >> 30) - 1 success=False self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") @@ -398,7 +400,7 @@ def test_02_deploy_vm_root_resize(self): else: self.debug("test 02 does not support hypervisor type " + self.hypervisor) except Exception as ex: - print(ex) + print(f'Error is {ex}') From cc8df0f201fbad67755d475b41ebf8cc3a0e52fe Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Mon, 21 Jun 2021 18:12:27 -0300 Subject: [PATCH 13/22] Refactor method createVMFromSpec --- .../resource/LibvirtComputingResource.java | 458 ++++++++++++------ 1 file changed, 308 insertions(+), 150 deletions(-) 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 8b7932652c0b..7fe5ac340a49 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 @@ -209,6 +209,67 @@ public class LibvirtComputingResource extends ServerResourceBase implements ServerResource, VirtualRouterDeployer { private static final Logger s_logger = Logger.getLogger(LibvirtComputingResource.class); + private static final String LEGACY = "legacy"; + private static final String SECURE = "secure"; + + /** + * Machine type. + */ + private static final String PC = "pc"; + private static final String VIRT = "virt"; + + /** + * Possible devices to add to VM. + */ + private static final String TABLET = "tablet"; + private static final String USB = "usb"; + private static final String MOUSE = "mouse"; + private static final String KEYBOARD = "keyboard"; + + /** + * Policies used by VM. + */ + private static final String RESTART = "restart"; + private static final String DESTROY = "destroy"; + + private static final String KVMCLOCK = "kvmclock"; + private static final String HYPERVCLOCK = "hypervclock"; + private static final String WINDOWS = "Windows"; + private static final String Q35 = "q35"; + private static final String PTY = "pty"; + private static final String VNC = "vnc"; + + /** + * Acronym of System Management Mode. Perform low-level system management operations while an OS is running. + */ + private static final String SMM = "smm"; + /** + * Acronym of Advanced Configuration and Power Interface.
+ * Provides an open standard that operating systems can use to discover and configure + * computer hardware components, to perform power management. + */ + private static final String ACPI = "acpi"; + /** + * Acronym of Advanced Programmable Interrupt Controllers.
+ * With an I/O APIC, operating systems can use more than 16 interrupt requests (IRQs) + * and therefore avoid IRQ sharing for improved reliability. + */ + private static final String APIC = "apic"; + /** + * Acronym of Physical Address Extension. Feature implemented in modern x86 processors.
+ * PAE extends memory addressing capabilities, allowing more than 4 GB of random access memory (RAM) to be used. + */ + private static final String PAE = "pae"; + /** + * Libvirt only suport guest cpu mode in versions from 0.9.10. + */ + private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_MODE = 9010; + private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_TUNE = 9000; + /** + * Verify if guest is ARM64 + */ + private static final String AARCH64 = "aarch64"; + private String _modifyVlanPath; private String _versionstringpath; private String _patchScriptPath; @@ -2227,8 +2288,13 @@ protected void enlightenWindowsVm(VirtualMachineTO vmTO, FeaturesDef features) { } } + /** + * Creates VM KVM definitions from virtual machine transfer object specifications. + */ public LibvirtVMDef createVMFromSpec(final VirtualMachineTO vmTO) { - final LibvirtVMDef vm = new LibvirtVMDef(); + s_logger.debug(String.format("Creating VM from specifications [%s]", vmTO.toString())); + + LibvirtVMDef vm = new LibvirtVMDef(); vm.setDomainName(vmTO.getName()); String uuid = vmTO.getUuid(); uuid = getUuid(uuid); @@ -2239,211 +2305,303 @@ public LibvirtVMDef createVMFromSpec(final VirtualMachineTO vmTO) { Map customParams = vmTO.getDetails(); boolean isUefiEnabled = false; boolean isSecureBoot = false; - String bootMode =null; + String bootMode = null; + if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) { isUefiEnabled = true; - bootMode = customParams.get(GuestDef.BootType.UEFI.toString()); - if (StringUtils.isNotBlank(bootMode) && "secure".equalsIgnoreCase(bootMode)) { + s_logger.debug(String.format("Enabled UEFI for VM UUID [%s].", uuid)); + + if (isSecureMode(customParams.get(GuestDef.BootType.UEFI.toString()))) { + s_logger.debug(String.format("Enabled Secure Boot for VM UUID [%s].", uuid)); isSecureBoot = true; } } Map extraConfig = vmTO.getExtraConfig(); if (dpdkSupport && (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA) || !extraConfig.containsKey(DpdkHelper.DPDK_HUGE_PAGES))) { - s_logger.info("DPDK is enabled but it needs extra configurations for CPU NUMA and Huge Pages for VM deployment"); + s_logger.info(String.format("DPDK is enabled for VM [%s], but it needs extra configurations for CPU NUMA and Huge Pages for VM deployment.", vmTO.toString())); } + configureVM(vmTO, vm, customParams, isUefiEnabled, isSecureBoot, bootMode, extraConfig, uuid); + return vm; + } - final GuestDef guest = new GuestDef(); + /** + * Configure created VM from specification, adding the necessary components to VM. + */ + private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map customParams, boolean isUefiEnabled, boolean isSecureBoot, String bootMode, + Map extraConfig, String uuid) { + s_logger.debug(String.format("Configuring VM with UUID [%s].", uuid)); - if (HypervisorType.LXC == _hypervisorType && VirtualMachine.Type.User == vmTO.getType()) { - // LXC domain is only valid for user VMs. Use KVM for system VMs. - guest.setGuestType(GuestDef.GuestType.LXC); - vm.setHvsType(HypervisorType.LXC.toString().toLowerCase()); - } else { - guest.setGuestType(GuestDef.GuestType.KVM); - vm.setHvsType(HypervisorType.KVM.toString().toLowerCase()); - vm.setLibvirtVersion(_hypervisorLibvirtVersion); - vm.setQemuVersion(_hypervisorQemuVersion); + GuestDef guest = createGuestFromSpec(vmTO, vm, uuid, customParams); + if (isUefiEnabled) { + configureGuestIfUefiEnabled(isSecureBoot, bootMode, guest); } - guest.setGuestArch(_guestCpuArch != null ? _guestCpuArch : vmTO.getArch()); - guest.setMachineType(_guestCpuArch != null && _guestCpuArch.equals("aarch64") ? "virt" : "pc"); - guest.setBootType(GuestDef.BootType.BIOS); - 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.setBootMode(GuestDef.BootMode.SECURE); // setting to secure mode - } + + vm.addComp(guest); + vm.addComp(createGuestResourceDef(vmTO)); + + int vcpus = vmTO.getCpus(); + if (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA)) { + vm.addComp(createCpuModeDef(vmTO, vcpus)); } - guest.setUuid(uuid); - guest.setBootOrder(GuestDef.BootOrder.CDROM); - guest.setBootOrder(GuestDef.BootOrder.HARDISK); - if (isUefiEnabled) { - if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) { - guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_SECURE)); - } + if (_hypervisorLibvirtVersion >= MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_TUNE) { + vm.addComp(createCpuTuneDef(vmTO)); + } - if (_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY) != null && "legacy".equalsIgnoreCase(bootMode)) { - guest.setLoader(_uefiProperties.getProperty(GuestDef.GUEST_LOADER_LEGACY)); - } + FeaturesDef features = createFeaturesDef(customParams, isUefiEnabled, isSecureBoot); + enlightenWindowsVm(vmTO, features); + vm.addComp(features); - if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH) != null) { - guest.setNvram(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH)); - } + vm.addComp(createTermPolicy()); + vm.addComp(createClockDef(vmTO)); + vm.addComp(createDevicesDef(vmTO, guest, vcpus, isUefiEnabled)); - if (isSecureBoot) { - if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE) != null && "secure".equalsIgnoreCase(bootMode)) { - guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE)); - } - } else { - if (_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY) != null) { - guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY)); - } - } + // Add extra configuration to User VM Domain XML before starting + if (MapUtils.isNotEmpty(extraConfig) && VirtualMachine.Type.User.equals(vmTO.getType())) { + s_logger.debug(String.format("Appending extra configuration data [%s] to guest VM [%s] domain XML.", extraConfig, vmTO.toString())); + addExtraConfigComponent(extraConfig, vm); + } + } + + /** + * Add devices components to VM. + */ + protected DevicesDef createDevicesDef(VirtualMachineTO vmTO, GuestDef guest, int vcpus, boolean isUefiEnabled) { + DevicesDef devices = new DevicesDef(); + devices.setEmulatorPath(_hypervisorPath); + devices.setGuestType(guest.getGuestType()); + devices.addDevice(createSerialDef()); + + if (_rngEnable) { + devices.addDevice(createRngDef()); } - vm.addComp(guest); + devices.addDevice(createChannelDef(vmTO)); + devices.addDevice(createWatchDogDef()); + devices.addDevice(createVideoDef()); + devices.addDevice(createConsoleDef()); + devices.addDevice(createGraphicDef(vmTO)); + devices.addDevice(createTabletInputDef()); - final GuestResourceDef grd = new GuestResourceDef(); + if (isGuestAarch64()) { + createArm64UsbDef(devices); + } - if (vmTO.getMinRam() != vmTO.getMaxRam() && !_noMemBalloon) { - grd.setMemBalloning(true); - grd.setCurrentMem(vmTO.getMinRam() / 1024); - grd.setMemorySize(vmTO.getMaxRam() / 1024); - } else { - grd.setMemorySize(vmTO.getMaxRam() / 1024); + DiskDef.DiskBus busT = getDiskModelFromVMDetail(vmTO); + if (busT == null) { + busT = getGuestDiskModel(vmTO.getPlatformEmulator(), isUefiEnabled); } - final int vcpus = vmTO.getCpus(); - grd.setVcpuNum(vcpus); - vm.addComp(grd); - if (!extraConfig.containsKey(DpdkHelper.DPDK_NUMA)) { - final CpuModeDef cmd = new CpuModeDef(); - cmd.setMode(_guestCpuMode); - cmd.setModel(_guestCpuModel); - if (vmTO.getType() == VirtualMachine.Type.User) { - cmd.setFeatures(_cpuFeatures); - } - setCpuTopology(cmd, vcpus, vmTO.getDetails()); - vm.addComp(cmd); + if (busT == DiskDef.DiskBus.SCSI) { + devices.addDevice(createSCSIDef(vcpus)); } + return devices; + } - if (_hypervisorLibvirtVersion >= 9000) { - final CpuTuneDef ctd = new CpuTuneDef(); - /** - A 4.0.X/4.1.X management server doesn't send the correct JSON - command for getMinSpeed, it only sends a 'speed' field. + protected WatchDogDef createWatchDogDef() { + return new WatchDogDef(_watchDogAction, _watchDogModel); + } - So if getMinSpeed() returns null we fall back to getSpeed(). + /* + * Add an explicit USB devices for ARM64 + */ + protected void createArm64UsbDef(DevicesDef devices) { + devices.addDevice(new InputDef(KEYBOARD, USB)); + devices.addDevice(new InputDef(MOUSE, USB)); + devices.addDevice(new LibvirtVMDef.USBDef((short)0, 0, 5, 0, 0)); + } - This way a >4.1 agent can work communicate a <=4.1 management server + protected InputDef createTabletInputDef() { + return new InputDef(TABLET, USB); + } - This change is due to the overcommit feature in 4.2 - */ - if (vmTO.getMinSpeed() != null) { - ctd.setShares(vmTO.getCpus() * vmTO.getMinSpeed()); - } else { - ctd.setShares(vmTO.getCpus() * vmTO.getSpeed()); - } + /** + * Add the VNC port passwd here, get the passwd from the vmInstance. + */ + protected GraphicDef createGraphicDef(VirtualMachineTO vmTO) { + return new GraphicDef(VNC, (short)0, true, vmTO.getVncAddr(), vmTO.getVncPassword(), null); + } - setQuotaAndPeriod(vmTO, ctd); + /** + * Add a VirtIO channel for the Qemu Guest Agent tools. + */ + protected ChannelDef createChannelDef(VirtualMachineTO vmTO) { + File virtIoChannel = Paths.get(_qemuSocketsPath.getPath(), vmTO.getName() + "." + _qemuGuestAgentSocketName).toFile(); + return new ChannelDef(_qemuGuestAgentSocketName, ChannelDef.ChannelType.UNIX, virtIoChannel); + } - vm.addComp(ctd); - } + /** + * If we're using virtio scsi, then we need to add a virtual scsi controller. + */ + protected SCSIDef createSCSIDef(int vcpus) { + return new SCSIDef((short)0, 0, 0, 9, 0, vcpus); + } - final FeaturesDef features = new FeaturesDef(); - features.addFeatures("pae"); - features.addFeatures("apic"); - features.addFeatures("acpi"); - if (isUefiEnabled && isSecureMode(customParams.get(GuestDef.BootType.UEFI.toString()))) { - features.addFeatures("smm"); - } + protected ConsoleDef createConsoleDef() { + return new ConsoleDef(PTY, null, null, (short)0); + } - //KVM hyperv enlightenment features based on OS Type - enlightenWindowsVm(vmTO, features); + protected VideoDef createVideoDef() { + return new VideoDef(_videoHw, _videoRam); + } - vm.addComp(features); + protected RngDef createRngDef() { + return new RngDef(_rngPath, _rngBackendModel, _rngRateBytes, _rngRatePeriod); + } - final TermPolicy term = new TermPolicy(); - term.setCrashPolicy("destroy"); - term.setPowerOffPolicy("destroy"); - term.setRebootPolicy("restart"); - vm.addComp(term); + protected SerialDef createSerialDef() { + return new SerialDef(PTY, null, (short)0); + } - final ClockDef clock = new ClockDef(); - if (vmTO.getOs().startsWith("Windows")) { + protected ClockDef createClockDef(final VirtualMachineTO vmTO) { + ClockDef clock = new ClockDef(); + if (org.apache.commons.lang.StringUtils.startsWith(vmTO.getOs(), WINDOWS)) { clock.setClockOffset(ClockDef.ClockOffset.LOCALTIME); - clock.setTimer("hypervclock", null, null); - } else if (vmTO.getType() != VirtualMachine.Type.User || isGuestPVEnabled(vmTO.getOs())) { - if (_hypervisorLibvirtVersion >= 9 * 1000 + 10) { - clock.setTimer("kvmclock", null, null, _noKvmClock); - } + clock.setTimer(HYPERVCLOCK, null, null); + } else if ((vmTO.getType() != VirtualMachine.Type.User || isGuestPVEnabled(vmTO.getOs())) && _hypervisorLibvirtVersion >= MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_MODE) { + clock.setTimer(KVMCLOCK, null, null, _noKvmClock); } + return clock; + } - vm.addComp(clock); + protected TermPolicy createTermPolicy() { + TermPolicy term = new TermPolicy(); + term.setCrashPolicy(DESTROY); + term.setPowerOffPolicy(DESTROY); + term.setRebootPolicy(RESTART); + return term; + } - final DevicesDef devices = new DevicesDef(); - devices.setEmulatorPath(_hypervisorPath); - devices.setGuestType(guest.getGuestType()); + protected FeaturesDef createFeaturesDef(Map customParams, boolean isUefiEnabled, boolean isSecureBoot) { + FeaturesDef features = new FeaturesDef(); + features.addFeatures(PAE); + features.addFeatures(APIC); + features.addFeatures(ACPI); + if (isUefiEnabled && isSecureBoot) { + features.addFeatures(SMM); + } + return features; + } - final SerialDef serial = new SerialDef("pty", null, (short)0); - devices.addDevice(serial); + /** + * A 4.0.X/4.1.X management server doesn't send the correct JSON + * command for getMinSpeed, it only sends a 'speed' field.
+ * So, to create a cpu tune, if getMinSpeed() returns null we fall back to getSpeed().
+ * This way a >4.1 agent can work communicate a <=4.1 management server.
+ * This change is due to the overcommit feature in 4.2. + */ + protected CpuTuneDef createCpuTuneDef(VirtualMachineTO vmTO) { + CpuTuneDef ctd = new CpuTuneDef(); + int shares = vmTO.getCpus() * (vmTO.getMinSpeed() != null ? vmTO.getMinSpeed() : vmTO.getSpeed()); + ctd.setShares(shares); + setQuotaAndPeriod(vmTO, ctd); + return ctd; + } - if (_rngEnable) { - final RngDef rngDevice = new RngDef(_rngPath, _rngBackendModel, _rngRateBytes, _rngRatePeriod); - devices.addDevice(rngDevice); + private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) { + final CpuModeDef cmd = new CpuModeDef(); + cmd.setMode(_guestCpuMode); + cmd.setModel(_guestCpuModel); + if (VirtualMachine.Type.User.equals(vmTO.getType())) { + cmd.setFeatures(_cpuFeatures); } + setCpuTopology(cmd, vcpus, vmTO.getDetails()); + return cmd; + } - /* Add a VirtIO channel for the Qemu Guest Agent tools */ - File virtIoChannel = Paths.get(_qemuSocketsPath.getPath(), vmTO.getName() + "." + _qemuGuestAgentSocketName).toFile(); - devices.addDevice(new ChannelDef(_qemuGuestAgentSocketName, ChannelDef.ChannelType.UNIX, virtIoChannel)); - - devices.addDevice(new WatchDogDef(_watchDogAction, _watchDogModel)); + /** + * Creates guest resources based in VM specification. + */ + protected GuestResourceDef createGuestResourceDef(VirtualMachineTO vmTO) { + GuestResourceDef grd = new GuestResourceDef(); - final VideoDef videoCard = new VideoDef(_videoHw, _videoRam); - devices.addDevice(videoCard); + grd.setMemorySize(vmTO.getMaxRam() / 1024); + if (vmTO.getMinRam() != vmTO.getMaxRam() && !_noMemBalloon) { + grd.setMemBalloning(true); + grd.setCurrentMem(vmTO.getMinRam() / 1024); + } + grd.setVcpuNum(vmTO.getCpus()); + return grd; + } - final ConsoleDef console = new ConsoleDef("pty", null, null, (short)0); - devices.addDevice(console); + private void configureGuestIfUefiEnabled(boolean isSecureBoot, String bootMode, GuestDef guest) { + setGuestLoader(bootMode, SECURE, guest, GuestDef.GUEST_LOADER_SECURE); + setGuestLoader(bootMode, LEGACY, guest, GuestDef.GUEST_LOADER_LEGACY); - //add the VNC port passwd here, get the passwd from the vmInstance. - final String passwd = vmTO.getVncPassword(); - final GraphicDef grap = new GraphicDef("vnc", (short)0, true, vmTO.getVncAddr(), passwd, null); - devices.addDevice(grap); + if (isUefiPropertieNotNull(GuestDef.GUEST_NVRAM_PATH)) { + guest.setNvram(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_PATH)); + } - final InputDef input = new InputDef("tablet", "usb"); - devices.addDevice(input); + if (isSecureBoot && isUefiPropertieNotNull(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE) && SECURE.equalsIgnoreCase(bootMode)) { + guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_SECURE)); + } else if (isUefiPropertieNotNull(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY)) { + guest.setNvramTemplate(_uefiProperties.getProperty(GuestDef.GUEST_NVRAM_TEMPLATE_LEGACY)); + } + } - // Add an explicit USB devices for ARM64 - if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { - devices.addDevice(new InputDef("keyboard", "usb")); - devices.addDevice(new InputDef("mouse", "usb")); - devices.addDevice(new LibvirtVMDef.USBDef((short)0, 0, 5, 0, 0)); + private void setGuestLoader(String bootMode, String mode, GuestDef guest, String propertie) { + if (isUefiPropertieNotNull(propertie) && mode.equalsIgnoreCase(bootMode)) { + guest.setLoader(_uefiProperties.getProperty(propertie)); } + } - DiskDef.DiskBus busT = getDiskModelFromVMDetail(vmTO); + private boolean isUefiPropertieNotNull(String propertie) { + return _uefiProperties.getProperty(propertie) != null; + } - if (busT == null) { - busT = getGuestDiskModel(vmTO.getPlatformEmulator(), isUefiEnabled); - } + private boolean isGuestAarch64() { + return AARCH64.equals(_guestCpuArch); + } - // If we're using virtio scsi, then we need to add a virtual scsi controller - if (busT == DiskDef.DiskBus.SCSI) { - final SCSIDef sd = new SCSIDef((short)0, 0, 0, 9, 0, vcpus); - devices.addDevice(sd); - } + /** + * Create a guest definition from a VM specification. + */ + protected GuestDef createGuestFromSpec(VirtualMachineTO vmTO, LibvirtVMDef vm, String uuid, Map customParams) { + GuestDef guest = new GuestDef(); - vm.addComp(devices); + configureGuestAndVMHypervisorType(vmTO, vm, guest); + guest.setGuestArch(_guestCpuArch != null ? _guestCpuArch : vmTO.getArch()); + guest.setMachineType(isGuestAarch64() ? VIRT : PC); + guest.setBootType(GuestDef.BootType.BIOS); + if (MapUtils.isNotEmpty(customParams) && customParams.containsKey(GuestDef.BootType.UEFI.toString())) { + guest.setBootType(GuestDef.BootType.UEFI); + guest.setBootMode(GuestDef.BootMode.LEGACY); + guest.setMachineType(Q35); + if (SECURE.equalsIgnoreCase(customParams.get(GuestDef.BootType.UEFI.toString()))) { + guest.setBootMode(GuestDef.BootMode.SECURE); + } + } + guest.setUuid(uuid); + guest.setBootOrder(GuestDef.BootOrder.CDROM); + guest.setBootOrder(GuestDef.BootOrder.HARDISK); + return guest; + } - // Add extra configuration to User VM Domain XML before starting - if (vmTO.getType().equals(VirtualMachine.Type.User) && MapUtils.isNotEmpty(extraConfig)) { - s_logger.info("Appending extra configuration data to guest VM domain XML"); - addExtraConfigComponent(extraConfig, vm); + protected void configureGuestAndVMHypervisorType(VirtualMachineTO vmTO, LibvirtVMDef vm, GuestDef guest) { + if (HypervisorType.LXC == _hypervisorType && VirtualMachine.Type.User.equals(vmTO.getType())) { + configureGuestAndUserVMToUseLXC(vm, guest); + } else { + configureGuestAndSystemVMToUseKVM(vm, guest); } + } - return vm; + /** + * KVM domain is only valid for system VMs. Use LXC for user VMs. + */ + private void configureGuestAndSystemVMToUseKVM(LibvirtVMDef vm, GuestDef guest) { + guest.setGuestType(GuestDef.GuestType.KVM); + vm.setHvsType(HypervisorType.KVM.toString().toLowerCase()); + vm.setLibvirtVersion(_hypervisorLibvirtVersion); + vm.setQemuVersion(_hypervisorQemuVersion); + } + + /** + * LXC domain is only valid for user VMs. Use KVM for system VMs. + */ + private void configureGuestAndUserVMToUseLXC(LibvirtVMDef vm, GuestDef guest) { + guest.setGuestType(GuestDef.GuestType.LXC); + vm.setHvsType(HypervisorType.LXC.toString().toLowerCase()); } /** From 2d3005e728a9076055004364d38539d0bcec80f2 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Mon, 21 Jun 2021 18:12:35 -0300 Subject: [PATCH 14/22] Add unit tests --- .../LibvirtComputingResourceTest.java | 552 +++++++++++++++--- 1 file changed, 471 insertions(+), 81 deletions(-) diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 84d08531c2bf..1bed1e85c02e 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -79,6 +79,7 @@ import org.mockito.BDDMockito; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.Spy; import org.mockito.invocation.InvocationOnMock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; @@ -160,11 +161,27 @@ import com.cloud.agent.api.to.VolumeTO; import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import com.cloud.exception.InternalErrorException; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.kvm.resource.KVMHABase.NfsStoragePool; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ChannelDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ClockDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.ConsoleDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.CpuTuneDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DevicesDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.FeaturesDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GraphicDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestDef.GuestType; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestResourceDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InputDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SCSIDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VideoDef; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef; import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtRequestWrapper; import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper; import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; @@ -201,6 +218,8 @@ public class LibvirtComputingResourceTest { VirtualMachineTO vmTO; @Mock LibvirtVMDef vmDef; + @Spy + private LibvirtComputingResource libvirtComputingResourceSpy = Mockito.spy(LibvirtComputingResource.class); String hyperVisorType = "kvm"; Random random = new Random(); @@ -214,6 +233,7 @@ public class LibvirtComputingResourceTest { @Before public void setup() throws Exception { + libvirtComputingResourceSpy._qemuSocketsPath = new File("/var/run/qemu"); Scanner scanner = new Scanner(memInfo); PowerMockito.whenNew(Scanner.class).withAnyArguments().thenReturn(scanner); } @@ -240,15 +260,13 @@ public void testCreateVMFromSpecLegacy() { final String vncAddr = ""; final String vncPassword = "mySuperSecretPassword"; - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); - final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, speed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); to.setArch("x86_64"); to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + to.setVcpuMaxLimit(cpus + 1); - final LibvirtVMDef vm = lcr.createVMFromSpec(to); + final LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); verifyVm(to, vm); @@ -273,15 +291,13 @@ public void testCreateVMFromSpecWithTopology6() { final String vncAddr = ""; final String vncPassword = "mySuperSecretPassword"; - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); - final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); to.setArch("x86_64"); to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + to.setVcpuMaxLimit(cpus + 1); - final LibvirtVMDef vm = lcr.createVMFromSpec(to); + final LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); verifyVm(to, vm); @@ -292,28 +308,8 @@ public void testCreateVMFromSpecWithTopology6() { */ @Test public void testCreateVMFromSpecWithTopology4() { - final int id = random.nextInt(65534); - final String name = "test-instance-1"; - - final int cpus = 8; - final int minSpeed = 1024; - final int maxSpeed = 2048; - final int minRam = 256 * 1024; - final int maxRam = 512 * 1024; - - final String os = "Ubuntu"; - - final String vncAddr = ""; - final String vncPassword = "mySuperSecretPassword"; - - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); - - final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); - to.setVncAddr(vncAddr); - to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); - - final LibvirtVMDef vm = lcr.createVMFromSpec(to); + VirtualMachineTO to = createDefaultVM(false); + LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); verifyVm(to, vm); @@ -328,59 +324,388 @@ public void testCreateVMFromSpecWithTopology4() { */ @Test public void testCreateVMFromSpec() { - final int id = random.nextInt(65534); - final String name = "test-instance-1"; + VirtualMachineTO to = createDefaultVM(false); + final LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); + vm.setHvsType(hyperVisorType); - final int cpus = random.nextInt(2) + 1; - final int minSpeed = 1024; - final int maxSpeed = 2048; - final int minRam = 256 * 1024; - final int maxRam = 512 * 1024; + verifyVm(to, vm); + } - final String os = "Ubuntu"; + @Test + public void testCreateGuestFromSpecWithoutCustomParam() { + VirtualMachineTO to = createDefaultVM(false); + LibvirtVMDef vm = new LibvirtVMDef(); + GuestDef guestDef = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), null); + verifySysInfo(guestDef, "smbios", to.getUuid(), "pc"); + Assert.assertEquals(GuestDef.BootType.BIOS, guestDef.getBootType()); + Assert.assertNull(guestDef.getBootMode()); + } - final String vncAddr = ""; - final String vncPassword = "mySuperSecretPassword"; + @Test + public void testCreateGuestFromSpecWithCustomParamAndUefi() { + VirtualMachineTO to = createDefaultVM(false); - final LibvirtComputingResource lcr = new LibvirtComputingResource(); - lcr._qemuSocketsPath = new File("/var/run/qemu"); + Map extraConfig = new HashMap<>(); + extraConfig.put(GuestDef.BootType.UEFI.toString(), "legacy"); - final VirtualMachineTO to = - new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); - to.setVncAddr(vncAddr); + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestDef = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), extraConfig); + verifySysInfo(guestDef, "smbios", to.getUuid(), "q35"); + Assert.assertEquals(GuestDef.BootType.UEFI, guestDef.getBootType()); + Assert.assertEquals(GuestDef.BootMode.LEGACY, guestDef.getBootMode()); + } + + @Test + public void testCreateGuestFromSpecWithCustomParamUefiAndSecure() { + VirtualMachineTO to = createDefaultVM(false); + + Map extraConfig = new HashMap<>(); + extraConfig.put(GuestDef.BootType.UEFI.toString(), "secure"); + + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestDef = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), extraConfig); + verifySysInfo(guestDef, "smbios", to.getUuid(), "q35"); + Assert.assertEquals(GuestDef.BootType.UEFI, guestDef.getBootType()); + Assert.assertEquals(GuestDef.BootMode.SECURE, guestDef.getBootMode()); + } + + @Test + public void testCreateGuestResourceDef() { + VirtualMachineTO to = createDefaultVM(false); + + GuestResourceDef guestResourceDef = libvirtComputingResourceSpy.createGuestResourceDef(to); + verifyGuestResourceDef(guestResourceDef, to); + } + + @Test + public void testCreateDevicesDef() { + VirtualMachineTO to = createDefaultVM(false); + + GuestDef guest = new GuestDef(); + guest.setGuestType(GuestType.KVM); + + DevicesDef devicesDef = libvirtComputingResourceSpy.createDevicesDef(to, guest, to.getCpus() + 1, false); + verifyDevices(devicesDef, to); + } + + @Test + public void testCreateDevicesWithSCSIDisk() { + VirtualMachineTO to = createDefaultVM(false); + to.setDetails(new HashMap<>()); + libvirtComputingResourceSpy._guestCpuArch = "aarch64"; + + GuestDef guest = new GuestDef(); + guest.setGuestType(GuestType.KVM); + + DevicesDef devicesDef = libvirtComputingResourceSpy.createDevicesDef(to, guest, to.getCpus() + 1, false); + verifyDevices(devicesDef, to); + + Document domainDoc = parse(devicesDef.toString()); + assertNodeExists(domainDoc, "/devices/controller[@type='scsi']"); + assertNodeExists(domainDoc, "/devices/controller[@model='virtio-scsi']"); + assertNodeExists(domainDoc, "/devices/controller/address[@type='pci']"); + assertNodeExists(domainDoc, "/devices/controller/driver[@queues='" + (to.getCpus() + 1) + "']"); + } + + @Test + public void testConfigureGuestAndSystemVMToUseKVM() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._hypervisorLibvirtVersion = 100; + libvirtComputingResourceSpy._hypervisorQemuVersion = 10; + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestFromSpec = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), null); + Assert.assertEquals(GuestDef.GuestType.KVM, guestFromSpec.getGuestType()); + Assert.assertEquals(HypervisorType.KVM.toString().toLowerCase(), vm.getHvsType()); + } + + @Test + public void testConfigureGuestAndUserVMToUseLXC() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._hypervisorType = HypervisorType.LXC; + LibvirtVMDef vm = new LibvirtVMDef(); + + GuestDef guestFromSpec = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), null); + Assert.assertEquals(GuestDef.GuestType.LXC, guestFromSpec.getGuestType()); + Assert.assertEquals(HypervisorType.LXC.toString().toLowerCase(), vm.getHvsType()); + } + + @Test + public void testCreateCpuTuneDefWithoutQuotaAndPeriod() { + VirtualMachineTO to = createDefaultVM(false); + + CpuTuneDef cpuTuneDef = libvirtComputingResourceSpy.createCpuTuneDef(to); + Document domainDoc = parse(cpuTuneDef.toString()); + assertXpath(domainDoc, "/cputune/shares/text()", String.valueOf(cpuTuneDef.getShares())); + } + + @Test + public void testCreateCpuTuneDefWithQuotaAndPeriod() { + VirtualMachineTO to = createDefaultVM(true); + to.setCpuQuotaPercentage(10.0); + + CpuTuneDef cpuTuneDef = libvirtComputingResourceSpy.createCpuTuneDef(to); + Document domainDoc = parse(cpuTuneDef.toString()); + assertXpath(domainDoc, "/cputune/shares/text()", String.valueOf(cpuTuneDef.getShares())); + assertXpath(domainDoc, "/cputune/quota/text()", String.valueOf(cpuTuneDef.getQuota())); + assertXpath(domainDoc, "/cputune/period/text()", String.valueOf(cpuTuneDef.getPeriod())); + } + + @Test + public void testCreateCpuTuneDefWithMinQuota() { + VirtualMachineTO to = createDefaultVM(true); + to.setCpuQuotaPercentage(0.01); + + CpuTuneDef cpuTuneDef = libvirtComputingResourceSpy.createCpuTuneDef(to); + Document domainDoc = parse(cpuTuneDef.toString()); + assertXpath(domainDoc, "/cputune/shares/text()", String.valueOf(cpuTuneDef.getShares())); + assertXpath(domainDoc, "/cputune/quota/text()", "1000"); + assertXpath(domainDoc, "/cputune/period/text()", String.valueOf(cpuTuneDef.getPeriod())); + } + + @Test + public void testCreateDefaultClockDef() { + VirtualMachineTO to = createDefaultVM(false); + + ClockDef clockDef = libvirtComputingResourceSpy.createClockDef(to); + Document domainDoc = parse(clockDef.toString()); + + assertXpath(domainDoc, "/clock/@offset", "utc"); + } + + @Test + public void testCreateClockDefWindows() { + VirtualMachineTO to = createDefaultVM(false); + to.setOs("Windows"); + + ClockDef clockDef = libvirtComputingResourceSpy.createClockDef(to); + Document domainDoc = parse(clockDef.toString()); + + assertXpath(domainDoc, "/clock/@offset", "localtime"); + assertXpath(domainDoc, "/clock/timer/@name", "hypervclock"); + assertXpath(domainDoc, "/clock/timer/@present", "yes"); + } + + @Test + public void testCreateClockDefKvmclock() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._hypervisorLibvirtVersion = 9020; + + ClockDef clockDef = libvirtComputingResourceSpy.createClockDef(to); + Document domainDoc = parse(clockDef.toString()); + + assertXpath(domainDoc, "/clock/@offset", "utc"); + assertXpath(domainDoc, "/clock/timer/@name", "kvmclock"); + } + + @Test + public void testCreateTermPolicy() { + TermPolicy termPolicy = libvirtComputingResourceSpy.createTermPolicy(); + + String xml = "\n" + termPolicy.toString() + ""; + Document domainDoc = parse(xml); + + assertXpath(domainDoc, "/terms/on_reboot/text()", "restart"); + assertXpath(domainDoc, "/terms/on_poweroff/text()", "destroy"); + assertXpath(domainDoc, "/terms/on_crash/text()", "destroy"); + } + + @Test + public void testCreateFeaturesDef() { + VirtualMachineTO to = createDefaultVM(false); + FeaturesDef featuresDef = libvirtComputingResourceSpy.createFeaturesDef(null, false, false); + + String xml = "" + featuresDef.toString() + ""; + Document domainDoc = parse(xml); + + verifyFeatures(domainDoc); + } + + @Test + public void testCreateFeaturesDefWithUefi() { + VirtualMachineTO to = createDefaultVM(false); + HashMap extraConfig = new HashMap<>(); + extraConfig.put(GuestDef.BootType.UEFI.toString(), ""); + + FeaturesDef featuresDef = libvirtComputingResourceSpy.createFeaturesDef(extraConfig, true, true); + + String xml = "" + featuresDef.toString() + ""; + Document domainDoc = parse(xml); + + verifyFeatures(domainDoc); + } + + @Test + public void testCreateWatchDog() { + WatchDogDef watchDogDef = libvirtComputingResourceSpy.createWatchDogDef(); + verifyWatchDogDevices(parse(watchDogDef.toString()), ""); + } + + @Test + public void testCreateArm64UsbDef() { + DevicesDef devicesDef = new DevicesDef(); + + libvirtComputingResourceSpy.createArm64UsbDef(devicesDef); + Document domainDoc = parse(devicesDef.toString()); + + assertXpath(domainDoc, "/devices/controller/@type", "usb"); + assertXpath(domainDoc, "/devices/controller/@model", "qemu-xhci"); + assertXpath(domainDoc, "/devices/controller/address/@type", "pci"); + assertNodeExists(domainDoc, "/devices/input[@type='keyboard']"); + assertNodeExists(domainDoc, "/devices/input[@bus='usb']"); + assertNodeExists(domainDoc, "/devices/input[@type='mouse']"); + assertNodeExists(domainDoc, "/devices/input[@bus='usb']"); + } + + @Test + public void testCreateInputDef() { + InputDef inputDef = libvirtComputingResourceSpy.createTabletInputDef(); + verifyTabletInputDevice(parse(inputDef.toString()), ""); + } + + @Test + public void testCreateGraphicDef() { + VirtualMachineTO to = createDefaultVM(false); + GraphicDef graphicDef = libvirtComputingResourceSpy.createGraphicDef(to); + verifyGraphicsDevices(to, parse(graphicDef.toString()), ""); + } + + @Test + public void testCreateChannelDef() { + VirtualMachineTO to = createDefaultVM(false); + ChannelDef channelDef = libvirtComputingResourceSpy.createChannelDef(to); + verifyChannelDevices(to, parse(channelDef.toString()), ""); + } + + @Test + public void testCreateSCSIDef() { + VirtualMachineTO to = createDefaultVM(false); + + SCSIDef scsiDef = libvirtComputingResourceSpy.createSCSIDef(to.getCpus()); + Document domainDoc = parse(scsiDef.toString()); + verifyScsi(to, domainDoc, ""); + } + + @Test + public void testCreateConsoleDef() { + VirtualMachineTO to = createDefaultVM(false); + ConsoleDef consoleDef = libvirtComputingResourceSpy.createConsoleDef(); + verifyConsoleDevices(parse(consoleDef.toString()), ""); + } + + @Test + public void testCreateVideoDef() { + VirtualMachineTO to = createDefaultVM(false); + libvirtComputingResourceSpy._videoRam = 200; + libvirtComputingResourceSpy._videoHw = "vGPU"; + + VideoDef videoDef = libvirtComputingResourceSpy.createVideoDef(); + Document domainDoc = parse(videoDef.toString()); + assertXpath(domainDoc, "/video/model/@type", "vGPU"); + assertXpath(domainDoc, "/video/model/@vram", "200"); + } + + @Test + public void testCreateRngDef() { + VirtualMachineTO to = createDefaultVM(false); + RngDef rngDef = libvirtComputingResourceSpy.createRngDef(); + Document domainDoc = parse(rngDef.toString()); + + assertXpath(domainDoc, "/rng/@model", "virtio"); + assertXpath(domainDoc, "/rng/rate/@period", "1000"); + assertXpath(domainDoc, "/rng/rate/@bytes", "2048"); + assertXpath(domainDoc, "/rng/backend/@model", "random"); + assertXpath(domainDoc, "/rng/backend/text()", "/dev/random"); + } + + @Test + public void testCreateSerialDef() { + VirtualMachineTO to = createDefaultVM(false); + SerialDef serialDef = libvirtComputingResourceSpy.createSerialDef(); + verifySerialDevices(parse(serialDef.toString()), ""); + } + + private VirtualMachineTO createDefaultVM(boolean limitCpuUse) { + int id = random.nextInt(65534); + String name = "test-instance-1"; + + int cpus = random.nextInt(2) + 1; + int minSpeed = 1024; + int maxSpeed = 2048; + int minRam = 256 * 1024; + int maxRam = 512 * 1024; + + String os = "Ubuntu"; + String vncAddr = ""; + String vncPassword = "mySuperSecretPassword"; + + final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, limitCpuUse, + vncPassword); to.setArch("x86_64"); + to.setVncAddr(vncAddr); to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + to.setVcpuMaxLimit(cpus + 1); - final LibvirtVMDef vm = lcr.createVMFromSpec(to); - vm.setHvsType(hyperVisorType); + return to; + } - verifyVm(to, vm); + private void verifyGuestResourceDef(GuestResourceDef guestResourceDef, VirtualMachineTO to) { + String xml = "" + guestResourceDef.toString() + ""; + Document domainDoc = parse(xml); + + String minRam = String.valueOf(to.getMinRam() / 1024); + verifyMemory(to, domainDoc, minRam); + assertNodeExists(domainDoc, "/domain/vcpu"); + verifyMemballoonDevices(domainDoc); + verifyVcpu(to, domainDoc); } - private void verifyVm(final VirtualMachineTO to, final LibvirtVMDef vm) { - final Document domainDoc = parse(vm.toString()); - assertXpath(domainDoc, "/domain/@type", vm.getHvsType()); - assertXpath(domainDoc, "/domain/name/text()", to.getName()); - assertXpath(domainDoc, "/domain/uuid/text()", to.getUuid()); - assertXpath(domainDoc, "/domain/description/text()", to.getOs()); - assertXpath(domainDoc, "/domain/clock/@offset", "utc"); - assertNodeExists(domainDoc, "/domain/features/pae"); - assertNodeExists(domainDoc, "/domain/features/apic"); - assertNodeExists(domainDoc, "/domain/features/acpi"); - assertXpath(domainDoc, "/domain/devices/serial/@type", "pty"); - assertXpath(domainDoc, "/domain/devices/serial/target/@port", "0"); - assertXpath(domainDoc, "/domain/devices/graphics/@type", "vnc"); - assertXpath(domainDoc, "/domain/devices/graphics/@listen", to.getVncAddr()); - assertXpath(domainDoc, "/domain/devices/graphics/@autoport", "yes"); - assertXpath(domainDoc, "/domain/devices/graphics/@passwd", to.getVncPassword()); + private void verifyVm(VirtualMachineTO to, LibvirtVMDef vm) { + Document domainDoc = parse(vm.toString()); + verifyHeader(domainDoc, vm.getHvsType(), to.getName(), to.getUuid(), to.getOs()); + verifyFeatures(domainDoc); + verifyClock(domainDoc); + verifySerialDevices(domainDoc, "/domain/devices"); + verifyGraphicsDevices(to, domainDoc, "/domain/devices"); + verifyConsoleDevices(domainDoc, "/domain/devices"); + verifyTabletInputDevice(domainDoc, "/domain/devices"); + verifyChannelDevices(to, domainDoc, "/domain/devices"); + + String minRam = String.valueOf(to.getMinRam() / 1024); + verifyMemory(to, domainDoc, minRam); + assertNodeExists(domainDoc, "/domain/cpu"); + + verifyMemballoonDevices(domainDoc); + verifyVcpu(to, domainDoc); + verifyOsType(domainDoc); + verifyOsBoot(domainDoc); + verifyPoliticOn_(domainDoc); + verifyWatchDogDevices(domainDoc, "/domain/devices"); + } + + private void verifyMemballoonDevices(Document domainDoc) { + assertXpath(domainDoc, "/domain/devices/memballoon/@model", "virtio"); + } - assertXpath(domainDoc, "/domain/devices/console/@type", "pty"); - assertXpath(domainDoc, "/domain/devices/console/target/@port", "0"); - assertXpath(domainDoc, "/domain/devices/input/@type", "tablet"); - assertXpath(domainDoc, "/domain/devices/input/@bus", "usb"); + private void verifyVcpu(VirtualMachineTO to, Document domainDoc) { + assertXpath(domainDoc, "/domain/vcpu/text()", String.valueOf(to.getCpus())); + } - assertNodeExists(domainDoc, "/domain/devices/channel"); - assertXpath(domainDoc, "/domain/devices/channel/@type", ChannelDef.ChannelType.UNIX.toString()); + private void verifyMemory(VirtualMachineTO to, Document domainDoc, String minRam) { + assertXpath(domainDoc, "/domain/memory/text()", String.valueOf(to.getMaxRam() / 1024)); + assertXpath(domainDoc, "/domain/currentMemory/text()", minRam); + } + + private void verifyWatchDogDevices(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/watchdog/@model", "i6300esb"); + assertXpath(domainDoc, prefix + "/watchdog/@action", "none"); + } + + private void verifyChannelDevices(VirtualMachineTO to, Document domainDoc, String prefix) { + assertNodeExists(domainDoc, prefix + "/channel"); + assertXpath(domainDoc, prefix + "/channel/@type", ChannelDef.ChannelType.UNIX.toString()); /* The configure() method of LibvirtComputingResource has not been called, so the default path for the sockets @@ -389,28 +714,93 @@ The configure() method of LibvirtComputingResource has not been called, so the d Calling configure is also not possible since that looks for certain files on the system which are not present during testing */ - assertXpath(domainDoc, "/domain/devices/channel/source/@path", "/var/run/qemu/" + to.getName() + ".org.qemu.guest_agent.0"); - assertXpath(domainDoc, "/domain/devices/channel/target/@name", "org.qemu.guest_agent.0"); + assertXpath(domainDoc, prefix + "/channel/source/@path", "/var/run/qemu/" + to.getName() + ".org.qemu.guest_agent.0"); + assertXpath(domainDoc, prefix + "/channel/target/@name", "org.qemu.guest_agent.0"); + } - assertXpath(domainDoc, "/domain/memory/text()", String.valueOf( to.getMaxRam() / 1024 )); - assertXpath(domainDoc, "/domain/currentMemory/text()", String.valueOf( to.getMinRam() / 1024 )); + private void verifyTabletInputDevice(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/input/@type", "tablet"); + assertXpath(domainDoc, prefix + "/input/@bus", "usb"); + } - assertXpath(domainDoc, "/domain/devices/memballoon/@model", "virtio"); - assertXpath(domainDoc, "/domain/vcpu/text()", String.valueOf(to.getCpus())); + private void verifyConsoleDevices(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/console/@type", "pty"); + assertXpath(domainDoc, prefix + "/console/target/@port", "0"); + } - assertXpath(domainDoc, "/domain/os/type/@machine", "pc"); - assertXpath(domainDoc, "/domain/os/type/text()", "hvm"); + private void verifyScsi(VirtualMachineTO to, Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/controller/@type", "scsi"); + assertXpath(domainDoc, prefix + "/controller/@model", "virtio-scsi"); + assertXpath(domainDoc, prefix + "/controller/address/@type", "pci"); + assertXpath(domainDoc, prefix + "/controller/driver/@queues", String.valueOf(to.getCpus())); + } - assertNodeExists(domainDoc, "/domain/cpu"); + private void verifyClock(Document domainDoc) { + assertXpath(domainDoc, "/domain/clock/@offset", "utc"); + } + + private void verifyGraphicsDevices(VirtualMachineTO to, Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/graphics/@type", "vnc"); + assertXpath(domainDoc, prefix + "/graphics/@listen", to.getVncAddr()); + assertXpath(domainDoc, prefix + "/graphics/@autoport", "yes"); + assertXpath(domainDoc, prefix + "/graphics/@passwd", to.getVncPassword()); + } + + private void verifySerialDevices(Document domainDoc, String prefix) { + assertXpath(domainDoc, prefix + "/serial/@type", "pty"); + assertXpath(domainDoc, prefix + "/serial/target/@port", "0"); + } + + private void verifyOsBoot(Document domainDoc) { assertNodeExists(domainDoc, "/domain/os/boot[@dev='cdrom']"); assertNodeExists(domainDoc, "/domain/os/boot[@dev='hd']"); + } + + private void verifyOsType(Document domainDoc) { + assertXpath(domainDoc, "/domain/os/type/@machine", "pc"); + assertXpath(domainDoc, "/domain/os/type/text()", "hvm"); + } + private void verifyPoliticOn_(Document domainDoc) { assertXpath(domainDoc, "/domain/on_reboot/text()", "restart"); assertXpath(domainDoc, "/domain/on_poweroff/text()", "destroy"); assertXpath(domainDoc, "/domain/on_crash/text()", "destroy"); + } + + private void verifyFeatures(Document domainDoc) { + assertNodeExists(domainDoc, "/domain/features/pae"); + assertNodeExists(domainDoc, "/domain/features/apic"); + assertNodeExists(domainDoc, "/domain/features/acpi"); + } + + private void verifyHeader(Document domainDoc, String hvsType, String name, String uuid, String os) { + assertXpath(domainDoc, "/domain/@type", hvsType); + assertXpath(domainDoc, "/domain/name/text()", name); + assertXpath(domainDoc, "/domain/uuid/text()", uuid); + assertXpath(domainDoc, "/domain/description/text()", os); + } + + private void verifyDevices(DevicesDef devicesDef, VirtualMachineTO to) { + Document domainDoc = parse(devicesDef.toString()); + + verifyWatchDogDevices(domainDoc, "/devices"); + verifyConsoleDevices(domainDoc, "/devices"); + verifySerialDevices(domainDoc, "/devices"); + verifyGraphicsDevices(to, domainDoc, "/devices"); + verifyChannelDevices(to, domainDoc, "/devices"); + verifyTabletInputDevice(domainDoc, "/devices"); + } + + private void verifySysInfo(GuestDef guestDef, String type, String uuid, String machine) { + // Need put because the string of guestdef generate two root element in XML, raising a error in parse. + String xml = "\n" + guestDef.toString() + ""; - assertXpath(domainDoc, "/domain/devices/watchdog/@model", "i6300esb"); - assertXpath(domainDoc, "/domain/devices/watchdog/@action", "none"); + Document domainDoc = parse(xml); + assertXpath(domainDoc, "/guestdef/sysinfo/@type", type); + assertNodeExists(domainDoc, "/guestdef/sysinfo/system/entry[@name='manufacturer']"); + assertNodeExists(domainDoc, "/guestdef/sysinfo/system/entry[@name='product']"); + assertXpath(domainDoc, "/guestdef/sysinfo/system/entry[@name='uuid']/text()", uuid); + assertXpath(domainDoc, "/guestdef/os/type/@machine", machine); } static Document parse(final String input) { From 2d02ede47ca8fd18447e81f1d8708e7cc7a81d40 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Wed, 23 Jun 2021 12:17:53 -0300 Subject: [PATCH 15/22] Fix test --- .../LibvirtComputingResourceTest.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 1bed1e85c02e..d098f49d91a1 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -308,7 +308,24 @@ public void testCreateVMFromSpecWithTopology6() { */ @Test public void testCreateVMFromSpecWithTopology4() { - VirtualMachineTO to = createDefaultVM(false); + final int id = random.nextInt(65534); + final String name = "test-instance-1"; + + final int cpus = 8; + final int minSpeed = 1024; + final int maxSpeed = 2048; + final int minRam = 256 * 1024; + final int maxRam = 512 * 1024; + + final String os = "Ubuntu"; + + final String vncAddr = ""; + final String vncPassword = "mySuperSecretPassword"; + + final VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); + to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); + LibvirtVMDef vm = libvirtComputingResourceSpy.createVMFromSpec(to); vm.setHvsType(hyperVisorType); From e7a88aee626863a72bfbaf734a1983e86d1c08b6 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 24 Jun 2021 11:54:22 -0300 Subject: [PATCH 16/22] Extract if block to method for add extra configs to VM Domain XML --- .../hypervisor/kvm/resource/LibvirtComputingResource.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 7fe5ac340a49..ac822beec178 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 @@ -2357,7 +2357,13 @@ private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map extraConfig) { if (MapUtils.isNotEmpty(extraConfig) && VirtualMachine.Type.User.equals(vmTO.getType())) { s_logger.debug(String.format("Appending extra configuration data [%s] to guest VM [%s] domain XML.", extraConfig, vmTO.toString())); addExtraConfigComponent(extraConfig, vm); From e35ee3c85dbb9f3f418826c893ca7d9391a9fb7b Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Wed, 30 Jun 2021 17:21:39 -0300 Subject: [PATCH 17/22] Split travis tests trying to isolate which test is causing an error --- .travis.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2174ddb1428e..fef9c8f0578f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,21 +52,25 @@ env: smoke/test_async_job smoke/test_backup_recovery_dummy smoke/test_create_list_domain_account_project - smoke/test_create_network - smoke/test_deploy_vgpu_enabled_vm + smoke/test_create_network" + + - TESTS="smoke/test_deploy_vgpu_enabled_vm smoke/test_deploy_vm_extra_config_data smoke/test_deploy_vm_iso smoke/test_deploy_vm_root_resize smoke/test_deploy_vm_with_userdata - smoke/test_deploy_vms_with_varied_deploymentplanners - smoke/test_diagnostics + smoke/test_deploy_vms_with_varied_deploymentplanners" + + - TESTS="smoke/test_diagnostics smoke/test_disk_offerings smoke/test_dynamicroles smoke/test_global_settings - smoke/test_guest_vlan_range - smoke/test_host_annotations + smoke/test_guest_vlan_range" + + - TESTS="smoke/test_host_annotations smoke/test_host_maintenance smoke/test_hostha_simulator" + - TESTS="smoke/test_internal_lb smoke/test_iso From 9377161e83ae87eb4b97f4865feee2b2642d759e Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 1 Jul 2021 11:49:06 -0300 Subject: [PATCH 18/22] Override toString() method --- .../main/java/com/cloud/agent/api/to/VirtualMachineTO.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java index c4729383dd4f..dabe6977d243 100644 --- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java @@ -413,4 +413,9 @@ public DeployAsIsInfoTO getDeployAsIsInfo() { public void setDeployAsIsInfo(DeployAsIsInfoTO deployAsIsInfo) { this.deployAsIsInfo = deployAsIsInfo; } + + @Override + public String toString() { + return String.format("VM {\"id\": %s, \"name\": \"%s\", \"uuid\": \"%s\", \"type\": \"%s\"}", id, name, uuid, type); + } } From 1bf0d0f24802edcb94f61e19f5c6bffe877fddf3 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 1 Jul 2021 11:50:56 -0300 Subject: [PATCH 19/22] Update documentation --- .../resource/LibvirtComputingResource.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) 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 ac822beec178..7d202ffc7adb 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 @@ -261,12 +261,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv */ private static final String PAE = "pae"; /** - * Libvirt only suport guest cpu mode in versions from 0.9.10. + * Libvirt supports guest CPU mode since 0.9.10. */ private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_MODE = 9010; + /** + * The CPU tune element provides details of the CPU tunable parameters for the domain.
+ * It is supported since Libvirt 0.9.0 + */ private static final int MIN_LIBVIRT_VERSION_FOR_GUEST_CPU_TUNE = 9000; /** - * Verify if guest is ARM64 + * Constant that defines ARM64 (aarch64) guest architectures. */ private static final String AARCH64 = "aarch64"; @@ -2326,7 +2330,7 @@ public LibvirtVMDef createVMFromSpec(final VirtualMachineTO vmTO) { } /** - * Configure created VM from specification, adding the necessary components to VM. + * Configures created VM from specification, adding the necessary components to VM. */ private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map customParams, boolean isUefiEnabled, boolean isSecureBoot, String bootMode, Map extraConfig, String uuid) { @@ -2361,7 +2365,7 @@ private void configureVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map extraConfig) { if (MapUtils.isNotEmpty(extraConfig) && VirtualMachine.Type.User.equals(vmTO.getType())) { @@ -2371,7 +2375,7 @@ private void addExtraConfigsToVM(VirtualMachineTO vmTO, LibvirtVMDef vm, Map + * The respective Virtio SCSI XML definition is generated only if the VM's Disk Bus is of ISCSI. */ protected SCSIDef createSCSIDef(int vcpus) { return new SCSIDef((short)0, 0, 0, 9, 0, vcpus); @@ -2561,7 +2566,7 @@ private boolean isGuestAarch64() { } /** - * Create a guest definition from a VM specification. + * Creates a guest definition from a VM specification. */ protected GuestDef createGuestFromSpec(VirtualMachineTO vmTO, LibvirtVMDef vm, String uuid, Map customParams) { GuestDef guest = new GuestDef(); @@ -2611,7 +2616,7 @@ private void configureGuestAndUserVMToUseLXC(LibvirtVMDef vm, GuestDef guest) { } /** - * Add extra configurations (if any) as a String component to the domain XML + * Adds extra configurations (if any) as a String component to the domain XML */ protected void addExtraConfigComponent(Map extraConfig, LibvirtVMDef vm) { if (MapUtils.isNotEmpty(extraConfig)) { From e2a52e57150abbfa836ac1fbf2f1e42736792774 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Thu, 1 Jul 2021 12:00:07 -0300 Subject: [PATCH 20/22] Fix checkstyle error (line with trailing spaces) --- .travis.yml | 16 ++++++---------- .../com/cloud/agent/api/to/VirtualMachineTO.java | 4 ++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index fef9c8f0578f..2174ddb1428e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,25 +52,21 @@ env: smoke/test_async_job smoke/test_backup_recovery_dummy smoke/test_create_list_domain_account_project - smoke/test_create_network" - - - TESTS="smoke/test_deploy_vgpu_enabled_vm + smoke/test_create_network + smoke/test_deploy_vgpu_enabled_vm smoke/test_deploy_vm_extra_config_data smoke/test_deploy_vm_iso smoke/test_deploy_vm_root_resize smoke/test_deploy_vm_with_userdata - smoke/test_deploy_vms_with_varied_deploymentplanners" - - - TESTS="smoke/test_diagnostics + smoke/test_deploy_vms_with_varied_deploymentplanners + smoke/test_diagnostics smoke/test_disk_offerings smoke/test_dynamicroles smoke/test_global_settings - smoke/test_guest_vlan_range" - - - TESTS="smoke/test_host_annotations + smoke/test_guest_vlan_range + smoke/test_host_annotations smoke/test_host_maintenance smoke/test_hostha_simulator" - - TESTS="smoke/test_internal_lb smoke/test_iso diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java index dabe6977d243..8a30b5ef9fee 100644 --- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java @@ -413,9 +413,9 @@ public DeployAsIsInfoTO getDeployAsIsInfo() { public void setDeployAsIsInfo(DeployAsIsInfoTO deployAsIsInfo) { this.deployAsIsInfo = deployAsIsInfo; } - + @Override public String toString() { - return String.format("VM {\"id\": %s, \"name\": \"%s\", \"uuid\": \"%s\", \"type\": \"%s\"}", id, name, uuid, type); + return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type); } } From 58a4d733325cb9413a29b033b14663ba51bad363 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Mon, 19 Jul 2021 11:39:20 -0300 Subject: [PATCH 21/22] Remove unnecessary comment --- .../hypervisor/kvm/resource/LibvirtComputingResource.java | 3 --- 1 file changed, 3 deletions(-) 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 7d202ffc7adb..58a7c7c8de34 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 @@ -2413,9 +2413,6 @@ protected WatchDogDef createWatchDogDef() { return new WatchDogDef(_watchDogAction, _watchDogModel); } - /* - * Adds an explicit USB devices for ARM64 - */ protected void createArm64UsbDef(DevicesDef devices) { devices.addDevice(new InputDef(KEYBOARD, USB)); devices.addDevice(new InputDef(MOUSE, USB)); From 1c54f8a4854da3ba6860179a5beb1f2197ad4310 Mon Sep 17 00:00:00 2001 From: SadiJr <17a0db2854@firemailbox.club> Date: Mon, 19 Jul 2021 14:42:56 -0300 Subject: [PATCH 22/22] Revert travis tests --- .travis.yml | 16 +- .../smoke/test_deploy_vm_root_resize.py | 265 +++++++++--------- 2 files changed, 135 insertions(+), 146 deletions(-) diff --git a/.travis.yml b/.travis.yml index fef9c8f0578f..2174ddb1428e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,25 +52,21 @@ env: smoke/test_async_job smoke/test_backup_recovery_dummy smoke/test_create_list_domain_account_project - smoke/test_create_network" - - - TESTS="smoke/test_deploy_vgpu_enabled_vm + smoke/test_create_network + smoke/test_deploy_vgpu_enabled_vm smoke/test_deploy_vm_extra_config_data smoke/test_deploy_vm_iso smoke/test_deploy_vm_root_resize smoke/test_deploy_vm_with_userdata - smoke/test_deploy_vms_with_varied_deploymentplanners" - - - TESTS="smoke/test_diagnostics + smoke/test_deploy_vms_with_varied_deploymentplanners + smoke/test_diagnostics smoke/test_disk_offerings smoke/test_dynamicroles smoke/test_global_settings - smoke/test_guest_vlan_range" - - - TESTS="smoke/test_host_annotations + smoke/test_guest_vlan_range + smoke/test_host_annotations smoke/test_host_maintenance smoke/test_hostha_simulator" - - TESTS="smoke/test_internal_lb smoke/test_iso diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py index ac54726bfbd0..f3b42a389b95 100644 --- a/test/integration/smoke/test_deploy_vm_root_resize.py +++ b/test/integration/smoke/test_deploy_vm_root_resize.py @@ -206,116 +206,113 @@ def test_00_deploy_vm_root_resize(self): # 2. root disk has new size per listVolumes # 3. Rejects non-supported hypervisor types """ - try: - print(f'Self template is {self.template}') - newrootsize = (self.template.size >> 30) + 2 - if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' - or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): - - accounts = Account.list(self.apiclient, id=self.account.id) - self.assertEqual(validateList(accounts)[0], PASS, - "accounts list validation failed") - initialResourceCount = int(accounts[0].primarystoragetotal) - - if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - else: - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - - list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) - self.debug( - "Verify listVirtualMachines response for virtual machine: %s" \ - % self.virtual_machine.id - ) - res=validateList(list_vms) - self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " - "response") - self.cleanup.append(self.virtual_machine) + newrootsize = (self.template.size >> 30) + 2 + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): - vm = list_vms[0] - self.assertEqual( - vm.id, - self.virtual_machine.id, - "Virtual Machine ids do not match" + accounts = Account.list(self.apiclient, id=self.account.id) + self.assertEqual(validateList(accounts)[0], PASS, + "accounts list validation failed") + initialResourceCount = int(accounts[0].primarystoragetotal) + + if self.hypervisor=="vmware": + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.template.id, + rootdisksize=newrootsize ) - self.assertEqual( - vm.name, - self.virtual_machine.name, - "Virtual Machine names do not match" - ) - self.assertEqual( - vm.state, - "Running", - msg="VM is not in Running state" + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize ) - # get root vol from created vm, verify it is correct size - list_volume_response = list_volumes( + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + res=validateList(list_vms) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") + self.cleanup.append(self.virtual_machine) + + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + + # get root vol from created vm, verify it is correct size + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + res=validateList(list_volume_response) + self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " + "response") + rootvolume = list_volume_response[0] + success = False + if rootvolume is not None and rootvolume.size == (newrootsize << 30): + success = True + + self.assertEqual( + success, + True, + "Check if the root volume resized appropriately" + ) + + response = matchResourceCount( + self.apiclient, (initialResourceCount + newrootsize), + RESOURCE_PRIMARY_STORAGE, + accountid=self.account.id) + self.assertEqual(response[0], PASS, response[1]) + else: + self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) + newrootsize = (self.template.size >> 30) + 2 + success = False + try: + self.virtual_machine = VirtualMachine.create( self.apiclient, - virtualmachineid=self.virtual_machine.id, - type='ROOT', - listall=True + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize ) - res=validateList(list_volume_response) - self.assertNotEqual(res[2], INVALID_INPUT, "Invalid list VM " - "response") - rootvolume = list_volume_response[0] - success = False - if rootvolume is not None and rootvolume.size == (newrootsize << 30): + except Exception as ex: + if re.search("Hypervisor \S+ does not support rootdisksize override", str(ex)): success = True + else: + self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - self.assertEqual( - success, - True, - "Check if the root volume resized appropriately" - ) - - response = matchResourceCount( - self.apiclient, (initialResourceCount + newrootsize), - RESOURCE_PRIMARY_STORAGE, - accountid=self.account.id) - self.assertEqual(response[0], PASS, response[1]) - else: - self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.hypervisor) - newrootsize = (self.template.size >> 30) + 2 - success = False - try: - self.virtual_machine = VirtualMachine.create( - self.apiclient, - self.testdata["virtual_machine"], - accountid=self.account.name, - zoneid=self.zone.id, - domainid=self.account.domainid, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - except Exception as ex: - if re.search("Hypervisor \S+ does not support rootdisksize override", str(ex)): - success = True - else: - self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - - self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) - except Exception as ex: - print(f'Error is {ex}') + self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.hypervisor) @attr(tags = ['advanced', 'basic', 'sg'], required_hardware="false") def test_01_deploy_vm_root_resize(self): @@ -361,46 +358,42 @@ def test_01_deploy_vm_root_resize(self): def test_02_deploy_vm_root_resize(self): """Test proper failure to deploy virtual machine with rootdisksize less than template size """ - try: - print(f'Self template is {self.template}') - newrootsize = (self.template.size >> 30) - 1 - success=False - self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") - - if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' - or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): - try: - if self.hypervisor=="vmware": - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.services_offering_vmware.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - else: - self.virtual_machine = VirtualMachine.create( - self.apiclient, self.services["virtual_machine"], - zoneid=self.zone.id, - accountid=self.account.name, - domainid=self.domain.id, - serviceofferingid=self.service_offering.id, - templateid=self.template.id, - rootdisksize=newrootsize - ) - except Exception as ex: + newrootsize = (self.template.size >> 30) - 1 + success=False + self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") + + if (self.hypervisor.lower() == 'kvm' or self.hypervisor.lower() == 'xenserver' + or self.hypervisor.lower() == 'vmware' or self.hypervisor.lower() == 'simulator'): + try: + if self.hypervisor=="vmware": + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.services_offering_vmware.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + else: + self.virtual_machine = VirtualMachine.create( + self.apiclient, self.services["virtual_machine"], + zoneid=self.zone.id, + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: if "rootdisksize override is smaller than template size" in str(ex): success = True else: self.debug("Virtual machine create did not fail appropriately. Error was actually : " + str(ex)); - self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") - else: - self.debug("test 02 does not support hypervisor type " + self.hypervisor) - except Exception as ex: - print(f'Error is {ex}') + self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") + else: + self.debug("test 02 does not support hypervisor type " + self.hypervisor)