[libvirt] [PATCH 4/7] qemu_agent: Introduce helpers for agent based CPU hot(un)plug
Eric Blake
eblake at redhat.com
Mon Apr 15 23:09:14 UTC 2013
On 04/15/2013 09:11 AM, Peter Krempa wrote:
> The qemu guest agent allows to online and offline CPUs from the perspective of
> the guest. This patch adds helpers that call 'guest-get-vcpus' and
> 'guest-set-vcpus' guest agent functions and convert the data for internal
> libvirt usage.
> ---
> src/qemu/qemu_agent.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_agent.h | 12 +++++
> 2 files changed, 149 insertions(+)
>
> diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
> +int
> +qemuAgentGetVCPUs(qemuAgentPtr mon,
> + qemuAgentCPUInfoPtr *info)
> +{
> + int ret = -1;
> + int i;
> + virJSONValuePtr cmd;
> + virJSONValuePtr reply = NULL;
> + virJSONValuePtr data = NULL;
> +
> + if (!(cmd = qemuAgentMakeCommand("guest-get-vcpus", NULL)))
> + return -1;
> +
> + if (qemuAgentCommand(mon, cmd, &reply,
> + VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0 ||
> + qemuAgentCheckError(cmd, reply) < 0)
> + goto cleanup;
> +
> + if (!(data = virJSONValueObjectGet(reply, "return"))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("guest-get-vcpus reply was missing return data"));
> + goto cleanup;
> + }
> +
> + if (data->type != VIR_JSON_TYPE_ARRAY) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("guest-get-vcpus return information was not an array"));
> + goto cleanup;
> + }
> +
> + if (VIR_ALLOC_N(*info, virJSONValueArraySize(data)) < 0) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> + for (i = 0 ; i < virJSONValueArraySize(data) ; i++) {
Quite a few calls to this...
> + virJSONValuePtr entry = virJSONValueArrayGet(data, i);
> + qemuAgentCPUInfoPtr in = *info + i;
> +
> + if (!entry) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("array element missing in guest-get-vcpus return "
> + "value"));
> + goto cleanup;
> + }
> +
> + if (virJSONValueObjectGetNumberUint(entry, "logical-id", &in->id) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("'logical-id' missing in reply of guest-get-vcpus"));
> + goto cleanup;
> + }
> +
> + if (virJSONValueObjectGetBoolean(entry, "online", &in->online) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("'online' missing in reply of guest-get-vcpus "));
trailing space in the error message
> + goto cleanup;
> + }
> +
> + if (virJSONValueObjectGetBoolean(entry, "can-offline",
> + &in->offlinable) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("'can-offline' missing in reply of guest-get-vcpus"));
> + goto cleanup;
> + }
> + }
> +
> + ret = virJSONValueArraySize(data);
...and again. Worth caching in a local variable?
> +
> +cleanup:
> + virJSONValueFree(cmd);
> + virJSONValueFree(reply);
> + virJSONValueFree(data);
> + return ret;
> +}
I checked qemu's qga/qapi-schema.json, and this matches the documentation.
> +
> +int
> +qemuAgentSetVCPUs(qemuAgentPtr mon,
> + qemuAgentCPUInfoPtr info,
> + size_t ninfo)
> +{
> + int ret = -1;
> + virJSONValuePtr cmd = NULL;
> + virJSONValuePtr reply = NULL;
> + virJSONValuePtr cpus = NULL;
> + virJSONValuePtr cpu = NULL;
> + size_t i;
> +
> + /* create the key data array */
> + if (!(cpus = virJSONValueNewArray()))
> + goto no_memory;
> +
> + for (i = 0; i < ninfo; i++) {
> + qemuAgentCPUInfoPtr in = &info[i];
> +
> + /* create single cpu object */
> + if (!(cpu = virJSONValueNewObject()))
> + goto no_memory;
> +
> + if (virJSONValueObjectAppendNumberInt(cpu, "logical-id", in->id) < 0)
> + goto no_memory;
> +
> + if (virJSONValueObjectAppendBoolean(cpu, "online", in->online) < 0)
> + goto no_memory;
> +
> + if (virJSONValueArrayAppend(cpus, cpu) < 0)
> + goto no_memory;
> +
> + cpu = NULL;
> + }
> +
> + if (!(cmd = qemuAgentMakeCommand("guest-set-vcpus",
> + "a:vcpus", cpus,
> + NULL)))
> + goto cleanup;
This has transfer semantics - after this point, cpus is owned by cmd.
You need to do:
cpus = NULL
here...
> +
> + if (qemuAgentCommand(mon, cmd, &reply,
> + VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0 ||
> + qemuAgentCheckError(cmd, reply) < 0)
> + goto cleanup;
> +
> + if (virJSONValueObjectGetNumberInt(reply, "return", &ret) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("malformed return value"));
> + }
Potential problem. In the qga documentation, this function is
documented as returning < ninfo if the command partially succeeded. I
don't know how you plan on using this in later functions, but it might
be worth documenting that this function has the same read()-like
semantics (a return of -1 is outright error, a return of 0 meant no
changes were requested, a return of < ninfo means the first few values
were processed before hitting an error, and a return of ninfo means all
changes were successful).
> +
> +cleanup:
> + virJSONValueFree(cmd);
> + virJSONValueFree(reply);
> + virJSONValueFree(cpu);
> + virJSONValueFree(cpus);
...in order to avoid a double-free here.
> + return ret;
> +
> +no_memory:
> + virReportOOMError();
> + goto cleanup;
> +}
> diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
> index ba04e61..79be283 100644
> --- a/src/qemu/qemu_agent.h
> +++ b/src/qemu/qemu_agent.h
> @@ -82,4 +82,16 @@ int qemuAgentArbitraryCommand(qemuAgentPtr mon,
> int timeout);
> int qemuAgentFSTrim(qemuAgentPtr mon,
> unsigned long long minimum);
> +
> +
> +typedef struct _qemuAgentCPUInfo qemuAgentCPUInfo;
> +typedef qemuAgentCPUInfo *qemuAgentCPUInfoPtr;
> +struct _qemuAgentCPUInfo {
> + unsigned int id; /* locigal cpu ID */
s/locigal/logical/
> + bool online; /* true if the CPU is activated */
> + bool offlinable; /* true if the CPU can be offlined - ignored when setting*/
space before */, and maybe wrap this long line
Enough comments that it is probably worth seeing a v2 (or at least
waiting for my review of the client of this new function in the tail of
the series).
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 621 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20130415/e712d6e8/attachment-0001.sig>
More information about the libvir-list
mailing list