一、环境说明
- 操作系统:openEuler 22.03
- CPU:Kunpeng-920,arm v8
- cloudstack:4.18
- libvirtd:6.2.0
二、问题描述
在UI上创建VPC后,平台会同时创建一个virtual router,此时virtual router有两个网卡,分别为private IP(169.;
然后在vpc下创建network,此时virtual router不会绑定network;
创建虚拟机时,指定此network,cloudstack报创建失败。
三、问题排查
当在vpc下的network创建第一个虚拟机时,cloudstack会先将virtual router绑定至该network,其中一个动作是为virtual router附加一个新的网卡,作为该network的网关。
但是虚拟机报创建失败后,查看virtual router仍只有两个网卡,其对应的network name列也是空的。
查看cloudstack management日志发现报错:org.libvirt.LibvirtException: internal error: No more available PCI slots。
而对比普通isolated network对应的virtual router的domain内容(virsh dumpxml),发现vpc下报错的virtual router缺少两个对应pci设备的定义。
通过搜索,在github上查看到类似的issue。
其解决方法是,在./plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java中添加代码如下:
java
if (_emulator != null && _emulator.endsWith("aarch64")) {
devicesBuilder.append("<controller type='pci' model='pcie-root'/>\n");
for (int i = 0; i < 32; i++) {
devicesBuilder.append("<controller type='pci' model='pcie-root-port'/>\n");
}
devicesBuilder.append("<controller type='pci' model='pcie-to-pci-bridge'/>\n");
}
通过_emulator判断为aarch64架构的话,就添加32个pci设备。
但是debug查看,该值在执行至本段代码是为空字符串,且查看上面代码
java
if (_emulator != null) {
devicesBuilder.append("<emulator>" + _emulator + "</emulator>\n");
}
本地查看虚拟机的domain内容,_emulator的值对应为/usr/libexec/qemu-kvm,也没有架构后缀。
因此怀疑本段代码没有普适性。
因此,将本段代码注释掉,修改代码如下:
java
#./plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java 添加一个类
public static class PCIDef {
public PCIDeg() {
}
@Override
public String toString() {
StringBuilder pciBuilder = new StringBuilder();
devicesBuilder.append("<controller type='pci' model='pcie-root'/>\n");
for (int i = 0; i < 32; i++) {
pciBuilder.append("<controller type='pci' model='pcie-root-port'/>\n");
}
pciBuilder.append("<controller type='pci' model='pcie-to-pci-bridge'/>\n");
return pciBuilder.toString();
}
}
#plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java 2553行
if (isGuestAarch64()) {
createArm64UsbDef(devices);
#新增
createArm64PCIDef(devices);
}
#plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java 2580行
protected void createArm64PCIDef(DevicesDef devices) {
devices.addDevice(new LibvirtVMDef.PCIDef());
}