[libvirt] [PATCH v2 01/10] Add qemuMonitorJSONGetObjectListPaths() method for QMP qom-list command

Michal Privoznik mprivozn at redhat.com
Thu Jul 11 14:06:00 UTC 2013


On 08.07.2013 21:20, John Ferlan wrote:
> Add a new qemuMonitorJSONGetObjectListPaths() method to support invocation
> of the 'qom-list' JSON monitor command with a provided path.
> 
> The returned list of paired data fields of "name" and "type" that can
> be used to peruse QOM configuration data and eventually utilize for the
> balloon statistics.
> 
> The test does a "{"execute":"qom-list", "arguments": { "path": "/"}}" which
> returns "{"return": [{"name": "machine", "type": "child<container>"},
> {"name": "type", "type": "string"}]}" resulting in a return of an array
> of 2 elements with [0].name="machine", [0].type="child<container>".  The [1]
> entry appears to be a header that could be used some day via a command such
> as "virsh qemuobject --list" to format output.
> ---
>  src/qemu/qemu_monitor_json.c | 102 +++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_monitor_json.h |  16 +++++++
>  tests/qemumonitorjsontest.c  |  79 +++++++++++++++++++++++++++++++++
>  3 files changed, 197 insertions(+)
> 
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 3383c88..fc2b65f 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -4540,6 +4540,108 @@ cleanup:
>  }
>  
>  
> +int qemuMonitorJSONGetObjectListPaths(qemuMonitorPtr mon,
> +                                      const char *path,
> +                                      qemuMonitorJSONListPathPtr **paths)
> +{
> +    int ret;
> +    virJSONValuePtr cmd;
> +    virJSONValuePtr reply = NULL;
> +    virJSONValuePtr data;
> +    qemuMonitorJSONListPathPtr *pathlist = NULL;
> +    int n = 0;
> +    size_t i;
> +
> +    *paths = NULL;
> +
> +    if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
> +                                           "s:path", path,
> +                                           NULL)))
> +        return -1;
> +
> +    ret = qemuMonitorJSONCommand(mon, cmd, &reply);
> +
> +    if (ret == 0)
> +        ret = qemuMonitorJSONCheckError(cmd, reply);
> +
> +    if (ret < 0)
> +        goto cleanup;
> +
> +    ret = -1;
> +
> +    if (!(data = virJSONValueObjectGet(reply, "return"))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("qom-list reply was missing return data"));
> +        goto cleanup;
> +    }
> +
> +    if ((n = virJSONValueArraySize(data)) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("qom-list reply data was not an array"));
> +        goto cleanup;
> +    }
> +
> +    /* null-terminated list */

Do we need NULL terminated list ... [1]

> +    if (VIR_ALLOC_N(pathlist, n + 1) < 0) {
> +        virReportOOMError();

This can be dropped now. But as you've said in one of previous e-mails
of your, you already did that.

> +        goto cleanup;
> +    }
> +
> +    for (i = 0; i < n; i++) {
> +        virJSONValuePtr child = virJSONValueArrayGet(data, i);
> +        const char *tmp;
> +        qemuMonitorJSONListPathPtr info;
> +
> +        if (VIR_ALLOC(info) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +
> +        pathlist[i] = info;
> +
> +        if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("qom-list reply data was missing 'name'"));
> +            goto cleanup;
> +        }
> +
> +        if (VIR_STRDUP(info->name, tmp) < 0)
> +            goto cleanup;
> +
> +        if (virJSONValueObjectHasKey(child, "type")) {
> +            if (!(tmp = virJSONValueObjectGetString(child, "type"))) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                               _("qom-list reply has malformed 'type' data"));
> +                goto cleanup;
> +            }
> +            if (VIR_STRDUP(info->type, tmp) < 0)
> +                goto cleanup;
> +        }
> +    }
> +
> +    ret = n;

1: ... if we are returning number of items in array? I'm not saying it's
something wrong, just curious.

