Skip to content

Commit 5df15a7

Browse files
authored
KVM/s390x Support: Add support for KVM on s390x architecture (#10038)
Signed-off-by: Niyam Siwach <niyam@ibm.com> Signed-off-by: Himanshu Mishra <Himanshu.Mishra2@ibm.com>
1 parent 398ffc3 commit 5df15a7

File tree

7 files changed

+52
-19
lines changed

7 files changed

+52
-19
lines changed

agent/conf/agent.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ hypervisor.type=kvm
209209
# the management server would send.
210210
# In case of arm64 (aarch64), this will change the machine type to 'virt' and
211211
# adds a SCSI and a USB controller in the domain xml.
212-
# Possible values: x86_64 | aarch64
212+
# Possible values: x86_64 | aarch64 | s390x
213213
# If null (default), defaults to the VM's OS architecture
214214
#guest.cpu.arch=
215215

agent/src/main/java/com/cloud/agent/properties/AgentProperties.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ public class AgentProperties{
383383
/**
384384
* This param will set the CPU architecture for the domain to override what the management server would send.<br>
385385
* 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.<br>
386-
* Possible values: x86_64 | aarch64 <br>
386+
* Possible values: x86_64 | aarch64 | s390x <br>
387387
* Data type: String.<br>
388388
* Default value: <code>null</code> (will set use the architecture of the VM's OS).
389389
*/

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

+34-12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.cloud.host.Host.HOST_INSTANCE_CONVERSION;
2020
import static com.cloud.host.Host.HOST_VOLUME_ENCRYPTION;
21+
import static org.apache.cloudstack.utils.linux.KVMHostInfo.isHostS390x;
2122

2223
import java.io.BufferedReader;
2324
import java.io.File;
@@ -244,11 +245,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
244245
private static final String LEGACY = "legacy";
245246
private static final String SECURE = "secure";
246247

248+
/**
249+
* Machine type for s390x architecture
250+
*/
251+
private static final String S390X_VIRTIO_DEVICE = "s390-ccw-virtio";
252+
247253
/**
248254
* Machine type.
249255
*/
250-
private static final String PC = "pc";
251-
private static final String VIRT = "virt";
256+
private static final String PC = isHostS390x() ? S390X_VIRTIO_DEVICE : "pc";
257+
private static final String VIRT = isHostS390x() ? S390X_VIRTIO_DEVICE : "virt";
252258

253259
/**
254260
* Possible devices to add to VM.
@@ -305,6 +311,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
305311
* Constant that defines ARM64 (aarch64) guest architectures.
306312
*/
307313
private static final String AARCH64 = "aarch64";
314+
/**
315+
* Constant that defines IBM Z Arch (s390x) guest architectures.
316+
*/
317+
private static final String S390X = "s390x";
308318

309319
public static final String RESIZE_NOTIFY_ONLY = "NOTIFYONLY";
310320
public static final String BASEPATH = "/usr/share/cloudstack-common/vms/";
@@ -1796,7 +1806,8 @@ private String matchPifFileInDirectory(final String bridgeName) {
17961806
"^dummy",
17971807
"^lo",
17981808
"^p\\d+p\\d+",
1799-
"^vni"
1809+
"^vni",
1810+
"^enc"
18001811
};
18011812

18021813
/**
@@ -2642,12 +2653,15 @@ protected DevicesDef createDevicesDef(VirtualMachineTO vmTO, GuestDef guest, int
26422653
}
26432654

26442655
devices.addDevice(createChannelDef(vmTO));
2645-
devices.addDevice(createWatchDogDef());
2656+
if (!isGuestS390x()) {
2657+
devices.addDevice(createWatchDogDef());
2658+
}
26462659
devices.addDevice(createVideoDef(vmTO));
26472660
devices.addDevice(createConsoleDef());
26482661
devices.addDevice(createGraphicDef(vmTO));
2649-
devices.addDevice(createTabletInputDef());
2650-
2662+
if (!isGuestS390x()) {
2663+
devices.addDevice(createTabletInputDef());
2664+
}
26512665
if (isGuestAarch64()) {
26522666
createArm64UsbDef(devices);
26532667
}
@@ -2765,7 +2779,9 @@ protected FeaturesDef createFeaturesDef(Map<String, String> customParams, boolea
27652779
FeaturesDef features = new FeaturesDef();
27662780
features.addFeatures(PAE);
27672781
features.addFeatures(APIC);
2768-
features.addFeatures(ACPI);
2782+
if (!isHostS390x()) {
2783+
features.addFeatures(ACPI);
2784+
}
27692785
if (isUefiEnabled && isSecureBoot) {
27702786
features.addFeatures(SMM);
27712787
}
@@ -2857,6 +2873,10 @@ private boolean isGuestAarch64() {
28572873
return AARCH64.equals(guestCpuArch);
28582874
}
28592875

2876+
private boolean isGuestS390x() {
2877+
return S390X.equals(guestCpuArch);
2878+
}
2879+
28602880
/**
28612881
* Creates a guest definition from a VM specification.
28622882
*/
@@ -2867,7 +2887,7 @@ protected GuestDef createGuestFromSpec(VirtualMachineTO vmTO, LibvirtVMDef vm, S
28672887
guest.setManufacturer(vmTO.getMetadataManufacturer());
28682888
guest.setProduct(vmTO.getMetadataProductName());
28692889
guest.setGuestArch(guestCpuArch != null ? guestCpuArch : vmTO.getArch());
2870-
guest.setMachineType(isGuestAarch64() ? VIRT : PC);
2890+
guest.setMachineType((isGuestAarch64() || isGuestS390x()) ? VIRT : PC);
28712891
guest.setBootType(GuestDef.BootType.BIOS);
28722892
if (MapUtils.isNotEmpty(customParams)) {
28732893
if (customParams.containsKey(GuestDef.BootType.UEFI.toString())) {
@@ -2881,7 +2901,9 @@ protected GuestDef createGuestFromSpec(VirtualMachineTO vmTO, LibvirtVMDef vm, S
28812901
guest.setIothreads(customParams.containsKey(VmDetailConstants.IOTHREADS));
28822902
}
28832903
guest.setUuid(uuid);
2884-
guest.setBootOrder(GuestDef.BootOrder.CDROM);
2904+
if(!isGuestS390x()) {
2905+
guest.setBootOrder(GuestDef.BootOrder.CDROM);
2906+
}
28852907
guest.setBootOrder(GuestDef.BootOrder.HARDISK);
28862908
return guest;
28872909
}
@@ -3122,7 +3144,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
31223144
final DiskDef.DiskType diskType = getDiskType(physicalDisk);
31233145
disk.defISODisk(volPath, devId, isUefiEnabled, diskType);
31243146

3125-
if (guestCpuArch != null && guestCpuArch.equals("aarch64")) {
3147+
if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) {
31263148
disk.setBusType(DiskDef.DiskBus.SCSI);
31273149
}
31283150
} else {
@@ -3220,7 +3242,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
32203242
if (vmSpec.getType() != VirtualMachine.Type.User) {
32213243
final DiskDef iso = new DiskDef();
32223244
iso.defISODisk(sysvmISOPath, DiskDef.DiskType.FILE);
3223-
if (guestCpuArch != null && guestCpuArch.equals("aarch64")) {
3245+
if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) {
32243246
iso.setBusType(DiskDef.DiskBus.SCSI);
32253247
}
32263248
vm.getDevices().addDevice(iso);
@@ -4294,7 +4316,7 @@ private DiskDef.DiskBus getGuestDiskModel(final String platformEmulator, boolean
42944316
return DiskDef.DiskBus.VIRTIO;
42954317
} else if (isUefiEnabled && StringUtils.startsWithAny(platformEmulator, "Windows", "Other")) {
42964318
return DiskDef.DiskBus.SATA;
4297-
} else if (guestCpuArch != null && guestCpuArch.equals("aarch64")) {
4319+
} else if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) {
42984320
return DiskDef.DiskBus.SCSI;
42994321
} else {
43004322
return DiskDef.DiskBus.IDE;

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ public String toString() {
248248
guestDef.append("<boot dev='" + bo + "'/>\n");
249249
}
250250
}
251-
guestDef.append("<smbios mode='sysinfo'/>\n");
251+
if (!(_arch != null && _arch.equals("s390x"))) {
252+
guestDef.append("<smbios mode='sysinfo'/>\n");
253+
}
252254
guestDef.append("</os>\n");
253255
if (iothreads) {
254256
guestDef.append(String.format("<iothreads>%s</iothreads>", NUMBER_OF_IOTHREADS));
@@ -580,7 +582,7 @@ public String toString() {
580582
}
581583
}
582584

583-
if (_emulator != null && _emulator.endsWith("aarch64")) {
585+
if (_emulator != null && (_emulator.endsWith("aarch64") || _emulator.endsWith("s390x"))) {
584586
devicesBuilder.append("<controller type='pci' model='pcie-root'/>\n");
585587
for (int i = 0; i < 32; i++) {
586588
devicesBuilder.append("<controller type='pci' model='pcie-root-port'/>\n");
@@ -1652,7 +1654,7 @@ public String getContent() {
16521654
if (_scriptPath != null) {
16531655
netBuilder.append("<script path='" + _scriptPath + "'/>\n");
16541656
}
1655-
if (_pxeDisable) {
1657+
if (_pxeDisable && !"s390x".equals(System.getProperty("os.arch"))) {
16561658
netBuilder.append("<rom bar='off' file=''/>");
16571659
}
16581660
if (_virtualPortType != null) {

plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/KVMHostInfo.java

+7
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ public String getCpuArch() {
111111
return cpuArch;
112112
}
113113

114+
public static boolean isHostS390x() {
115+
return "s390x".equals(System.getProperty("os.arch"));
116+
}
117+
114118
protected static long getCpuSpeed(final String cpabilities, final NodeInfo nodeInfo) {
115119
long speed = 0L;
116120
speed = getCpuSpeedFromCommandLscpu();
@@ -137,6 +141,9 @@ private static long getCpuSpeedFromCommandLscpu() {
137141
try {
138142
LOGGER.info("Fetching CPU speed from command \"lscpu\".");
139143
String command = "lscpu | grep -i 'Model name' | head -n 1 | egrep -o '[[:digit:]].[[:digit:]]+GHz' | sed 's/GHz//g'";
144+
if(isHostS390x()) {
145+
command = "lscpu | grep 'CPU dynamic MHz' | cut -d ':' -f 2 | tr -d ' ' | awk '{printf \"%.1f\\n\", $1 / 1000}'";
146+
}
140147
String result = Script.runSimpleBashScript(command);
141148
long speed = (long) (Float.parseFloat(result) * 1000);
142149
LOGGER.info(String.format("Command [%s] resulted in the value [%s] for CPU speed.", command, speed));

plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ public void testCreateGuestFromSpecWithoutCustomParam() {
401401
VirtualMachineTO to = createDefaultVM(false);
402402
LibvirtVMDef vm = new LibvirtVMDef();
403403
GuestDef guestDef = libvirtComputingResourceSpy.createGuestFromSpec(to, vm, to.getUuid(), null);
404-
verifySysInfo(guestDef, "smbios", to.getUuid(), "pc");
404+
verifySysInfo(guestDef, "smbios", to.getUuid(), "s390x".equals(System.getProperty("os.arch")) ? "s390-ccw-virtio" : "pc");
405405
Assert.assertEquals(GuestDef.BootType.BIOS, guestDef.getBootType());
406406
Assert.assertNull(guestDef.getBootMode());
407407
}
@@ -829,7 +829,7 @@ private void verifyOsBoot(Document domainDoc) {
829829
}
830830

831831
private void verifyOsType(Document domainDoc) {
832-
assertXpath(domainDoc, "/domain/os/type/@machine", "pc");
832+
assertXpath(domainDoc, "/domain/os/type/@machine", "s390x".equals(System.getProperty("os.arch")) ? "s390-ccw-virtio" : "pc");
833833
assertXpath(domainDoc, "/domain/os/type/text()", "hvm");
834834
}
835835

server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java

+2
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) {
309309

310310
if (vmProfile.getTemplate().getBits() == 32) {
311311
to.setArch("i686");
312+
} else if("s390x".equals(System.getProperty("os.arch"))) {
313+
to.setArch("s390x");
312314
} else {
313315
to.setArch("x86_64");
314316
}

0 commit comments

Comments
 (0)