qemu: caps: Move QAPI schema related code into separate file

Extract the code into qemu_qapi.c/h so that we separate it from various
parts of the code.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Peter Krempa 2018-03-20 08:44:11 +01:00
parent 9be9e26b74
commit 367697c54c
5 changed files with 227 additions and 157 deletions

View File

@ -141,6 +141,7 @@ src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_text.c
src/qemu/qemu_parse_command.c
src/qemu/qemu_process.c
src/qemu/qemu_qapi.c
src/remote/remote_client_bodies.h
src/remote/remote_daemon.c
src/remote/remote_daemon_config.c

View File

@ -46,6 +46,8 @@ QEMU_DRIVER_SOURCES = \
qemu/qemu_capspriv.h \
qemu/qemu_security.c \
qemu/qemu_security.h \
qemu/qemu_qapi.c \
qemu/qemu_qapi.h \
$(NULL)

View File

@ -46,6 +46,7 @@
#include "qemu_domain.h"
#define __QEMU_CAPSPRIV_H_ALLOW__
#include "qemu_capspriv.h"
#include "qemu_qapi.h"
#include <fcntl.h>
#include <sys/stat.h>
@ -4564,163 +4565,6 @@ virQEMUCapsInitQMPBasicArch(virQEMUCapsPtr qemuCaps)
}
/**
* virQEMUCapsQMPSchemaObjectGetType:
* @field: name of the object containing the requested type
* @name: name of the requested type
* @namefield: name of the object property holding @name
*
* Helper that selects the type of a QMP schema object member or it's variant
* member. Returns the type string on success or NULL on error.
*/
static const char *
virQEMUCapsQMPSchemaObjectGetType(const char *field,
const char *name,
const char *namefield,
virJSONValuePtr elem)
{
virJSONValuePtr arr;
virJSONValuePtr cur;
const char *curname;
const char *type;
size_t i;
if (!(arr = virJSONValueObjectGetArray(elem, field)))
return NULL;
for (i = 0; i < virJSONValueArraySize(arr); i++) {
if (!(cur = virJSONValueArrayGet(arr, i)) ||
!(curname = virJSONValueObjectGetString(cur, namefield)) ||
!(type = virJSONValueObjectGetString(cur, "type")))
continue;
if (STREQ(name, curname))
return type;
}
return NULL;
}
static virJSONValuePtr
virQEMUCapsQMPSchemaTraverse(const char *baseName,
char **query,
virHashTablePtr schema)
{
virJSONValuePtr base;
const char *metatype;
do {
if (!(base = virHashLookup(schema, baseName)))
return NULL;
if (!*query)
return base;
if (!(metatype = virJSONValueObjectGetString(base, "meta-type")))
return NULL;
/* flatten arrays by default */
if (STREQ(metatype, "array")) {
if (!(baseName = virJSONValueObjectGetString(base, "element-type")))
return NULL;
continue;
} else if (STREQ(metatype, "object")) {
if (**query == '+')
baseName = virQEMUCapsQMPSchemaObjectGetType("variants",
*query + 1,
"case", base);
else
baseName = virQEMUCapsQMPSchemaObjectGetType("members",
*query,
"name", base);
if (!baseName)
return NULL;
} else if (STREQ(metatype, "command") ||
STREQ(metatype, "event")) {
if (!(baseName = virJSONValueObjectGetString(base, *query)))
return NULL;
} else {
/* alternates, basic types and enums can't be entered */
return NULL;
}
query++;
} while (*query);
return base;
}
/**
* virQEMUCapsQMPSchemaGetByPath:
* @query: string specifying the required data type (see below)
* @schema: hash table containing the schema data
* @entry: filled with the located schema object requested by @query
*
* Retrieves the requested schema entry specified by @query to @entry. The
* @query parameter has the following syntax which is very closely tied to the
* qemu schema syntax entries separated by slashes with a few special characters:
*
* "command_or_event/attribute/subattribute/+variant_discriminator/subattribute"
*
* command_or_event: name of the event or attribute to introspect
* attribute: selects whether arguments or return type should be introspected
* ("arg-type" or "ret-type" for commands, "arg-type" for events)
* subattribute: specifies member name of object types
* +variant_discriminator: In the case of unionized objects, select a
* specific case to introspect.
*
* Array types are automatically flattened to the singular type. Alternate
* types are currently not supported.
*
* The above types can be chained arbitrarily using slashes to construct any
* path into the schema tree.
*
* Returns 0 on success (including if the requested schema was not found) and
* fills @entry appropriately. On failure returns -1 and sets an appropriate
* error message.
*/
static int
virQEMUCapsQMPSchemaGetByPath(const char *query,
virHashTablePtr schema,
virJSONValuePtr *entry)
{
char **elems = NULL;
*entry = NULL;
if (!(elems = virStringSplit(query, "/", 0)))
return -1;
if (!*elems) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed query string"));
virStringListFree(elems);
return -1;
}
*entry = virQEMUCapsQMPSchemaTraverse(*elems, elems + 1, schema);
virStringListFree(elems);
return 0;
}
static bool
virQEMUCapsQMPSchemaQueryPath(const char *query,
virHashTablePtr schema)
{
virJSONValuePtr entry;
if (virQEMUCapsQMPSchemaGetByPath(query, schema, &entry))
return false;
return !!entry;
}
static int
virQEMUCapsProbeQMPSchemaCapabilities(virQEMUCapsPtr qemuCaps,
qemuMonitorPtr mon)

