When CPU comparison APIs return VIR_CPU_COMPARE_INCOMPATIBLE, the caller has no clue why the CPU is considered incompatible with host CPU. And in some cases, it would be nice to be able to get such info in a client rather than having to look in logs. To achieve this, the APIs can be told to return VIR_ERR_CPU_INCOMPATIBLE error for incompatible CPUs and the reason will be described in the associated error message. Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- include/libvirt/virterror.h | 2 ++ src/bhyve/bhyve_driver.c | 2 +- src/cpu/cpu.c | 10 ++++++---- src/cpu/cpu.h | 9 ++++++--- src/cpu/cpu_aarch64.c | 3 ++- src/cpu/cpu_arm.c | 3 ++- src/cpu/cpu_generic.c | 15 +++++++++++---- src/cpu/cpu_powerpc.c | 10 ++++++++-- src/cpu/cpu_x86.c | 20 ++++++++++++++++++-- src/qemu/qemu_driver.c | 2 +- src/util/virerror.c | 6 ++++++ tests/cputest.c | 4 ++-- 12 files changed, 65 insertions(+), 21 deletions(-) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index be90797..15ba4f1 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -300,6 +300,8 @@ typedef enum { was denied */ VIR_ERR_DBUS_SERVICE = 89, /* error from a dbus service */ VIR_ERR_STORAGE_VOL_EXIST = 90, /* the storage vol already exists */ + VIR_ERR_CPU_INCOMPATIBLE = 91, /* given CPU is incompatible with host + CPU*/ } virErrorNumber; /** diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index bb9bcb7..9bece84 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -1332,7 +1332,7 @@ bhyveConnectCompareCPU(virConnectPtr conn, VIR_WARN("cannot get host CPU capabilities"); ret = VIR_CPU_COMPARE_INCOMPATIBLE; } else { - ret = cpuCompareXML(caps->host.cpu, xmlDesc); + ret = cpuCompareXML(caps->host.cpu, xmlDesc, false); } cleanup: diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index c3d66dd..08bec5e 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -92,7 +92,8 @@ cpuGetSubDriver(virArch arch) */ virCPUCompareResult cpuCompareXML(virCPUDefPtr host, - const char *xml) + const char *xml, + bool failIncompatible) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; @@ -108,7 +109,7 @@ cpuCompareXML(virCPUDefPtr host, if (cpu == NULL) goto cleanup; - ret = cpuCompare(host, cpu); + ret = cpuCompare(host, cpu, failIncompatible); cleanup: virCPUDefFree(cpu); @@ -134,7 +135,8 @@ cpuCompareXML(virCPUDefPtr host, */ virCPUCompareResult cpuCompare(virCPUDefPtr host, - virCPUDefPtr cpu) + virCPUDefPtr cpu, + bool failIncompatible) { struct cpuArchDriver *driver; @@ -156,7 +158,7 @@ cpuCompare(virCPUDefPtr host, return VIR_CPU_COMPARE_ERROR; } - return driver->compare(host, cpu); + return driver->compare(host, cpu, failIncompatible); } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index e9f2713..339964c 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -46,7 +46,8 @@ struct _virCPUData { typedef virCPUCompareResult (*cpuArchCompare) (virCPUDefPtr host, - virCPUDefPtr cpu); + virCPUDefPtr cpu, + bool failIncompatible); typedef int (*cpuArchDecode) (virCPUDefPtr cpu, @@ -119,12 +120,14 @@ struct cpuArchDriver { extern virCPUCompareResult cpuCompareXML(virCPUDefPtr host, - const char *xml) + const char *xml, + bool failIncompatible) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); extern virCPUCompareResult cpuCompare (virCPUDefPtr host, - virCPUDefPtr cpu) + virCPUDefPtr cpu, + bool failIncompatible) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); extern int diff --git a/src/cpu/cpu_aarch64.c b/src/cpu/cpu_aarch64.c index 7255d9f..6346f9b 100644 --- a/src/cpu/cpu_aarch64.c +++ b/src/cpu/cpu_aarch64.c @@ -110,7 +110,8 @@ AArch64Baseline(virCPUDefPtr *cpus, static virCPUCompareResult AArch64Compare(virCPUDefPtr host ATTRIBUTE_UNUSED, - virCPUDefPtr cpu ATTRIBUTE_UNUSED) + virCPUDefPtr cpu ATTRIBUTE_UNUSED, + bool failIncompatible ATTRIBUTE_UNUSED) { return VIR_CPU_COMPARE_IDENTICAL; } diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index 39e8f12..ec755bd 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -113,7 +113,8 @@ ArmBaseline(virCPUDefPtr *cpus, static virCPUCompareResult ArmCompare(virCPUDefPtr host ATTRIBUTE_UNUSED, - virCPUDefPtr cpu ATTRIBUTE_UNUSED) + virCPUDefPtr cpu ATTRIBUTE_UNUSED, + bool failMessages ATTRIBUTE_UNUSED) { return VIR_CPU_COMPARE_IDENTICAL; } diff --git a/src/cpu/cpu_generic.c b/src/cpu/cpu_generic.c index f115c40..d6890c0 100644 --- a/src/cpu/cpu_generic.c +++ b/src/cpu/cpu_generic.c @@ -57,17 +57,20 @@ genericHashFeatures(virCPUDefPtr cpu) static virCPUCompareResult genericCompare(virCPUDefPtr host, - virCPUDefPtr cpu) + virCPUDefPtr cpu, + bool failIncompatible) { - virHashTablePtr hash; + virHashTablePtr hash = NULL; virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; size_t i; unsigned int reqfeatures; if ((cpu->arch != VIR_ARCH_NONE && host->arch != cpu->arch) || - STRNEQ(host->model, cpu->model)) - return VIR_CPU_COMPARE_INCOMPATIBLE; + STRNEQ(host->model, cpu->model)) { + ret = VIR_CPU_COMPARE_INCOMPATIBLE; + goto cleanup; + } if ((hash = genericHashFeatures(host)) == NULL) goto cleanup; @@ -102,6 +105,10 @@ genericCompare(virCPUDefPtr host, cleanup: virHashFree(hash); + if (failIncompatible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) { + ret = VIR_CPU_COMPARE_ERROR; + virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL); + } return ret; } diff --git a/src/cpu/cpu_powerpc.c b/src/cpu/cpu_powerpc.c index 05fa55b..67cb9ff 100644 --- a/src/cpu/cpu_powerpc.c +++ b/src/cpu/cpu_powerpc.c @@ -440,13 +440,19 @@ ppcCompute(virCPUDefPtr host, static virCPUCompareResult ppcCompare(virCPUDefPtr host, - virCPUDefPtr cpu) + virCPUDefPtr cpu, + bool failIncompatible) { if ((cpu->arch == VIR_ARCH_NONE || host->arch == cpu->arch) && STREQ(host->model, cpu->model)) return VIR_CPU_COMPARE_IDENTICAL; - return VIR_CPU_COMPARE_INCOMPATIBLE; + if (failIncompatible) { + virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL); + return VIR_CPU_COMPARE_ERROR; + } else { + return VIR_CPU_COMPARE_INCOMPATIBLE; + } } static int diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 72c5216..235fa49 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1463,9 +1463,25 @@ x86Compute(virCPUDefPtr host, static virCPUCompareResult x86Compare(virCPUDefPtr host, - virCPUDefPtr cpu) + virCPUDefPtr cpu, + bool failIncomaptible) { - return x86Compute(host, cpu, NULL, NULL); + virCPUCompareResult ret; + char *message = NULL; + + ret = x86Compute(host, cpu, NULL, &message); + + if (failIncomaptible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) { + ret = VIR_CPU_COMPARE_ERROR; + if (message) { + virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", message); + } else { + virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL); + } + } + VIR_FREE(message); + + return ret; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 22699c1..3c23fc7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11528,7 +11528,7 @@ qemuConnectCompareCPU(virConnectPtr conn, VIR_WARN("cannot get host CPU capabilities"); ret = VIR_CPU_COMPARE_INCOMPATIBLE; } else { - ret = cpuCompareXML(caps->host.cpu, xmlDesc); + ret = cpuCompareXML(caps->host.cpu, xmlDesc, false); } cleanup: diff --git a/src/util/virerror.c b/src/util/virerror.c index e0bc970..6bd3d09 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -1277,6 +1277,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("error from service: %s"); break; + case VIR_ERR_CPU_INCOMPATIBLE: + if (info == NULL) + errmsg = _("the CPU is incompatible with host CPU"); + else + errmsg = _("the CPU is incompatible with host CPU: %s"); + break; } return errmsg; } diff --git a/tests/cputest.c b/tests/cputest.c index 3766c2f..38cd71e 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -228,7 +228,7 @@ cpuTestCompare(const void *arg) !(cpu = cpuTestLoadXML(data->arch, data->name))) goto cleanup; - result = cpuCompare(host, cpu); + result = cpuCompare(host, cpu, false); if (data->result == VIR_CPU_COMPARE_ERROR) virResetLastError(); @@ -357,7 +357,7 @@ cpuTestBaseline(const void *arg) for (i = 0; i < ncpus; i++) { virCPUCompareResult cmp; - cmp = cpuCompare(cpus[i], baseline); + cmp = cpuCompare(cpus[i], baseline, false); if (cmp != VIR_CPU_COMPARE_SUPERSET && cmp != VIR_CPU_COMPARE_IDENTICAL) { if (virTestGetVerbose()) { -- 2.0.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list