From 5df15a7aa62a2fe0caa95fa2e05710205b26e3b1 Mon Sep 17 00:00:00 2001 From: niyamsw Date: Wed, 29 Jan 2025 22:04:16 +0530 Subject: [PATCH] KVM/s390x Support: Add support for KVM on s390x architecture (#10038) Signed-off-by: Niyam Siwach Signed-off-by: Himanshu Mishra --- agent/conf/agent.properties | 2 +- .../agent/properties/AgentProperties.java | 2 +- .../resource/LibvirtComputingResource.java | 46 ++++++++++++++----- .../hypervisor/kvm/resource/LibvirtVMDef.java | 8 ++-- .../cloudstack/utils/linux/KVMHostInfo.java | 7 +++ .../LibvirtComputingResourceTest.java | 4 +- .../cloud/hypervisor/HypervisorGuruBase.java | 2 + 7 files changed, 52 insertions(+), 19 deletions(-) diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index 515614fff16..eb2fbe3aed9 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -209,7 +209,7 @@ hypervisor.type=kvm # the management server would send. # In case of arm64 (aarch64), this will change the machine type to 'virt' and # adds a SCSI and a USB controller in the domain xml. -# Possible values: x86_64 | aarch64 +# Possible values: x86_64 | aarch64 | s390x # If null (default), defaults to the VM's OS architecture #guest.cpu.arch= diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java index 52679811f7c..f66232b86e5 100644 --- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java +++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java @@ -383,7 +383,7 @@ public class AgentProperties{ /** * This param will set the CPU architecture for the domain to override what the management server would send.
* In case of arm64 (aarch64), this will change the machine type to 'virt' and add a SCSI and a USB controller in the domain XML.
- * Possible values: x86_64 | aarch64
+ * Possible values: x86_64 | aarch64 | s390x
* Data type: String.
* Default value: null (will set use the architecture of the VM's OS). */ 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 47edd2eff18..2f57ad6ffb0 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 @@ -18,6 +18,7 @@ package com.cloud.hypervisor.kvm.resource; import static com.cloud.host.Host.HOST_INSTANCE_CONVERSION; import static com.cloud.host.Host.HOST_VOLUME_ENCRYPTION; +import static org.apache.cloudstack.utils.linux.KVMHostInfo.isHostS390x; import java.io.BufferedReader; import java.io.File; @@ -244,11 +245,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private static final String LEGACY = "legacy"; private static final String SECURE = "secure"; + /** + * Machine type for s390x architecture + */ + private static final String S390X_VIRTIO_DEVICE = "s390-ccw-virtio"; + /** * Machine type. */ - private static final String PC = "pc"; - private static final String VIRT = "virt"; + private static final String PC = isHostS390x() ? S390X_VIRTIO_DEVICE : "pc"; + private static final String VIRT = isHostS390x() ? S390X_VIRTIO_DEVICE : "virt"; /** * Possible devices to add to VM. @@ -305,6 +311,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv * Constant that defines ARM64 (aarch64) guest architectures. */ private static final String AARCH64 = "aarch64"; + /** + * Constant that defines IBM Z Arch (s390x) guest architectures. + */ + private static final String S390X = "s390x"; public static final String RESIZE_NOTIFY_ONLY = "NOTIFYONLY"; public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; @@ -1796,7 +1806,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv "^dummy", "^lo", "^p\\d+p\\d+", - "^vni" + "^vni", + "^enc" }; /** @@ -2642,12 +2653,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } devices.addDevice(createChannelDef(vmTO)); - devices.addDevice(createWatchDogDef()); + if (!isGuestS390x()) { + devices.addDevice(createWatchDogDef()); + } devices.addDevice(createVideoDef(vmTO)); devices.addDevice(createConsoleDef()); devices.addDevice(createGraphicDef(vmTO)); - devices.addDevice(createTabletInputDef()); - + if (!isGuestS390x()) { + devices.addDevice(createTabletInputDef()); + } if (isGuestAarch64()) { createArm64UsbDef(devices); } @@ -2765,7 +2779,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv FeaturesDef features = new FeaturesDef(); features.addFeatures(PAE); features.addFeatures(APIC); - features.addFeatures(ACPI); + if (!isHostS390x()) { + features.addFeatures(ACPI); + } if (isUefiEnabled && isSecureBoot) { features.addFeatures(SMM); } @@ -2857,6 +2873,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return AARCH64.equals(guestCpuArch); } + private boolean isGuestS390x() { + return S390X.equals(guestCpuArch); + } + /** * Creates a guest definition from a VM specification. */ @@ -2867,7 +2887,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv guest.setManufacturer(vmTO.getMetadataManufacturer()); guest.setProduct(vmTO.getMetadataProductName()); guest.setGuestArch(guestCpuArch != null ? guestCpuArch : vmTO.getArch()); - guest.setMachineType(isGuestAarch64() ? VIRT : PC); + guest.setMachineType((isGuestAarch64() || isGuestS390x()) ? VIRT : PC); guest.setBootType(GuestDef.BootType.BIOS); if (MapUtils.isNotEmpty(customParams)) { if (customParams.containsKey(GuestDef.BootType.UEFI.toString())) { @@ -2881,7 +2901,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv guest.setIothreads(customParams.containsKey(VmDetailConstants.IOTHREADS)); } guest.setUuid(uuid); - guest.setBootOrder(GuestDef.BootOrder.CDROM); + if(!isGuestS390x()) { + guest.setBootOrder(GuestDef.BootOrder.CDROM); + } guest.setBootOrder(GuestDef.BootOrder.HARDISK); return guest; } @@ -3122,7 +3144,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv final DiskDef.DiskType diskType = getDiskType(physicalDisk); disk.defISODisk(volPath, devId, isUefiEnabled, diskType); - if (guestCpuArch != null && guestCpuArch.equals("aarch64")) { + if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) { disk.setBusType(DiskDef.DiskBus.SCSI); } } else { @@ -3220,7 +3242,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (vmSpec.getType() != VirtualMachine.Type.User) { final DiskDef iso = new DiskDef(); iso.defISODisk(sysvmISOPath, DiskDef.DiskType.FILE); - if (guestCpuArch != null && guestCpuArch.equals("aarch64")) { + if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) { iso.setBusType(DiskDef.DiskBus.SCSI); } vm.getDevices().addDevice(iso); @@ -4294,7 +4316,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return DiskDef.DiskBus.VIRTIO; } else if (isUefiEnabled && StringUtils.startsWithAny(platformEmulator, "Windows", "Other")) { return DiskDef.DiskBus.SATA; - } else if (guestCpuArch != null && guestCpuArch.equals("aarch64")) { + } else if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) { return DiskDef.DiskBus.SCSI; } else { return DiskDef.DiskBus.IDE; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index 39373ab6e3b..82617696954 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -248,7 +248,9 @@ public class LibvirtVMDef { guestDef.append("\n"); } } - guestDef.append("\n"); + if (!(_arch != null && _arch.equals("s390x"))) { + guestDef.append("\n"); + } guestDef.append("\n"); if (iothreads) { guestDef.append(String.format("%s", NUMBER_OF_IOTHREADS)); @@ -580,7 +582,7 @@ public class LibvirtVMDef { } } - if (_emulator != null && _emulator.endsWith("aarch64")) { + if (_emulator != null && (_emulator.endsWith("aarch64") || _emulator.endsWith("s390x"))) { devicesBuilder.append("\n"); for (int i = 0; i < 32; i++) { devicesBuilder.append("\n"); @@ -1652,7 +1654,7 @@ public class LibvirtVMDef { if (_scriptPath != null) { netBuilder.append("