[libvirt] [PATCH 0/9] New public API for computing baseline CPU

Hi, This series introduces a new virConnectBaselineCPU() API call for computing baseline CPU model from a set of host CPU definitions. The call accepts a list of <cpu>...</cpu> xml definitions taken from host capabilities and returns an xml description of a guest CPU which is supported by all hosts. virsh is little bit less picky and accepts a file containing host CPU definitions. It doesn't care what is outside of the <cpu/> tag, which allows for concatenating outputs of virsh capabilities from several hosts and feeding the result to virsh cpu-baseline. This series can also be found on cpu-baseline branch of git://gitorious.org/~jirka/libvirt/jirka-staging.git In practice it works like this: # virsh cpu-baseline /dev/stdin >guest-cpu <<EOF <capabilities> <host> <cpu> <arch>x86_64</arch> <model>core2duo</model> <topology sockets='1' cores='2' threads='1'/> <feature name='lahf_lm'/> <feature name='xtpr'/> <feature name='cx16'/> <feature name='tm2'/> <feature name='est'/> <feature name='vmx'/> </cpu> </host> </capabilities> <cpu> <arch>i686</arch> <model>pentiumpro</model> <topology sockets='1' cores='2' threads='1'/> <feature name='vme'/> <feature name='pse36'/> <feature name='pni'/> <feature name='monitor'/> <feature name='ssse3'/> </cpu> <cpu> <arch>x86_64</arch> <model>phenom</model> </cpu> EOF # cat guest-cpu <cpu match='exact'> <model>qemu32</model> <feature policy='require' name='monitor'/> <feature policy='require' name='pse36'/> </cpu> Jiri Denemark (9): Functions for computing baseline CPU from a set of host CPUs Implement cpuArchBaseline in generic CPU driver Implement cpuArchBaseline in x86 CPU driver virConnectBaselineCPU public API Internal driver API for virConnectBaselineCPU virConnectBaselineCPU public API implementation Wire protocol format and dispatcher for virConnectBaselineCPU Implement cpuBaseline in remote and qemu drivers cpu-baseline command for virsh daemon/remote.c | 25 +++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 ++ include/libvirt/libvirt.h.in | 18 +++++ src/cpu/cpu.c | 125 ++++++++++++++++++++++++++++++++++- src/cpu/cpu.h | 23 ++++++- src/cpu/cpu_generic.c | 104 ++++++++++++++++++++++++++++- src/cpu/cpu_x86.c | 88 ++++++++++++++++++++++++- src/driver.h | 6 ++ src/esx/esx_driver.c | 1 + src/libvirt.c | 57 ++++++++++++++++ src/libvirt_private.syms | 2 + src/libvirt_public.syms | 5 ++ src/lxc/lxc_driver.c | 1 + src/opennebula/one_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 14 ++++ src/remote/remote_driver.c | 32 +++++++++ src/remote/remote_protocol.c | 24 +++++++- src/remote/remote_protocol.h | 20 ++++++ src/remote/remote_protocol.x | 18 +++++- src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/xen/xen_driver.c | 1 + tools/virsh.c | 72 ++++++++++++++++++++ tools/virsh.pod | 8 ++ 30 files changed, 658 insertions(+), 7 deletions(-)

