nova代码里获取libvirt里 os type 的machine的,如果这里获取和qemu不一致,会报如下错误:
libvirtError: internal error: process exited while connecting to monitor: 2017-10-10T06:45:38.821223Z qemu-kvm: -machine pc-i440fx-rhel7.3.0,accel=kvm,usb=off,dump-guest-core=off: unsupported machine type
2017-10-10 14:45:39.131 150753 ERROR oslo_messaging.rpc.server Use -machine help to list supported machines
一般可以用virsh dumpxml instance-name 可以看到 os type 段
<os>
<type arch='x86_64' machine='pc-i440fx-2.6'>hvm</type>
<boot dev='hd'/>
<smbios mode='sysinfo'/>
</os>
获取qemu-kvm支持的machine列表
[root@nova02 ~]# /usr/libexec/qemu-kvm -machine help
Supported machines are:
pc Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-2.6)
pc-i440fx-2.6 Standard PC (i440FX + PIIX, 1996) (default)
pc-i440fx-2.5 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-2.4 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-2.3 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-2.2 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-2.1 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-2.0 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-1.7 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-1.6 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-1.5 Standard PC (i440FX + PIIX, 1996)
pc-i440fx-1.4 Standard PC (i440FX + PIIX, 1996)
pc-1.3 Standard PC (i440FX + PIIX, 1996)
pc-1.2 Standard PC (i440FX + PIIX, 1996)
pc-1.1 Standard PC (i440FX + PIIX, 1996)
pc-1.0 Standard PC (i440FX + PIIX, 1996)
pc-0.15 Standard PC (i440FX + PIIX, 1996)
pc-0.14 Standard PC (i440FX + PIIX, 1996)
pc-0.13 Standard PC (i440FX + PIIX, 1996)
pc-0.12 Standard PC (i440FX + PIIX, 1996)
pc-0.11 Standard PC (i440FX + PIIX, 1996)
pc-0.10 Standard PC (i440FX + PIIX, 1996)
q35 Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-2.6)
pc-q35-2.6 Standard PC (Q35 + ICH9, 2009)
pc-q35-2.5 Standard PC (Q35 + ICH9, 2009)
pc-q35-2.4 Standard PC (Q35 + ICH9, 2009)
isapc ISA-only PC
none empty machine
下面看下nova里如何设置这个machine的
def _machine_type_mappings(self):
mappings = {}
for mapping in CONF.libvirt.hw_machine_type:
host_arch, _, machine_type = mapping.partition('=')
mappings[host_arch] = machine_type
return mappings
def _get_machine_type(self, image_meta, caps):
# The underlying machine type can be set as an image attribute,
# or otherwise based on some architecture specific defaults
mach_type = None
if image_meta.properties.get('hw_machine_type') is not None:
mach_type = image_meta.properties.hw_machine_type
else:
# For ARM systems we will default to vexpress-a15 for armv7
# and virt for aarch64
if caps.host.cpu.arch == fields.Architecture.ARMV7:
mach_type = "vexpress-a15"
if caps.host.cpu.arch == fields.Architecture.AARCH64:
mach_type = "virt"
if caps.host.cpu.arch in (fields.Architecture.S390,
fields.Architecture.S390X):
mach_type = 's390-ccw-virtio'
# If set in the config, use that as the default.
if CONF.libvirt.hw_machine_type:
mappings = self._machine_type_mappings()
mach_type = mappings.get(caps.host.cpu.arch)
return mach_type
glance 设置 hw_machine_type
glance image-update --property hw_machine_type=pc-i440fx-2.6 06865811-b430-414a-8ff2-4eeb2b608c77
从以上代码可以得出,如果image镜像信息里有 hw_machine_type 就直接用了,如果没有就判断caps.host.cpu.arch,如果 arch是x86,就会去 CONF.libvirt.hw_machine_type里找,如果都没有,就会返回空
如果arch 是 x86后,生xml后,libvirt会根据情况生成
下面我们来看libvirt是如何生成这个machine的
if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
def->emulator))) 获取qemu cap
goto cleanup;
if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
goto cleanup;
static int
qemuCanonicalizeMachine(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
{
const char *canon;
if (!(canon = virQEMUCapsGetCanonicalMachine(qemuCaps, def->os.machine)))
return 0;
if (STRNEQ(canon, def->os.machine)) {
char *tmp;
if (VIR_STRDUP(tmp, canon) < 0)
return -1;
VIR_FREE(def->os.machine);
def->os.machine = tmp; 把从qemu获取到的machine赋值给os.mahcine
}
return 0;
}
virQEMUCapsNewForBinaryInternal
libvirt这段代码,还不太明白,有可能不对。但是可以肯于的是libvirt获取machine是也是调用qemu的接口,所以会保持libvirt qemu的一致性。
如果中途切了qemu, 导致qemu os machine发生变化,重启下libvirt就可以了。