187
src/qemu/qemu_qapi.c Normal file
View File

@ -0,0 +1,187 @@
/*
* qemu_qapi.c: helper functions for QEMU QAPI schema handling
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "qemu_qapi.h"
#include "viralloc.h"
#include "virstring.h"
#include "virerror.h"
#include "virlog.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
VIR_LOG_INIT("qemu.qemu_qapi");
/**
* virQEMUCapsQMPSchemaObjectGetType:
* @field: name of the object containing the requested type
* @name: name of the requested type
* @namefield: name of the object property holding @name
*
* Helper that selects the type of a QMP schema object member or it's variant
* member. Returns the type string on success or NULL on error.
*/
static const char *
virQEMUCapsQMPSchemaObjectGetType(const char *field,
const char *name,
const char *namefield,
virJSONValuePtr elem)
{
virJSONValuePtr arr;
virJSONValuePtr cur;
const char *curname;
const char *type;
size_t i;
if (!(arr = virJSONValueObjectGetArray(elem, field)))
return NULL;
for (i = 0; i < virJSONValueArraySize(arr); i++) {
if (!(cur = virJSONValueArrayGet(arr, i)) ||
!(curname = virJSONValueObjectGetString(cur, namefield)) ||
!(type = virJSONValueObjectGetString(cur, "type")))
continue;
if (STREQ(name, curname))
return type;
}
return NULL;
}
static virJSONValuePtr
virQEMUCapsQMPSchemaTraverse(const char *baseName,
char **query,
virHashTablePtr schema)
{
virJSONValuePtr base;
const char *metatype;
do {
if (!(base = virHashLookup(schema, baseName)))
return NULL;
if (!*query)
return base;
if (!(metatype = virJSONValueObjectGetString(base, "meta-type")))
return NULL;
/* flatten arrays by default */
if (STREQ(metatype, "array")) {
if (!(baseName = virJSONValueObjectGetString(base, "element-type")))
return NULL;
continue;
} else if (STREQ(metatype, "object")) {
if (**query == '+')
baseName = virQEMUCapsQMPSchemaObjectGetType("variants",
*query + 1,
"case", base);
else
baseName = virQEMUCapsQMPSchemaObjectGetType("members",
*query,
"name", base);
if (!baseName)
return NULL;
} else if (STREQ(metatype, "command") ||
STREQ(metatype, "event")) {
if (!(baseName = virJSONValueObjectGetString(base, *query)))
return NULL;
} else {
/* alternates, basic types and enums can't be entered */
return NULL;
}
query++;
} while (*query);
return base;
}
/**
* virQEMUCapsQMPSchemaGetByPath:
* @query: string specifying the required data type (see below)
* @schema: hash table containing the schema data
* @entry: filled with the located schema object requested by @query
*
* Retrieves the requested schema entry specified by @query to @entry. The
* @query parameter has the following syntax which is very closely tied to the
* qemu schema syntax entries separated by slashes with a few special characters:
*
* "command_or_event/attribute/subattribute/+variant_discriminator/subattribute"
*
* command_or_event: name of the event or attribute to introspect
* attribute: selects whether arguments or return type should be introspected
* ("arg-type" or "ret-type" for commands, "arg-type" for events)
* subattribute: specifies member name of object types
* +variant_discriminator: In the case of unionized objects, select a
* specific case to introspect.
*
* Array types are automatically flattened to the singular type. Alternate
* types are currently not supported.
*
* The above types can be chained arbitrarily using slashes to construct any
* path into the schema tree.
*
* Returns 0 on success (including if the requested schema was not found) and
* fills @entry appropriately. On failure returns -1 and sets an appropriate
* error message.
*/
int
virQEMUCapsQMPSchemaGetByPath(const char *query,
virHashTablePtr schema,
virJSONValuePtr *entry)
{
char **elems = NULL;
*entry = NULL;
if (!(elems = virStringSplit(query, "/", 0)))
return -1;
if (!*elems) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed query string"));
virStringListFree(elems);
return -1;
}
*entry = virQEMUCapsQMPSchemaTraverse(*elems, elems + 1, schema);
virStringListFree(elems);
return 0;
}
bool
virQEMUCapsQMPSchemaQueryPath(const char *query,
virHashTablePtr schema)
{
virJSONValuePtr entry;
if (virQEMUCapsQMPSchemaGetByPath(query, schema, &entry))
return false;
return !!entry;
}

36
src/qemu/qemu_qapi.h Normal file
View File

@ -0,0 +1,36 @@
/*
* qemu_qapi.h: helper functions for QEMU QAPI schema
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __QEMU_QAPI_H__
# define __QEMU_QAPI_H__
# include "internal.h"
# include "virhash.h"
# include "virjson.h"
int
virQEMUCapsQMPSchemaGetByPath(const char *query,
virHashTablePtr schema,
virJSONValuePtr *entry);
bool
virQEMUCapsQMPSchemaQueryPath(const char *query,
virHashTablePtr schema);
#endif /* __QEMU_QAPI_H__ */