Baseline CPU is the best CPU which can be used for a guest on any of the hosts. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 125 +++++++++++++++++++++++++++++++++++++++++++++- src/cpu/cpu.h | 23 ++++++++- src/cpu/cpu_generic.c | 3 +- src/cpu/cpu_x86.c | 3 +- src/libvirt_private.syms | 2 + 5 files changed, 152 insertions(+), 4 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 3e46948..1438d13 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1,7 +1,7 @@ /* * cpu.c: internal functions for CPU manipulation * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009--2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,6 +23,7 @@ #include <config.h> +#include "memory.h" #include "xml.h" #include "cpu.h" #include "cpu_x86.h" @@ -245,3 +246,125 @@ cpuGuestData(virConnectPtr conn, return driver->guestData(host, guest, data); } + + +char * +cpuBaselineXML(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int nmodels, + const char **models) +{ + xmlDocPtr doc = NULL; + xmlXPathContextPtr ctxt = NULL; + virCPUDefPtr *cpus = NULL; + virCPUDefPtr cpu; + char *cpustr; + unsigned int i; + + if (xmlCPUs == NULL && ncpus != 0) { + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("nonzero ncpus doesn't match with NULL xmlCPUs")); + return NULL; + } + + if (ncpus < 1) { + virCPUReportError(conn, VIR_ERR_INVALID_ARG, "%s", _("No CPUs given")); + return NULL; + } + + if (VIR_ALLOC_N(cpus, ncpus)) + goto no_memory; + + for (i = 0; i < ncpus; i++) { + doc = xmlParseMemory(xmlCPUs[i], strlen(xmlCPUs[i])); + if (doc == NULL || (ctxt = xmlXPathNewContext(doc)) == NULL) + goto no_memory; + + ctxt->node = xmlDocGetRootElement(doc); + + cpus[i] = virCPUDefParseXML(conn, ctxt->node, ctxt, VIR_CPU_TYPE_HOST); + if (cpus[i] == NULL) + goto error; + + xmlXPathFreeContext(ctxt); + xmlFreeDoc(doc); + ctxt = NULL; + doc = NULL; + } + + if (!(cpu = cpuBaseline(conn, ncpus, cpus, nmodels, models))) + goto error; + + cpustr = virCPUDefFormat(conn, cpu, "", 0); + +cleanup: + if (cpus) { + for (i = 0; i < ncpus; i++) + virCPUDefFree(cpus[i]); + VIR_FREE(cpus); + } + virCPUDefFree(cpu); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(doc); + + return cpustr; + +no_memory: + virReportOOMError(conn); +error: + cpustr = NULL; + goto cleanup; +} + + +virCPUDefPtr +cpuBaseline(virConnectPtr conn, + unsigned int ncpus, + virCPUDefPtr *cpus, + unsigned int nmodels, + const char **models) +{ + struct cpuArchDriver *driver; + virCPUDefPtr cpu; + + if (cpus == NULL && ncpus != 0) { + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("nonzero ncpus doesn't match with NULL cpus")); + return NULL; + } + + if (ncpus < 1) { + virCPUReportError(conn, VIR_ERR_INVALID_ARG, "%s", _("No CPUs given")); + return NULL; + } + + if (models == NULL && nmodels != 0) { + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("nonzero nmodels doesn't match with NULL models")); + return NULL; + } + + if ((driver = cpuGetSubDriver(conn, cpus[0]->arch)) == NULL) + return NULL; + + if (driver->baseline == NULL) { + virCPUReportError(conn, VIR_ERR_NO_SUPPORT, + _("cannot compute baseline CPU of %s architecture"), + cpus[0]->arch); + return NULL; + } + + if ((cpu = driver->baseline(ncpus, cpus, nmodels, models))) { + int i; + + cpu->type = VIR_CPU_TYPE_GUEST; + cpu->match = VIR_CPU_MATCH_EXACT; + VIR_FREE(cpu->arch); + + for (i = 0; i < cpu->nfeatures; i++) + cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE; + } + + return cpu; +} diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 5b1636d..a51fac8 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -1,7 +1,7 @@ /* * cpu.h: internal functions for CPU manipulation * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009--2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -70,6 +70,12 @@ typedef virCPUCompareResult virCPUDefPtr guest, union cpuData **data); +typedef virCPUDefPtr +(*cpuArchBaseline) (unsigned int ncpus, + virCPUDefPtr *cpus, + unsigned int nmodels, + const char **models); + struct cpuArchDriver { const char *name; @@ -81,6 +87,7 @@ struct cpuArchDriver { cpuArchDataFree free; cpuArchNodeData nodeData; cpuArchGuestData guestData; + cpuArchBaseline baseline; }; @@ -126,4 +133,18 @@ cpuGuestData(virConnectPtr conn, virCPUDefPtr guest, union cpuData **data); +extern char * +cpuBaselineXML(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int nmodels, + const char **models); + +extern virCPUDefPtr +cpuBaseline (virConnectPtr conn, + unsigned int ncpus, + virCPUDefPtr *cpus, + unsigned int nmodels, + const char **models); + #endif /* __VIR_CPU_H__ */ diff --git a/src/cpu/cpu_generic.c b/src/cpu/cpu_generic.c index b18c1b4..16bc4b0 100644 --- a/src/cpu/cpu_generic.c +++ b/src/cpu/cpu_generic.c @@ -118,5 +118,6 @@ struct cpuArchDriver cpuDriverGeneric = { .encode = NULL, .free = NULL, .nodeData = NULL, - .guestData = NULL + .guestData = NULL, + .baseline = NULL, }; diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index ce55588..f316db1 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1205,5 +1205,6 @@ struct cpuArchDriver cpuDriverX86 = { #else .nodeData = NULL, #endif - .guestData = x86GuestData + .guestData = x86GuestData, + .baseline = NULL, }; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7573af3..aa826d6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -72,6 +72,8 @@ virCgroupSetFreezerState; # cpu.h +cpuBaseline; +cpuBaselineXML; cpuCompare; cpuCompareXML; cpuDataFree; -- 1.6.6.1

On Fri, Feb 05, 2010 at 04:56:50PM +0100, Jiri Denemark wrote:
Baseline CPU is the best CPU which can be used for a guest on any of the hosts.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 125 +++++++++++++++++++++++++++++++++++++++++++++- src/cpu/cpu.h | 23 ++++++++- src/cpu/cpu_generic.c | 3 +- src/cpu/cpu_x86.c | 3 +- src/libvirt_private.syms | 2 + 5 files changed, 152 insertions(+), 4 deletions(-)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 3e46948..1438d13 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1,7 +1,7 @@ /* * cpu.c: internal functions for CPU manipulation * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009--2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,6 +23,7 @@
#include <config.h>
+#include "memory.h" #include "xml.h" #include "cpu.h" #include "cpu_x86.h" @@ -245,3 +246,125 @@ cpuGuestData(virConnectPtr conn,
return driver->guestData(host, guest, data); } + + +char * +cpuBaselineXML(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int nmodels, + const char **models)
In the other APIs we have, the array length is typically after the array pointer. Could you swap this array here to match and the other related places Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_generic.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu_generic.c b/src/cpu/cpu_generic.c index 16bc4b0..dc35b30 100644 --- a/src/cpu/cpu_generic.c +++ b/src/cpu/cpu_generic.c @@ -2,7 +2,7 @@ * cpu_generic.c: CPU manipulation driver for architectures which are not * handled by their own driver * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009--2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include <config.h> +#include "memory.h" #include "hash.h" #include "cpu.h" #include "cpu_generic.h" @@ -109,6 +110,104 @@ cleanup: } +static virCPUDefPtr +genericBaseline(unsigned int ncpus, + virCPUDefPtr *cpus, + unsigned int nmodels, + const char **models) +{ + virCPUDefPtr cpu = NULL; + virCPUFeatureDefPtr features = NULL; + unsigned int nfeatures; + unsigned int count; + unsigned int i, j; + + if (models) { + bool found = false; + for (i = 0; i < nmodels; i++) { + if (STREQ(cpus[0]->model, models[i])) { + found = true; + break; + } + } + if (!found) { + virCPUReportError(NULL, VIR_ERR_INTERNAL_ERROR, + _("CPU model '%s' is not support by hypervisor"), + cpus[0]->model); + goto error; + } + } + + if (VIR_ALLOC(cpu) < 0 || + !(cpu->arch = strdup(cpus[0]->arch)) || + !(cpu->model = strdup(cpus[0]->model)) || + VIR_ALLOC_N(features, cpus[0]->nfeatures) < 0) + goto no_memory; + + cpu->type = VIR_CPU_TYPE_HOST; + + count = nfeatures = cpus[0]->nfeatures; + for (i = 0; i < nfeatures; i++) + features[i].name = cpus[0]->features[i].name; + + for (i = 1; i < ncpus; i++) { + virHashTablePtr hash; + + if (STRNEQ(cpu->arch, cpus[i]->arch)) { + virCPUReportError(NULL, VIR_ERR_INTERNAL_ERROR, + _("CPUs have incompatible architectures: '%s' != '%s'"), + cpu->arch, cpus[i]->arch); + goto error; + } + + if (STRNEQ(cpu->model, cpus[i]->model)) { + virCPUReportError(NULL, VIR_ERR_INTERNAL_ERROR, + _("CPU models don't match: '%s' != '%s'"), + cpu->model, cpus[i]->model); + goto error; + } + + if (!(hash = genericHashFeatures(cpus[i]))) + goto no_memory; + + for (j = 0; j < nfeatures; j++) { + if (features[j].name && + !virHashLookup(hash, features[j].name)) { + features[j].name = NULL; + count--; + } + } + + virHashFree(hash, NULL); + } + + if (VIR_ALLOC_N(cpu->features, count) < 0) + goto no_memory; + cpu->nfeatures = count; + + j = 0; + for (i = 0; i < nfeatures; i++) { + if (!features[i].name) + continue; + + if (!(cpu->features[j++].name = strdup(features[i].name))) + goto no_memory; + } + +cleanup: + VIR_FREE(features); + + return cpu; + +no_memory: + virReportOOMError(NULL); +error: + virCPUDefFree(cpu); + cpu = NULL; + goto cleanup; +} + + struct cpuArchDriver cpuDriverGeneric = { .name = "generic", .arch = NULL, @@ -119,5 +218,5 @@ struct cpuArchDriver cpuDriverGeneric = { .free = NULL, .nodeData = NULL, .guestData = NULL, - .baseline = NULL, + .baseline = genericBaseline, }; -- 1.6.6.1

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 86 insertions(+), 1 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index f316db1..a9f04f0 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -137,6 +137,17 @@ x86cpuidClearBits(struct cpuX86cpuid *cpuid, } +static inline void +x86cpuidAndBits(struct cpuX86cpuid *cpuid, + const struct cpuX86cpuid *mask) +{ + cpuid->eax &= mask->eax; + cpuid->ebx &= mask->ebx; + cpuid->ecx &= mask->ecx; + cpuid->edx &= mask->edx; +} + + static struct cpuX86cpuid * x86DataCpuid(const union cpuData *data, uint32_t function) @@ -477,6 +488,27 @@ x86ModelSubtract(struct x86_model *model1, } +static void +x86ModelIntersect(struct x86_model *model1, + const struct x86_model *model2) +{ + int i; + struct cpuX86cpuid *cpuid; + + for (i = 0; i < model1->ncpuid; i++) { + struct cpuX86cpuid *intersection = model1->cpuid + i; + + cpuid = x86cpuidFind(model2->cpuid, + model2->ncpuid, + intersection->function); + if (cpuid != NULL) + x86cpuidAndBits(intersection, cpuid); + else + x86cpuidClearBits(intersection, intersection); + } +} + + static int x86ModelAdd(struct x86_model *model1, const struct x86_model *model2) @@ -1192,6 +1224,59 @@ error: #endif +static virCPUDefPtr +x86Baseline(unsigned int ncpus, + virCPUDefPtr *cpus, + unsigned int nmodels, + const char **models) +{ + struct x86_map *map = NULL; + struct x86_model *base_model = NULL; + union cpuData *data = NULL; + virCPUDefPtr cpu = NULL; + unsigned int i; + + if (!(map = x86LoadMap())) + goto error; + + if (!(base_model = x86ModelFromCPU(cpus[0], map, 0))) + goto error; + + if (VIR_ALLOC(cpu) < 0 || + !(cpu->arch = strdup(cpus[0]->arch))) + goto no_memory; + + for (i = 1; i < ncpus; i++) { + struct x86_model *model; + if (!(model = x86ModelFromCPU(cpus[i], map, 0))) + goto error; + + x86ModelIntersect(base_model, model); + x86ModelFree(model); + } + + if (!(data = x86DataFromModel(base_model))) + goto no_memory; + + if (x86Decode(cpu, data, nmodels, models) < 0) + goto error; + +cleanup: + x86DataFree(data); + x86ModelFree(base_model); + x86MapFree(map); + + return cpu; + +no_memory: + virReportOOMError(NULL); +error: + virCPUDefFree(cpu); + cpu = NULL; + goto cleanup; +} + + struct cpuArchDriver cpuDriverX86 = { .name = "x86", .arch = archs, @@ -1206,5 +1291,5 @@ struct cpuArchDriver cpuDriverX86 = { .nodeData = NULL, #endif .guestData = x86GuestData, - .baseline = NULL, + .baseline = x86Baseline, }; -- 1.6.6.1

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- include/libvirt/libvirt.h.in | 18 ++++++++++++++++++ src/libvirt_public.syms | 5 +++++ 2 files changed, 23 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index f192fb1..0a96a04 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1756,6 +1756,24 @@ int virConnectCompareCPU(virConnectPtr conn, unsigned int flags); +/** + * virConnectBaselineCPU: + * + * @conn: virConnect connection + * @ncpus: number of CPUs in xmlCPUs + * @xmlCPUs: array of XML descriptions of host CPUs + * @flags: fine-tuning flags + * + * Computes the most feature-rich CPU which is compatible with all given + * host CPUs. + * + * Returns XML description of the computed CPU or NULL on error. + */ +char *virConnectBaselineCPU(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0521158..bb4963b 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -349,4 +349,9 @@ LIBVIRT_0.7.5 { virDomainMemoryStats; } LIBVIRT_0.7.3; +LIBVIRT_0.7.7 { + global: + virConnectBaselineCPU; +} LIBVIRT_0.7.5; + # .... define new API here using predicted next version number .... -- 1.6.6.1

On Fri, Feb 05, 2010 at 04:56:53PM +0100, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- include/libvirt/libvirt.h.in | 18 ++++++++++++++++++ src/libvirt_public.syms | 5 +++++ 2 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index f192fb1..0a96a04 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1756,6 +1756,24 @@ int virConnectCompareCPU(virConnectPtr conn, unsigned int flags);
+/** + * virConnectBaselineCPU: + * + * @conn: virConnect connection + * @ncpus: number of CPUs in xmlCPUs + * @xmlCPUs: array of XML descriptions of host CPUs + * @flags: fine-tuning flags + * + * Computes the most feature-rich CPU which is compatible with all given + * host CPUs. + * + * Returns XML description of the computed CPU or NULL on error. + */ +char *virConnectBaselineCPU(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int flags);
Can we switch this one to to have 'ncpus' after xmlCPUs too.
+ #ifdef __cplusplus } #endif diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0521158..bb4963b 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -349,4 +349,9 @@ LIBVIRT_0.7.5 { virDomainMemoryStats; } LIBVIRT_0.7.3;
+LIBVIRT_0.7.7 { + global: + virConnectBaselineCPU; +} LIBVIRT_0.7.5; + # .... define new API here using predicted next version number .... --
Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/driver.h | 6 ++++++ src/esx/esx_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/opennebula/one_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/xen/xen_driver.c | 1 + 12 files changed, 17 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index c7e4fbf..5c3e645 100644 --- a/src/driver.h +++ b/src/driver.h @@ -359,6 +359,11 @@ typedef int (*virDrvCPUCompare)(virConnectPtr conn, const char *cpu, unsigned int flags); +typedef char * + (*virDrvCPUBaseline)(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int flags); /** * _virDriver: @@ -448,6 +453,7 @@ struct _virDriver { virDrvDomainIsActive domainIsActive; virDrvDomainIsPersistent domainIsPersistent; virDrvCPUCompare cpuCompare; + virDrvCPUBaseline cpuBaseline; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index fc5a50e..c97a37b 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -3401,6 +3401,7 @@ static virDriver esxDriver = { esxDomainIsActive, /* domainIsActive */ esxDomainIsPersistent, /* domainIsPersistent */ NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index d78f7f7..b9e5a2e 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2456,6 +2456,7 @@ static virDriver lxcDriver = { lxcDomainIsActive, lxcDomainIsPersistent, NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; static virStateDriver lxcStateDriver = { diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c index c96d24d..b31100c 100644 --- a/src/opennebula/one_driver.c +++ b/src/opennebula/one_driver.c @@ -783,6 +783,7 @@ static virDriver oneDriver = { NULL, /* domainIsActive */ NULL, /* domainIsPersistent */ NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; static virStateDriver oneStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 196fd8c..000a0ca 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1535,6 +1535,7 @@ static virDriver openvzDriver = { openvzDomainIsActive, openvzDomainIsPersistent, NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index bd5cfc7..c4c490a 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -1651,6 +1651,7 @@ virDriver phypDriver = { NULL, /* domainIsActive */ NULL, /* domainIsPersistent */ NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; int diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1e796ef..db07b66 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -8606,6 +8606,7 @@ static virDriver qemuDriver = { qemuDomainIsActive, qemuDomainIsPersistent, qemuCPUCompare, /* cpuCompare */ + NULL, /* cpuBaseline */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d6f5fce..33c3cd3 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8923,6 +8923,7 @@ static virDriver remote_driver = { remoteDomainIsActive, /* domainIsActive */ remoteDomainIsPersistent, /* domainIsPersistent */ remoteCPUCompare, /* cpuCompare */ + NULL, /* cpuBaseline */ }; static virNetworkDriver network_driver = { diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 2122a1b..a56c067 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5238,6 +5238,7 @@ static virDriver testDriver = { testDomainIsActive, /* domainIsActive */ testDomainIsPersistent, /* domainIsPersistent */ NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; static virNetworkDriver testNetworkDriver = { diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 31cea5c..9088e83 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1924,6 +1924,7 @@ static virDriver umlDriver = { umlDomainIsActive, umlDomainIsPersistent, NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index e40c848..a568f5b 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -7035,6 +7035,7 @@ virDriver NAME(Driver) = { vboxDomainIsActive, vboxDomainIsPersistent, NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; virNetworkDriver NAME(NetworkDriver) = { diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 72f56ae..a52157b 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1864,6 +1864,7 @@ static virDriver xenUnifiedDriver = { xenUnifiedDomainIsActive, xenUnifiedDomainisPersistent, NULL, /* cpuCompare */ + NULL, /* cpuBaseline */ }; /** -- 1.6.6.1

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/libvirt.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 57 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 8a9ee20..47ce54e 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -10980,3 +10980,60 @@ error: virDispatchError(conn); return VIR_CPU_COMPARE_ERROR; } + + +/** + * virConnectBaselineCPU: + * + * @conn: virConnect connection + * @ncpus: number of CPUs in xmlCPUs + * @xmlCPUs: array of XML descriptions of host CPUs + * @flags: fine-tuning flags, currently unused, pass 0. + * + * Computes the most feature-rich CPU which is compatible with all given + * host CPUs. + * + * Returns XML description of the computed CPU or NULL on error. + */ +char * +virConnectBaselineCPU(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int flags) +{ + unsigned int i; + + VIR_DEBUG("conn=%p, ncpus=%u, xmlCPUs=%p, flags=%u", + conn, ncpus, xmlCPUs, flags); + if (xmlCPUs) { + for (i = 0; i < ncpus; i++) + VIR_DEBUG("xmlCPUs[%u]=%s", i, xmlCPUs[i]); + } + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return NULL; + } + if (xmlCPUs == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->driver->cpuBaseline) { + char *cpu; + + cpu = conn->driver->cpuBaseline(conn, ncpus, xmlCPUs, flags); + if (!cpu) + goto error; + return cpu; + } + + virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return NULL; +} -- 1.6.6.1

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- daemon/remote.c | 25 +++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_protocol.c | 24 +++++++++++++++++++++++- src/remote/remote_protocol.h | 20 ++++++++++++++++++++ src/remote/remote_protocol.x | 18 +++++++++++++++++- 8 files changed, 100 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 299f971..0ac4ba6 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -5312,6 +5312,31 @@ remoteDispatchCpuCompare(struct qemud_server *server ATTRIBUTE_UNUSED, } +static int +remoteDispatchCpuBaseline(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *err, + remote_cpu_baseline_args *args, + remote_cpu_baseline_ret *ret) +{ + char *cpu; + + cpu = virConnectBaselineCPU(conn, + args->xmlCPUs.xmlCPUs_len, + (const char **) args->xmlCPUs.xmlCPUs_val, + args->flags); + if (cpu == NULL) { + remoteDispatchConnError(err, conn); + return -1; + } + + ret->cpu = cpu; + return 0; +} + + /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index c1801d0..bbf70ff 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -135,3 +135,4 @@ remote_interface_is_active_args val_remote_interface_is_active_args; remote_cpu_compare_args val_remote_cpu_compare_args; remote_domain_memory_stats_args val_remote_domain_memory_stats_args; + remote_cpu_baseline_args val_remote_cpu_baseline_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 1a0f8d8..99cf01c 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -50,6 +50,14 @@ static int remoteDispatchClose( remote_error *err, void *args, void *ret); +static int remoteDispatchCpuBaseline( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_cpu_baseline_args *args, + remote_cpu_baseline_ret *ret); static int remoteDispatchCpuCompare( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h index d7811de..5c6a78f 100644 --- a/daemon/remote_dispatch_ret.h +++ b/daemon/remote_dispatch_ret.h @@ -117,3 +117,4 @@ remote_get_lib_version_ret val_remote_get_lib_version_ret; remote_cpu_compare_ret val_remote_cpu_compare_ret; remote_domain_memory_stats_ret val_remote_domain_memory_stats_ret; + remote_cpu_baseline_ret val_remote_cpu_baseline_ret; diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index 09ebeee..51a897c 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -802,3 +802,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_memory_stats_args, .ret_filter = (xdrproc_t) xdr_remote_domain_memory_stats_ret, }, +{ /* CpuBaseline => 160 */ + .fn = (dispatch_fn) remoteDispatchCpuBaseline, + .args_filter = (xdrproc_t) xdr_remote_cpu_baseline_args, + .ret_filter = (xdrproc_t) xdr_remote_cpu_baseline_ret, +}, diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 834eb6b..4ff6217 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -4,7 +4,7 @@ * It was generated using rpcgen. */ -#include "./remote/remote_protocol.h" +#include "/home/jirka/work/libvirt/git/src/remote/remote_protocol.h" #include "internal.h" #include <arpa/inet.h> @@ -2912,6 +2912,28 @@ xdr_remote_cpu_compare_ret (XDR *xdrs, remote_cpu_compare_ret *objp) } bool_t +xdr_remote_cpu_baseline_args (XDR *xdrs, remote_cpu_baseline_args *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->xmlCPUs.xmlCPUs_val; + + if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->xmlCPUs.xmlCPUs_len, REMOTE_CPU_BASELINE_MAX, + sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_cpu_baseline_ret (XDR *xdrs, remote_cpu_baseline_ret *objp) +{ + + if (!xdr_remote_nonnull_string (xdrs, &objp->cpu)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_procedure (XDR *xdrs, remote_procedure *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index 3f3b520..9c1b341 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -48,6 +48,7 @@ typedef remote_nonnull_string *remote_string; #define REMOTE_SECURITY_DOI_MAX VIR_SECURITY_DOI_BUFLEN #define REMOTE_SECRET_VALUE_MAX 65536 #define REMOTE_SECRET_UUID_LIST_MAX 16384 +#define REMOTE_CPU_BASELINE_MAX 256 typedef char remote_uuid[VIR_UUID_BUFLEN]; @@ -1649,6 +1650,20 @@ struct remote_cpu_compare_ret { int result; }; typedef struct remote_cpu_compare_ret remote_cpu_compare_ret; + +struct remote_cpu_baseline_args { + struct { + u_int xmlCPUs_len; + remote_nonnull_string *xmlCPUs_val; + } xmlCPUs; + u_int flags; +}; +typedef struct remote_cpu_baseline_args remote_cpu_baseline_args; + +struct remote_cpu_baseline_ret { + remote_nonnull_string cpu; +}; +typedef struct remote_cpu_baseline_ret remote_cpu_baseline_ret; #define REMOTE_PROGRAM 0x20008086 #define REMOTE_PROTOCOL_VERSION 1 @@ -1812,6 +1827,7 @@ enum remote_procedure { REMOTE_PROC_GET_LIB_VERSION = 157, REMOTE_PROC_CPU_COMPARE = 158, REMOTE_PROC_DOMAIN_MEMORY_STATS = 159, + REMOTE_PROC_CPU_BASELINE = 160, }; typedef enum remote_procedure remote_procedure; @@ -2114,6 +2130,8 @@ extern bool_t xdr_remote_interface_is_active_args (XDR *, remote_interface_is_a extern bool_t xdr_remote_interface_is_active_ret (XDR *, remote_interface_is_active_ret*); extern bool_t xdr_remote_cpu_compare_args (XDR *, remote_cpu_compare_args*); extern bool_t xdr_remote_cpu_compare_ret (XDR *, remote_cpu_compare_ret*); +extern bool_t xdr_remote_cpu_baseline_args (XDR *, remote_cpu_baseline_args*); +extern bool_t xdr_remote_cpu_baseline_ret (XDR *, remote_cpu_baseline_ret*); extern bool_t xdr_remote_procedure (XDR *, remote_procedure*); extern bool_t xdr_remote_message_type (XDR *, remote_message_type*); extern bool_t xdr_remote_message_status (XDR *, remote_message_status*); @@ -2390,6 +2408,8 @@ extern bool_t xdr_remote_interface_is_active_args (); extern bool_t xdr_remote_interface_is_active_ret (); extern bool_t xdr_remote_cpu_compare_args (); extern bool_t xdr_remote_cpu_compare_ret (); +extern bool_t xdr_remote_cpu_baseline_args (); +extern bool_t xdr_remote_cpu_baseline_ret (); extern bool_t xdr_remote_procedure (); extern bool_t xdr_remote_message_type (); extern bool_t xdr_remote_message_status (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index bed3940..1e9053b 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -155,6 +155,11 @@ const REMOTE_SECRET_VALUE_MAX = 65536; */ const REMOTE_SECRET_UUID_LIST_MAX = 16384; +/* + * Upper limit on list of CPUs accepted when computing a baseline CPU. + */ +const REMOTE_CPU_BASELINE_MAX = 256; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -1461,6 +1466,16 @@ struct remote_cpu_compare_ret { }; +struct remote_cpu_baseline_args { + remote_nonnull_string xmlCPUs<REMOTE_CPU_BASELINE_MAX>; + unsigned flags; +}; + +struct remote_cpu_baseline_ret { + remote_nonnull_string cpu; +}; + + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -1641,7 +1656,8 @@ enum remote_procedure { REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, REMOTE_PROC_GET_LIB_VERSION = 157, REMOTE_PROC_CPU_COMPARE = 158, - REMOTE_PROC_DOMAIN_MEMORY_STATS = 159 + REMOTE_PROC_DOMAIN_MEMORY_STATS = 159, + REMOTE_PROC_CPU_BASELINE = 160 /* * Notice how the entries are grouped in sets of 10 ? -- 1.6.6.1

On Fri, Feb 05, 2010 at 04:56:56PM +0100, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- daemon/remote.c | 25 +++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_protocol.c | 24 +++++++++++++++++++++++- src/remote/remote_protocol.h | 20 ++++++++++++++++++++ src/remote/remote_protocol.x | 18 +++++++++++++++++- 8 files changed, 100 insertions(+), 2 deletions(-)
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 834eb6b..4ff6217 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -4,7 +4,7 @@ * It was generated using rpcgen. */
-#include "./remote/remote_protocol.h" +#include "/home/jirka/work/libvirt/git/src/remote/remote_protocol.h"
That's rather odd. I wonder why rpcgen decided to use absolute includes all of a sudden Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On 02/10/2010 07:11 PM, Daniel P. Berrange wrote:
On Fri, Feb 05, 2010 at 04:56:56PM +0100, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark<jdenemar@redhat.com> --- daemon/remote.c | 25 +++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_ret.h | 1 + daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_protocol.c | 24 +++++++++++++++++++++++- src/remote/remote_protocol.h | 20 ++++++++++++++++++++ src/remote/remote_protocol.x | 18 +++++++++++++++++- 8 files changed, 100 insertions(+), 2 deletions(-)
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 834eb6b..4ff6217 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -4,7 +4,7 @@ * It was generated using rpcgen. */
-#include "./remote/remote_protocol.h" +#include "/home/jirka/work/libvirt/git/src/remote/remote_protocol.h"
That's rather odd. I wonder why rpcgen decided to use absolute includes all of a sudden
Building out of the source tree? Paolo

diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 834eb6b..4ff6217 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -4,7 +4,7 @@ * It was generated using rpcgen. */
-#include "./remote/remote_protocol.h" +#include "/home/jirka/work/libvirt/git/src/remote/remote_protocol.h"
That's rather odd. I wonder why rpcgen decided to use absolute includes all of a sudden
Building out of the source tree?
Exactly. I wonder what's going to be less irritating for me... fixing the build system to actually generate everything correctly in a separate build directory or start building in source directory. Jirka

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_driver.c | 15 ++++++++++++++- src/remote/remote_driver.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index db07b66..ef164be 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -8530,6 +8530,19 @@ qemuCPUCompare(virConnectPtr conn, return ret; } +static char * +qemuCPUBaseline(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int flags ATTRIBUTE_UNUSED) +{ + char *cpu; + + cpu = cpuBaselineXML(conn, ncpus, xmlCPUs, 0, NULL); + + return cpu; +} + static virDriver qemuDriver = { VIR_DRV_QEMU, "QEMU", @@ -8606,7 +8619,7 @@ static virDriver qemuDriver = { qemuDomainIsActive, qemuDomainIsPersistent, qemuCPUCompare, /* cpuCompare */ - NULL, /* cpuBaseline */ + qemuCPUBaseline, /* cpuBaseline */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 33c3cd3..3a8a10f 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7535,6 +7535,37 @@ done: return rv; } + +static char * +remoteCPUBaseline(virConnectPtr conn, + unsigned int ncpus, + const char **xmlCPUs, + unsigned int flags) +{ + struct private_data *priv = conn->privateData; + remote_cpu_baseline_args args; + remote_cpu_baseline_ret ret; + char *cpu = NULL; + + remoteDriverLock(priv); + + args.xmlCPUs.xmlCPUs_len = ncpus; + args.xmlCPUs.xmlCPUs_val = (char **) xmlCPUs; + args.flags = flags; + + memset(&ret, 0, sizeof (ret)); + if (call(conn, priv, 0, REMOTE_PROC_CPU_BASELINE, + (xdrproc_t) xdr_remote_cpu_baseline_args, (char *) &args, + (xdrproc_t) xdr_remote_cpu_baseline_ret, (char *) &ret) == -1) + goto done; + + cpu = ret.cpu; + +done: + remoteDriverUnlock(priv); + return cpu; +} + /*----------------------------------------------------------------------*/ @@ -8923,7 +8954,7 @@ static virDriver remote_driver = { remoteDomainIsActive, /* domainIsActive */ remoteDomainIsPersistent, /* domainIsPersistent */ remoteCPUCompare, /* cpuCompare */ - NULL, /* cpuBaseline */ + remoteCPUBaseline, /* cpuBaseline */ }; static virNetworkDriver network_driver = { -- 1.6.6.1

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tools/virsh.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 8 ++++++ 2 files changed, 80 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 01d2038..2f30a4e 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -6958,6 +6958,77 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) return ret; } +/* + * "cpu-baseline" command + */ +static const vshCmdInfo info_cpu_baseline[] = { + {"help", gettext_noop("compute baseline CPU")}, + {"desc", gettext_noop("Compute baseline CPU for a set of given CPUs.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_cpu_baseline[] = { + {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing XML CPU descriptions")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) +{ + char *from; + int found; + int ret = TRUE; + char *buffer; + char *p; + char *result = NULL; + const char **list = NULL; + unsigned int count = 0; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + return FALSE; + + from = vshCommandOptString(cmd, "file", &found); + if (!found) + return FALSE; + + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) + return FALSE; + + p = buffer; + while ((p = strstr(p, "<cpu>"))) { + list = vshRealloc(ctl, list, sizeof(char *) * (count + 1)); + list[count++] = p; + + if ((p = strstr(p, "</cpu>"))) { + p += strlen("</cpu>"); + if (*p != '\0') { + *p = '\0'; + p++; + } + } + } + + if (count == 0) { + vshError(ctl, _("No host CPU specified in '%s'"), from); + ret = FALSE; + goto cleanup; + } + + result = virConnectBaselineCPU(ctl->conn, count, list, 0); + + if (result) + vshPrint(ctl, "%s", result); + else + ret = FALSE; + +cleanup: + VIR_FREE(result); + VIR_FREE(list); + VIR_FREE(buffer); + + return ret; +} + /* Common code for the edit / net-edit / pool-edit functions which follow. */ static char * editWriteToTempFile (vshControl *ctl, const char *doc) @@ -7329,6 +7400,7 @@ static const vshCmdDef commands[] = { #ifndef WIN32 {"console", cmdConsole, opts_console, info_console}, #endif + {"cpu-baseline", cmdCPUBaseline, opts_cpu_baseline, info_cpu_baseline}, {"cpu-compare", cmdCPUCompare, opts_cpu_compare, info_cpu_compare}, {"create", cmdCreate, opts_create, info_create}, {"start", cmdStart, opts_start, info_start}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 10f622f..8f6df19 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -213,6 +213,14 @@ crashed. Prints the available amount of memory on the machine or within a NUMA cell if I<cellno> is provided. +=item B<cpu-baseline> I<FILE> + +Compute baseline CPU which will be supported by all host CPUs given in <file>. +The list of host CPUs is built by extracting all <cpu> elements from the +<file>. Thus, the <file> can contain either a set of <cpu> elements separated +by new lines or even a set of complete <capabilities> elements printed by +B<capabilities> command. + =item B<cpu-compare> I<FILE> Compare CPU definition from XML <file> with host CPU. The XML <file> may -- 1.6.6.1

On Fri, Feb 05, 2010 at 04:56:49PM +0100, Jiri Denemark wrote:
Hi,
This series introduces a new virConnectBaselineCPU() API call for computing baseline CPU model from a set of host CPU definitions. The call accepts a list of <cpu>...</cpu> xml definitions taken from host capabilities and returns an xml description of a guest CPU which is supported by all hosts.
virsh is little bit less picky and accepts a file containing host CPU definitions. It doesn't care what is outside of the <cpu/> tag, which allows for concatenating outputs of virsh capabilities from several hosts and feeding the result to virsh cpu-baseline.
This series can also be found on cpu-baseline branch of git://gitorious.org/~jirka/libvirt/jirka-staging.git
It all looks pretty good to me. Did the python code generator handle this correctly though ? I'm surprised if it did, because it normally screws up on any API involving arrays. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (3)
-
Daniel P. Berrange
-
Jiri Denemark
-
Paolo Bonzini