[libvirt] [PATCH 0/4] Misc fixes to JSON/QMP mode for latest upstream QEMU

Just some misc fixes to make QMP mode work again for latest upstreqam QEMU GIT. NB this is OK because QMP isn't declared stable yet & isn't enabled in libvirt

The <console> tag is supposed to result in addition of a single <serial> device for HVM guests. The 'targetType' attribute was missing though causing the compatibility code to add a second <console> device * src/conf/domain_conf.c: Set targetType for serial device --- src/conf/domain_conf.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 74c2337..e548d1d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3749,6 +3749,7 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, } def->nserials = 1; def->serials[0] = chr; + chr->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL; } } else { def->console = chr; -- 1.6.6

On Fri, Jan 22, 2010 at 05:01:11PM +0000, Daniel P. Berrange wrote:
The <console> tag is supposed to result in addition of a single <serial> device for HVM guests. The 'targetType' attribute was missing though causing the compatibility code to add a second <console> device
* src/conf/domain_conf.c: Set targetType for serial device --- src/conf/domain_conf.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 74c2337..e548d1d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3749,6 +3749,7 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, } def->nserials = 1; def->serials[0] = chr; + chr->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL; } } else { def->console = chr;
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Two files were using functions from <sys/stat.h> but not including in. Most of the time they got this automatically via another header, but certain build flag combinations can reveal the problem * src/lxc/lxc_container.c, src/node_device/node_device_linux_sysfs.c: Add <sys/stat.h> --- src/lxc/lxc_container.c | 1 + src/node_device/node_device_linux_sysfs.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 539a1f4..02242c7 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -32,6 +32,7 @@ #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/wait.h> +#include <sys/stat.h> #include <unistd.h> #include <mntent.h> diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 361a084..33e658d 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -23,6 +23,7 @@ #include <config.h> #include <fcntl.h> +#include <sys/stat.h> #include "node_device_driver.h" #include "node_device_hal.h" -- 1.6.6

On Fri, Jan 22, 2010 at 05:01:12PM +0000, Daniel P. Berrange wrote:
Two files were using functions from <sys/stat.h> but not including in. Most of the time they got this automatically via another header, but certain build flag combinations can reveal the problem
* src/lxc/lxc_container.c, src/node_device/node_device_linux_sysfs.c: Add <sys/stat.h> --- src/lxc/lxc_container.c | 1 + src/node_device/node_device_linux_sysfs.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 539a1f4..02242c7 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -32,6 +32,7 @@ #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/wait.h> +#include <sys/stat.h> #include <unistd.h> #include <mntent.h>
diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 361a084..33e658d 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -23,6 +23,7 @@ #include <config.h>
#include <fcntl.h> +#include <sys/stat.h>
#include "node_device_driver.h" #include "node_device_hal.h"
ACK, I remember seeing some warning on builds for stat() but there were another one, I need to dig out ... here they are: --------------------- CC libvirt_driver_lxc_la-lxc_driver.lo lxc/lxc_container.c: In function 'lxcContainerPopulateDevices': lxc/lxc_container.c:465: warning: implicit declaration of function 'mknod' lxc/lxc_container.c:465: warning: nested extern declaration of 'mknod' lxc/lxc_container.c:466: warning: implicit declaration of function 'chmod' lxc/lxc_container.c:466: warning: nested extern declaration of 'chmod' and CC libvirt_lxc-lxc_controller.o lxc/lxc_container.c: In function 'lxcContainerPopulateDevices': lxc/lxc_container.c:465: warning: implicit declaration of function 'mknod' lxc/lxc_container.c:465: warning: nested extern declaration of 'mknod' lxc/lxc_container.c:466: warning: implicit declaration of function 'chmod' lxc/lxc_container.c:466: warning: nested extern declaration of 'chmod' --------------------- since <fcntl.h> <sys/types.h> and <unistd.h> are in src/lxc/lxc_driver.c I think this means #include <sys/stat.h> should also be added to src/lxc/lxc_driver.c too to avoid the warning, can you add it too ? thanks, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Mon, Jan 25, 2010 at 03:15:27PM +0100, Daniel Veillard wrote:
On Fri, Jan 22, 2010 at 05:01:12PM +0000, Daniel P. Berrange wrote:
Two files were using functions from <sys/stat.h> but not including in. Most of the time they got this automatically via another header, but certain build flag combinations can reveal the problem
* src/lxc/lxc_container.c, src/node_device/node_device_linux_sysfs.c: Add <sys/stat.h> --- src/lxc/lxc_container.c | 1 + src/node_device/node_device_linux_sysfs.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 539a1f4..02242c7 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -32,6 +32,7 @@ #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/wait.h> +#include <sys/stat.h> #include <unistd.h> #include <mntent.h>
diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 361a084..33e658d 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -23,6 +23,7 @@ #include <config.h>
#include <fcntl.h> +#include <sys/stat.h>
#include "node_device_driver.h" #include "node_device_hal.h"
ACK, I remember seeing some warning on builds for stat() but there were another one, I need to dig out ... here they are:
--------------------- CC libvirt_driver_lxc_la-lxc_driver.lo lxc/lxc_container.c: In function 'lxcContainerPopulateDevices': lxc/lxc_container.c:465: warning: implicit declaration of function 'mknod' lxc/lxc_container.c:465: warning: nested extern declaration of 'mknod' lxc/lxc_container.c:466: warning: implicit declaration of function 'chmod' lxc/lxc_container.c:466: warning: nested extern declaration of 'chmod'
and
CC libvirt_lxc-lxc_controller.o lxc/lxc_container.c: In function 'lxcContainerPopulateDevices': lxc/lxc_container.c:465: warning: implicit declaration of function 'mknod' lxc/lxc_container.c:465: warning: nested extern declaration of 'mknod' lxc/lxc_container.c:466: warning: implicit declaration of function 'chmod' lxc/lxc_container.c:466: warning: nested extern declaration of 'chmod' ---------------------
since <fcntl.h> <sys/types.h> and <unistd.h> are in src/lxc/lxc_driver.c I think this means #include <sys/stat.h> should also be added to src/lxc/lxc_driver.c too to avoid the warning, can you add it too ?
Those warnings you paste are the ones that my patch is fixing - I don't think we need to change lxc_driver.c - just lxc_container.c should be sufficient, as lxc_driver.c doesn't use the mknod/chmod stuff at all. 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 Mon, Jan 25, 2010 at 02:22:16PM +0000, Daniel P. Berrange wrote:
On Mon, Jan 25, 2010 at 03:15:27PM +0100, Daniel Veillard wrote:
On Fri, Jan 22, 2010 at 05:01:12PM +0000, Daniel P. Berrange wrote:
Two files were using functions from <sys/stat.h> but not including in. Most of the time they got this automatically via another header, but certain build flag combinations can reveal the problem
* src/lxc/lxc_container.c, src/node_device/node_device_linux_sysfs.c: Add <sys/stat.h> --- src/lxc/lxc_container.c | 1 + src/node_device/node_device_linux_sysfs.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 539a1f4..02242c7 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -32,6 +32,7 @@ #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/wait.h> +#include <sys/stat.h> #include <unistd.h> #include <mntent.h>
diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 361a084..33e658d 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -23,6 +23,7 @@ #include <config.h>
#include <fcntl.h> +#include <sys/stat.h>
#include "node_device_driver.h" #include "node_device_hal.h"
ACK, I remember seeing some warning on builds for stat() but there were another one, I need to dig out ... here they are:
--------------------- CC libvirt_driver_lxc_la-lxc_driver.lo lxc/lxc_container.c: In function 'lxcContainerPopulateDevices': lxc/lxc_container.c:465: warning: implicit declaration of function 'mknod' lxc/lxc_container.c:465: warning: nested extern declaration of 'mknod' lxc/lxc_container.c:466: warning: implicit declaration of function 'chmod' lxc/lxc_container.c:466: warning: nested extern declaration of 'chmod'
and
CC libvirt_lxc-lxc_controller.o lxc/lxc_container.c: In function 'lxcContainerPopulateDevices': lxc/lxc_container.c:465: warning: implicit declaration of function 'mknod' lxc/lxc_container.c:465: warning: nested extern declaration of 'mknod' lxc/lxc_container.c:466: warning: implicit declaration of function 'chmod' lxc/lxc_container.c:466: warning: nested extern declaration of 'chmod' ---------------------
since <fcntl.h> <sys/types.h> and <unistd.h> are in src/lxc/lxc_driver.c I think this means #include <sys/stat.h> should also be added to src/lxc/lxc_driver.c too to avoid the warning, can you add it too ?
Those warnings you paste are the ones that my patch is fixing - I don't think we need to change lxc_driver.c - just lxc_container.c should be sufficient, as lxc_driver.c doesn't use the mknod/chmod stuff at all.
Ah, right, I got confused byt the output, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

* src/util/json.c, src/util/json.h: Declare returned strings to be const * src/qemu/qemu_monitor.c: Wire up JSON mode for qemuMonitorGetPtyPaths * src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h: Fix const correctness. Add missing error message in the function qemuMonitorJSONGetAllPCIAddresses. Add implementation of the qemuMonitorGetPtyPaths function calling 'query-chardev'. --- src/qemu/qemu_monitor.c | 7 ++- src/qemu/qemu_monitor_json.c | 121 +++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_monitor_json.h | 3 + src/util/json.c | 4 +- src/util/json.h | 4 +- 5 files changed, 128 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 031df30..817ccd7 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1245,10 +1245,15 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, int qemuMonitorGetPtyPaths(qemuMonitorPtr mon, virHashTablePtr paths) { + int ret; DEBUG("mon=%p, fd=%d", mon, mon->fd); - return qemuMonitorTextGetPtyPaths(mon, paths); + if (mon->json) + ret = qemuMonitorJSONGetPtyPaths(mon, paths); + else + ret = qemuMonitorTextGetPtyPaths(mon, paths); + return ret; } diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 57e2ad9..7dd2bdb 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -65,7 +65,7 @@ static int qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon, virJSONValuePtr obj) { - char *type; + const char *type; int i; VIR_DEBUG("mon=%p obj=%p", mon, obj); @@ -248,7 +248,7 @@ qemuMonitorJSONCommand(qemuMonitorPtr mon, */ static char *qemuMonitorJSONStringifyError(virJSONValuePtr error) { - char *klass = virJSONValueObjectGetString(error, "class"); + const char *klass = virJSONValueObjectGetString(error, "class"); if (klass) { return strdup(klass); @@ -304,7 +304,7 @@ qemuMonitorJSONHasError(virJSONValuePtr reply, const char *klass) { virJSONValuePtr error; - char *thisklass; + const char *thisklass; if (!virJSONValueObjectHasKey(reply, "error")) return 0; @@ -592,11 +592,19 @@ int qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon, /* Success */ if (ret == 0) { + virJSONValuePtr data; unsigned long long mem; - if (virJSONValueObjectGetNumberUlong(reply, "return", &mem) < 0) { + if (!(data = virJSONValueObjectGet(reply, "return"))) { qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", - _("info balloon reply was missing mem return data")); + _("info balloon reply was missing return data")); + ret = -1; + goto cleanup; + } + + if (virJSONValueObjectGetNumberUlong(data, "balloon", &mem) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("info balloon reply was missing balloon data")); ret = -1; goto cleanup; } @@ -916,7 +924,7 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, unsigned long long *total) { virJSONValuePtr ret; - char *statusstr; + const char *statusstr; if (!(ret = virJSONValueObjectGet(reply, "return"))) { qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", @@ -1483,6 +1491,105 @@ int qemuMonitorJSONRemoveHostNetwork(qemuMonitorPtr mon, } +/* + * Example return data + * + * {"return": [ + * {"filename": "stdio", "label": "monitor"}, + * {"filename": "pty:/dev/pts/6", "label": "serial0"}, + * {"filename": "pty:/dev/pts/7", "label": "parallel0"} + * ]} + * + */ +static int qemuMonitorJSONExtractPtyPaths(virJSONValuePtr reply, + virHashTablePtr paths) +{ + virJSONValuePtr data; + int ret = -1; + int i; + + if (!(data = virJSONValueObjectGet(reply, "return"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device reply was missing return data")); + goto cleanup; + } + + if (data->type != VIR_JSON_TYPE_ARRAY) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was not an array")); + goto cleanup; + } + + for (i = 0 ; i < virJSONValueArraySize(data) ; i++) { + virJSONValuePtr entry = virJSONValueArrayGet(data, i); + const char *type; + const char *id; + if (!entry) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing aray element")); + goto cleanup; + } + + if (!(type = virJSONValueObjectGetString(entry, "filename"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing filename")); + goto cleanup; + } + + if (!(id = virJSONValueObjectGetString(entry, "label"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing filename")); + goto cleanup; + } + + if (STRPREFIX(type, "pty:")) { + char *path = strdup(type + strlen("pty:")); + if (!path) { + virReportOOMError(NULL); + goto cleanup; + } + + if (virHashAddEntry(paths, id, path) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("failed to save chardev path '%s'"), path); + VIR_FREE(path); + goto cleanup; + } + } + } + + ret = 0; + +cleanup: + return ret; +} + +int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths) + +{ + int ret; + virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-chardev", + NULL); + virJSONValuePtr reply = NULL; + + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + if (ret == 0) + ret = qemuMonitorJSONExtractPtyPaths(reply, paths); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, virDomainDevicePCIAddress *guestAddr) @@ -1594,5 +1701,7 @@ int qemuMonitorJSONAttachDrive(qemuMonitorPtr mon, int qemuMonitorJSONGetAllPCIAddresses(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuMonitorPCIAddress **addrs ATTRIBUTE_UNUSED) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("query-pci not suppported in JSON mode")); return -1; } diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 7db9785..858aac0 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -141,6 +141,9 @@ int qemuMonitorJSONRemoveHostNetwork(qemuMonitorPtr mon, int vlan, const char *netname); +int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths); + int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, virDomainDevicePCIAddress *guestAddr); diff --git a/src/util/json.c b/src/util/json.c index 4b3e629..a292e1b 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -440,7 +440,7 @@ virJSONValuePtr virJSONValueArrayGet(virJSONValuePtr array, unsigned int element return array->data.array.values[element]; } -char *virJSONValueGetString(virJSONValuePtr string) +const char *virJSONValueGetString(virJSONValuePtr string) { if (string->type != VIR_JSON_TYPE_STRING) return NULL; @@ -508,7 +508,7 @@ int virJSONValueIsNull(virJSONValuePtr val) } -char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key) +const char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key) { virJSONValuePtr val; if (object->type != VIR_JSON_TYPE_OBJECT) diff --git a/src/util/json.h b/src/util/json.h index 7468628..1af9d9d 100644 --- a/src/util/json.h +++ b/src/util/json.h @@ -99,7 +99,7 @@ virJSONValuePtr virJSONValueObjectGet(virJSONValuePtr object, const char *key); int virJSONValueArraySize(virJSONValuePtr object); virJSONValuePtr virJSONValueArrayGet(virJSONValuePtr object, unsigned int element); -char *virJSONValueGetString(virJSONValuePtr object); +const char *virJSONValueGetString(virJSONValuePtr object); int virJSONValueGetNumberInt(virJSONValuePtr object, int *value); int virJSONValueGetNumberUint(virJSONValuePtr object, unsigned int *value); int virJSONValueGetNumberLong(virJSONValuePtr object, long long *value); @@ -108,7 +108,7 @@ int virJSONValueGetNumberDouble(virJSONValuePtr object, double *value); int virJSONValueGetBoolean(virJSONValuePtr object); int virJSONValueIsNull(virJSONValuePtr object); -char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key); +const char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key); int virJSONValueObjectGetNumberInt(virJSONValuePtr object, const char *key, int *value); int virJSONValueObjectGetNumberUint(virJSONValuePtr object, const char *key, unsigned int *value); int virJSONValueObjectGetNumberLong(virJSONValuePtr object, const char *key, long long *value); -- 1.6.6

On Fri, Jan 22, 2010 at 05:01:13PM +0000, Daniel P. Berrange wrote:
* src/util/json.c, src/util/json.h: Declare returned strings to be const * src/qemu/qemu_monitor.c: Wire up JSON mode for qemuMonitorGetPtyPaths * src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h: Fix const correctness. Add missing error message in the function qemuMonitorJSONGetAllPCIAddresses. Add implementation of the qemuMonitorGetPtyPaths function calling 'query-chardev'. --- src/qemu/qemu_monitor.c | 7 ++- src/qemu/qemu_monitor_json.c | 121 +++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_monitor_json.h | 3 + src/util/json.c | 4 +- src/util/json.h | 4 +- 5 files changed, 128 insertions(+), 11 deletions(-)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 031df30..817ccd7 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1245,10 +1245,15 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, int qemuMonitorGetPtyPaths(qemuMonitorPtr mon, virHashTablePtr paths) { + int ret; DEBUG("mon=%p, fd=%d", mon, mon->fd);
- return qemuMonitorTextGetPtyPaths(mon, paths); + if (mon->json) + ret = qemuMonitorJSONGetPtyPaths(mon, paths); + else + ret = qemuMonitorTextGetPtyPaths(mon, paths); + return ret; }
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 57e2ad9..7dd2bdb 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -65,7 +65,7 @@ static int qemuMonitorJSONIOProcessEvent(qemuMonitorPtr mon, virJSONValuePtr obj) { - char *type; + const char *type; int i; VIR_DEBUG("mon=%p obj=%p", mon, obj);
@@ -248,7 +248,7 @@ qemuMonitorJSONCommand(qemuMonitorPtr mon, */ static char *qemuMonitorJSONStringifyError(virJSONValuePtr error) { - char *klass = virJSONValueObjectGetString(error, "class"); + const char *klass = virJSONValueObjectGetString(error, "class");
if (klass) { return strdup(klass); @@ -304,7 +304,7 @@ qemuMonitorJSONHasError(virJSONValuePtr reply, const char *klass) { virJSONValuePtr error; - char *thisklass; + const char *thisklass;
if (!virJSONValueObjectHasKey(reply, "error")) return 0; @@ -592,11 +592,19 @@ int qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
/* Success */ if (ret == 0) { + virJSONValuePtr data; unsigned long long mem;
- if (virJSONValueObjectGetNumberUlong(reply, "return", &mem) < 0) { + if (!(data = virJSONValueObjectGet(reply, "return"))) { qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", - _("info balloon reply was missing mem return data")); + _("info balloon reply was missing return data")); + ret = -1; + goto cleanup; + } + + if (virJSONValueObjectGetNumberUlong(data, "balloon", &mem) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("info balloon reply was missing balloon data")); ret = -1; goto cleanup; } @@ -916,7 +924,7 @@ qemuMonitorJSONGetMigrationStatusReply(virJSONValuePtr reply, unsigned long long *total) { virJSONValuePtr ret; - char *statusstr; + const char *statusstr;
if (!(ret = virJSONValueObjectGet(reply, "return"))) { qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", @@ -1483,6 +1491,105 @@ int qemuMonitorJSONRemoveHostNetwork(qemuMonitorPtr mon, }
+/* + * Example return data + * + * {"return": [ + * {"filename": "stdio", "label": "monitor"}, + * {"filename": "pty:/dev/pts/6", "label": "serial0"}, + * {"filename": "pty:/dev/pts/7", "label": "parallel0"} + * ]} + * + */ +static int qemuMonitorJSONExtractPtyPaths(virJSONValuePtr reply, + virHashTablePtr paths) +{ + virJSONValuePtr data; + int ret = -1; + int i; + + if (!(data = virJSONValueObjectGet(reply, "return"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device reply was missing return data")); + goto cleanup; + } + + if (data->type != VIR_JSON_TYPE_ARRAY) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was not an array")); + goto cleanup; + } + + for (i = 0 ; i < virJSONValueArraySize(data) ; i++) { + virJSONValuePtr entry = virJSONValueArrayGet(data, i); + const char *type; + const char *id; + if (!entry) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing aray element")); + goto cleanup; + } + + if (!(type = virJSONValueObjectGetString(entry, "filename"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing filename")); + goto cleanup; + } + + if (!(id = virJSONValueObjectGetString(entry, "label"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing filename")); + goto cleanup; + } + + if (STRPREFIX(type, "pty:")) { + char *path = strdup(type + strlen("pty:")); + if (!path) { + virReportOOMError(NULL); + goto cleanup; + } + + if (virHashAddEntry(paths, id, path) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("failed to save chardev path '%s'"), path); + VIR_FREE(path); + goto cleanup; + } + } + } + + ret = 0; + +cleanup: + return ret; +} + +int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths) + +{ + int ret; + virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-chardev", + NULL); + virJSONValuePtr reply = NULL; + + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + if (ret == 0) + ret = qemuMonitorJSONExtractPtyPaths(reply, paths); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, virDomainDevicePCIAddress *guestAddr) @@ -1594,5 +1701,7 @@ int qemuMonitorJSONAttachDrive(qemuMonitorPtr mon, int qemuMonitorJSONGetAllPCIAddresses(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuMonitorPCIAddress **addrs ATTRIBUTE_UNUSED) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("query-pci not suppported in JSON mode")); return -1; } diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 7db9785..858aac0 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -141,6 +141,9 @@ int qemuMonitorJSONRemoveHostNetwork(qemuMonitorPtr mon, int vlan, const char *netname);
+int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon, + virHashTablePtr paths); + int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon, const char *bus, virDomainDevicePCIAddress *guestAddr); diff --git a/src/util/json.c b/src/util/json.c index 4b3e629..a292e1b 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -440,7 +440,7 @@ virJSONValuePtr virJSONValueArrayGet(virJSONValuePtr array, unsigned int element return array->data.array.values[element]; }
-char *virJSONValueGetString(virJSONValuePtr string) +const char *virJSONValueGetString(virJSONValuePtr string) { if (string->type != VIR_JSON_TYPE_STRING) return NULL; @@ -508,7 +508,7 @@ int virJSONValueIsNull(virJSONValuePtr val) }
-char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key) +const char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key) { virJSONValuePtr val; if (object->type != VIR_JSON_TYPE_OBJECT) diff --git a/src/util/json.h b/src/util/json.h index 7468628..1af9d9d 100644 --- a/src/util/json.h +++ b/src/util/json.h @@ -99,7 +99,7 @@ virJSONValuePtr virJSONValueObjectGet(virJSONValuePtr object, const char *key); int virJSONValueArraySize(virJSONValuePtr object); virJSONValuePtr virJSONValueArrayGet(virJSONValuePtr object, unsigned int element);
-char *virJSONValueGetString(virJSONValuePtr object); +const char *virJSONValueGetString(virJSONValuePtr object); int virJSONValueGetNumberInt(virJSONValuePtr object, int *value); int virJSONValueGetNumberUint(virJSONValuePtr object, unsigned int *value); int virJSONValueGetNumberLong(virJSONValuePtr object, long long *value); @@ -108,7 +108,7 @@ int virJSONValueGetNumberDouble(virJSONValuePtr object, double *value); int virJSONValueGetBoolean(virJSONValuePtr object); int virJSONValueIsNull(virJSONValuePtr object);
-char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key); +const char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key); int virJSONValueObjectGetNumberInt(virJSONValuePtr object, const char *key, int *value); int virJSONValueObjectGetNumberUint(virJSONValuePtr object, const char *key, unsigned int *value); int virJSONValueObjectGetNumberLong(virJSONValuePtr object, const char *key, long long *value);
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

The KVM build of QEMU includs the thread ID of each vCPU in the 'query-cpus' output. This is required for pinning guests to particular host CPUs * src/qemu/qemu_monitor_json.c: Extract 'thread_id' from CPU info --- src/qemu/qemu_monitor_json.c | 82 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 81 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 7dd2bdb..8e88c7e 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -536,6 +536,85 @@ int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon) } +/* + * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 }, + * { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ] + */ +static int +qemuMonitorJSONExtractCPUInfo(virJSONValuePtr reply, + int **pids) +{ + virJSONValuePtr data; + int ret = -1; + int i; + int *threads = NULL; + int ncpus; + + if (!(data = virJSONValueObjectGet(reply, "return"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu reply was missing return data")); + goto cleanup; + } + + if (data->type != VIR_JSON_TYPE_ARRAY) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was not an array")); + goto cleanup; + } + + if ((ncpus = virJSONValueArraySize(data)) <= 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was empty")); + goto cleanup; + } + + if (VIR_REALLOC_N(threads, ncpus) < 0) { + virReportOOMError(NULL); + goto cleanup; + } + + for (i = 0 ; i < ncpus ; i++) { + virJSONValuePtr entry = virJSONValueArrayGet(data, i); + int cpu; + int thread; + if (!entry) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing aray element")); + goto cleanup; + } + + if (virJSONValueObjectGetNumberInt(entry, "CPU", &cpu) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was missing cpu number")); + goto cleanup; + } + + if (virJSONValueObjectGetNumberInt(entry, "thread_id", &thread) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was missing thread ID")); + goto cleanup; + } + + if (cpu != i) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("unexpected cpu index %d expecting %d"), + i, cpu); + goto cleanup; + } + + threads[i] = thread; + } + + *pids = threads; + threads = NULL; + ret = 0; + +cleanup: + VIR_FREE(threads); + return ret; +} + + int qemuMonitorJSONGetCPUInfo(qemuMonitorPtr mon, int **pids) { @@ -554,7 +633,8 @@ int qemuMonitorJSONGetCPUInfo(qemuMonitorPtr mon, if (ret == 0) ret = qemuMonitorJSONCheckError(cmd, reply); - /* XXX extract PIDs if present - QEMU hasn't implement this yet :-( */ + if (ret == 0) + ret = qemuMonitorJSONExtractCPUInfo(reply, pids); virJSONValueFree(cmd); virJSONValueFree(reply); -- 1.6.6

On Fri, Jan 22, 2010 at 05:01:14PM +0000, Daniel P. Berrange wrote:
The KVM build of QEMU includs the thread ID of each vCPU in the 'query-cpus' output. This is required for pinning guests to particular host CPUs
* src/qemu/qemu_monitor_json.c: Extract 'thread_id' from CPU info --- src/qemu/qemu_monitor_json.c | 82 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 81 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 7dd2bdb..8e88c7e 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -536,6 +536,85 @@ int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon) }
+/* + * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 }, + * { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ] + */ +static int +qemuMonitorJSONExtractCPUInfo(virJSONValuePtr reply, + int **pids) +{ + virJSONValuePtr data; + int ret = -1; + int i; + int *threads = NULL; + int ncpus; + + if (!(data = virJSONValueObjectGet(reply, "return"))) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu reply was missing return data")); + goto cleanup; + } + + if (data->type != VIR_JSON_TYPE_ARRAY) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was not an array")); + goto cleanup; + } + + if ((ncpus = virJSONValueArraySize(data)) <= 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was empty")); + goto cleanup; + } + + if (VIR_REALLOC_N(threads, ncpus) < 0) { + virReportOOMError(NULL); + goto cleanup; + } + + for (i = 0 ; i < ncpus ; i++) { + virJSONValuePtr entry = virJSONValueArrayGet(data, i); + int cpu; + int thread; + if (!entry) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("character device information was missing aray element")); + goto cleanup; + } + + if (virJSONValueObjectGetNumberInt(entry, "CPU", &cpu) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was missing cpu number")); + goto cleanup; + } + + if (virJSONValueObjectGetNumberInt(entry, "thread_id", &thread) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cpu information was missing thread ID")); + goto cleanup; + } + + if (cpu != i) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("unexpected cpu index %d expecting %d"), + i, cpu); + goto cleanup; + } + + threads[i] = thread; + } + + *pids = threads; + threads = NULL; + ret = 0; + +cleanup: + VIR_FREE(threads); + return ret; +} + + int qemuMonitorJSONGetCPUInfo(qemuMonitorPtr mon, int **pids) { @@ -554,7 +633,8 @@ int qemuMonitorJSONGetCPUInfo(qemuMonitorPtr mon, if (ret == 0) ret = qemuMonitorJSONCheckError(cmd, reply);
- /* XXX extract PIDs if present - QEMU hasn't implement this yet :-( */ + if (ret == 0) + ret = qemuMonitorJSONExtractCPUInfo(reply, pids);
virJSONValueFree(cmd); virJSONValueFree(reply);
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard