monitor: add object-add (QMP) and object_add (HMP) command
Add two commands that are the monitor counterparts of -object. The commands have the same Visitor-based implementation, but use different kinds of visitors so that the HMP command has a DWIM string-based syntax, while the QMP variant accepts a stricter JSON-based properties dictionary. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Tested-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
This commit is contained in:
parent
ab2d0531b2
commit
cff8b2c6fc
@ -1241,6 +1241,20 @@ STEXI
|
||||
@item netdev_del
|
||||
@findex netdev_del
|
||||
Remove host network device.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
.name = "object_add",
|
||||
.args_type = "object:O",
|
||||
.params = "[qom-type=]type,id=str[,prop=value][,...]",
|
||||
.help = "create QOM object",
|
||||
.mhandler.cmd = hmp_object_add,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@item object_add
|
||||
@findex object_add
|
||||
Create QOM object.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
|
58
hmp.c
58
hmp.c
@ -21,6 +21,7 @@
|
||||
#include "qmp-commands.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "ui/console.h"
|
||||
#include "block/qapi.h"
|
||||
#include "qemu-io.h"
|
||||
@ -1354,6 +1355,63 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)
|
||||
hmp_handle_error(mon, &err);
|
||||
}
|
||||
|
||||
void hmp_object_add(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *err = NULL;
|
||||
QemuOpts *opts;
|
||||
char *type = NULL;
|
||||
char *id = NULL;
|
||||
void *dummy = NULL;
|
||||
OptsVisitor *ov;
|
||||
QDict *pdict;
|
||||
|
||||
opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ov = opts_visitor_new(opts);
|
||||
pdict = qdict_clone_shallow(qdict);
|
||||
|
||||
visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err);
|
||||
if (err) {
|
||||
goto out_clean;
|
||||
}
|
||||
|
||||
qdict_del(pdict, "qom-type");
|
||||
visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
|
||||
if (err) {
|
||||
goto out_clean;
|
||||
}
|
||||
|
||||
qdict_del(pdict, "id");
|
||||
visit_type_str(opts_get_visitor(ov), &id, "id", &err);
|
||||
if (err) {
|
||||
goto out_clean;
|
||||
}
|
||||
|
||||
object_add(type, id, pdict, opts_get_visitor(ov), &err);
|
||||
if (err) {
|
||||
goto out_clean;
|
||||
}
|
||||
visit_end_struct(opts_get_visitor(ov), &err);
|
||||
if (err) {
|
||||
qmp_object_del(id, NULL);
|
||||
}
|
||||
|
||||
out_clean:
|
||||
opts_visitor_cleanup(ov);
|
||||
|
||||
QDECREF(pdict);
|
||||
qemu_opts_del(opts);
|
||||
g_free(id);
|
||||
g_free(type);
|
||||
g_free(dummy);
|
||||
|
||||
out:
|
||||
hmp_handle_error(mon, &err);
|
||||
}
|
||||
|
||||
void hmp_getfd(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *fdname = qdict_get_str(qdict, "fdname");
|
||||
|
1
hmp.h
1
hmp.h
@ -90,6 +90,7 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
|
||||
void hmp_qemu_io(Monitor *mon, const QDict *qdict);
|
||||
void hmp_cpu_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_object_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_object_del(Monitor *mon, const QDict *qdict);
|
||||
|
||||
#endif
|
||||
|
@ -93,6 +93,9 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
|
||||
int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret);
|
||||
|
||||
int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret);
|
||||
int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret);
|
||||
void object_add(const char *type, const char *id, const QDict *qdict,
|
||||
Visitor *v, Error **errp);
|
||||
|
||||
AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
|
||||
bool has_opaque, const char *opaque,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#ifndef QAPI_VISITOR_CORE_H
|
||||
#define QAPI_VISITOR_CORE_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/error.h"
|
||||
#include <stdlib.h>
|
||||
@ -26,8 +27,6 @@ typedef struct GenericList
|
||||
struct GenericList *next;
|
||||
} GenericList;
|
||||
|
||||
typedef struct Visitor Visitor;
|
||||
|
||||
void visit_start_handle(Visitor *v, void **obj, const char *kind,
|
||||
const char *name, Error **errp);
|
||||
void visit_end_handle(Visitor *v, Error **errp);
|
||||
|
@ -10,6 +10,8 @@ typedef struct QEMUBH QEMUBH;
|
||||
|
||||
typedef struct AioContext AioContext;
|
||||
|
||||
typedef struct Visitor Visitor;
|
||||
|
||||
struct Monitor;
|
||||
typedef struct Monitor Monitor;
|
||||
typedef struct MigrationParams MigrationParams;
|
||||
|
@ -2758,6 +2758,26 @@
|
||||
##
|
||||
{ 'command': 'netdev_del', 'data': {'id': 'str'} }
|
||||
|
||||
##
|
||||
# @object-add:
|
||||
#
|
||||
# Create a QOM object.
|
||||
#
|
||||
# @qom-type: the class name for the object to be created
|
||||
#
|
||||
# @id: the name of the new object
|
||||
#
|
||||
# @props: #optional a dictionary of properties to be passed to the backend
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# Error if @qom-type is not a valid class name
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'command': 'object-add',
|
||||
'data': {'qom-type': 'str', 'id': 'str', '*props': 'dict'},
|
||||
'gen': 'no' }
|
||||
|
||||
##
|
||||
# @object-del:
|
||||
#
|
||||
|
@ -876,6 +876,32 @@ Example:
|
||||
<- { "return": {} }
|
||||
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
.name = "object-add",
|
||||
.args_type = "qom-type:s,id:s,props:q?",
|
||||
.mhandler.cmd_new = qmp_object_add,
|
||||
},
|
||||
|
||||
SQMP
|
||||
object-add
|
||||
----------
|
||||
|
||||
Create QOM object.
|
||||
|
||||
Arguments:
|
||||
|
||||
- "qom-type": the object's QOM type, i.e. the class name (json-string)
|
||||
- "id": the object's ID, must be unique (json-string)
|
||||
- "props": a dictionary of object property values (optional, json-dict)
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "object-add", "arguments": { "qom-type": "rng-random", "id": "rng1",
|
||||
"props": { "filename": "/dev/hwrng" } } }
|
||||
<- { "return": {} }
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
|
62
qmp.c
62
qmp.c
@ -24,6 +24,8 @@
|
||||
#include "hw/qdev.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "qom/qom-qobject.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
NameInfo *qmp_query_name(Error **errp)
|
||||
@ -530,6 +532,66 @@ void qmp_add_client(const char *protocol, const char *fdname,
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void object_add(const char *type, const char *id, const QDict *qdict,
|
||||
Visitor *v, Error **errp)
|
||||
{
|
||||
Object *obj;
|
||||
const QDictEntry *e;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!object_class_by_name(type)) {
|
||||
error_setg(errp, "invalid class name");
|
||||
return;
|
||||
}
|
||||
|
||||
obj = object_new(type);
|
||||
if (qdict) {
|
||||
for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
|
||||
object_property_set(obj, v, e->key, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
object_unref(obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object_property_add_child(container_get(object_get_root(), "/objects"),
|
||||
id, obj, errp);
|
||||
object_unref(obj);
|
||||
}
|
||||
|
||||
int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret)
|
||||
{
|
||||
const char *type = qdict_get_str(qdict, "qom-type");
|
||||
const char *id = qdict_get_str(qdict, "id");
|
||||
QObject *props = qdict_get(qdict, "props");
|
||||
const QDict *pdict = NULL;
|
||||
Error *local_err = NULL;
|
||||
QmpInputVisitor *qiv;
|
||||
|
||||
if (props) {
|
||||
pdict = qobject_to_qdict(props);
|
||||
if (!pdict) {
|
||||
error_set(&local_err, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
qiv = qmp_input_visitor_new(props);
|
||||
object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err);
|
||||
qmp_input_visitor_cleanup(qiv);
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qmp_object_del(const char *id, Error **errp)
|
||||
{
|
||||
Object *container;
|
||||
|
Loading…
Reference in New Issue
Block a user