> +    *paths = pathlist;
> +
> +cleanup:
> +    if (ret < 0 && pathlist) {
> +        for (i = 0; i < n; i++)
> +            qemuMonitorJSONListPathFree(pathlist[i]);
> +        VIR_FREE(pathlist);
> +    }
> +    virJSONValueFree(cmd);
> +    virJSONValueFree(reply);
> +    return ret;
> +}
> +
> +void qemuMonitorJSONListPathFree(qemuMonitorJSONListPathPtr paths)
> +{
> +    if (!paths)
> +        return;
> +    VIR_FREE(paths->name);
> +    VIR_FREE(paths->type);
> +    VIR_FREE(paths);
> +}
> +
>  int qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
>                                    const char *type,
>                                    char ***props)
> diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
> index d79b86b..e7ce145 100644
> --- a/src/qemu/qemu_monitor_json.h
> +++ b/src/qemu/qemu_monitor_json.h
> @@ -332,6 +332,22 @@ int qemuMonitorJSONGetKVMState(qemuMonitorPtr mon,
>  int qemuMonitorJSONGetObjectTypes(qemuMonitorPtr mon,
>                                    char ***types)
>      ATTRIBUTE_NONNULL(2);
> +
> +typedef struct _qemuMonitorJSONListPath qemuMonitorJSONListPath;
> +typedef qemuMonitorJSONListPath *qemuMonitorJSONListPathPtr;
> +
> +struct _qemuMonitorJSONListPath {
> +    char *name;
> +    char *type;
> +};
> +
> +int qemuMonitorJSONGetObjectListPaths(qemuMonitorPtr mon,
> +                                      const char *path,
> +                                      qemuMonitorJSONListPathPtr **paths)
> +    ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
> +
> +void qemuMonitorJSONListPathFree(qemuMonitorJSONListPathPtr paths);
> +
>  int qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
>                                    const char *type,
>                                    char ***props)
> diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
> index acc94ca..380d377 100644
> --- a/tests/qemumonitorjsontest.c
> +++ b/tests/qemumonitorjsontest.c
> @@ -23,6 +23,7 @@
>  #include "testutilsqemu.h"
>  #include "qemumonitortestutils.h"
>  #include "qemu/qemu_conf.h"
> +#include "qemu/qemu_monitor_json.h"
>  #include "virthread.h"
>  #include "virerror.h"
>  #include "virstring.h"
> @@ -595,6 +596,83 @@ cleanup:
>  }
>  
>  
> +/*
> + * This test will request to return a list of paths for "/". It should be
> + * a simple list of 1 real element that being the "machine". The following
> + * is the execution and expected return:
> + *
> + *  {"execute":"qom-list", "arguments": { "path": "/"}}"
> + *  {"return": [{"name": "machine", "type": "child<container>"}, \
> + *              {"name": "type", "type": "string"}]}
> + */
> +static int
> +testQemuMonitorJSONGetListPaths(const void *data)
> +{
> +    const virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
> +    qemuMonitorTestPtr test = qemuMonitorTestNew(true, xmlopt);
> +    int ret = -1;
> +    qemuMonitorJSONListPathPtr *paths;
> +    int npaths = 0;
> +    int i;

And after Daniel's patches, this needs to be size_t i;

> +
> +    if (!test)
> +        return -1;
> +
> +    if (qemuMonitorTestAddItem(test, "qom-list",
> +                               "{ "
> +                               "  \"return\": [ "
> +                               "  {\"name\": \"machine\", "
> +                               "   \"type\": \"child<container>\"}, "
> +                               "  {\"name\": \"type\", "
> +                               "   \"type\": \"string\"} "
> +                               " ]"
> +                               "}") < 0)
> +        goto cleanup;
> +
> +    /* present with path */
> +    if ((npaths = qemuMonitorJSONGetObjectListPaths(
> +                                                qemuMonitorTestGetMonitor(test),
> +                                                "/",
> +                                                &paths)) < 0)
> +        goto cleanup;
> +
> +    if (npaths != 2) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       "npaths was %d, expected 1", npaths);
> +        goto cleanup;
> +    }
> +
> +#define CHECK(i, wantname, wanttype)                                    \
> +    do {                                                                \
> +        if (STRNEQ(paths[i]->name, (wantname))) {                       \
> +            virReportError(VIR_ERR_INTERNAL_ERROR,                      \
> +                           "name was %s, expected %s",                  \
> +                           paths[i]->name, (wantname));                 \
> +            goto cleanup;                                               \
> +        }                                                               \
> +        if (STRNEQ_NULLABLE(paths[i]->type, (wanttype))) {              \
> +            virReportError(VIR_ERR_INTERNAL_ERROR,                      \
> +                           "type was %s, expected %s",                  \
> +                           NULLSTR(paths[i]->type), (wanttype));        \
> +            goto cleanup;                                               \
> +        }                                                               \
> +    } while (0)
> +
> +    CHECK(0, "machine", "child<container>");
> +
> +#undef CHECK
> +
> +    ret = 0;
> +
> +cleanup:
> +    qemuMonitorTestFree(test);
> +    for (i = 0; i < npaths; i++)
> +        qemuMonitorJSONListPathFree(paths[i]);
> +    VIR_FREE(paths);
> +    return ret;
> +}
> +
> +
>  static int
>  mymain(void)
>  {
> @@ -623,6 +701,7 @@ mymain(void)
>      DO_TEST(GetCommands);
>      DO_TEST(GetTPMModels);
>      DO_TEST(GetCommandLineOptionParameters);
> +    DO_TEST(GetListPaths);
>  
>      virObjectUnref(xmlopt);
>  
> 

Michal




More information about the libvir-list mailing list