qapi: add support for command options
Options allow for changes in commands behavior. This commit introduces the QCO_NO_SUCCESS_RESP option, which causes a command to not emit a success response. This is needed by commands such as qemu-ga's guest-shutdown, which may not be able to complete before the VM vanishes. In this case, it's useful and simpler not to bother sending a success response. Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com> Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
This commit is contained in:
parent
76ee152a86
commit
d34b867d81
@ -25,16 +25,24 @@ typedef enum QmpCommandType
|
|||||||
QCT_NORMAL,
|
QCT_NORMAL,
|
||||||
} QmpCommandType;
|
} QmpCommandType;
|
||||||
|
|
||||||
|
typedef enum QmpCommandOptions
|
||||||
|
{
|
||||||
|
QCO_NO_OPTIONS = 0x0,
|
||||||
|
QCO_NO_SUCCESS_RESP = 0x1,
|
||||||
|
} QmpCommandOptions;
|
||||||
|
|
||||||
typedef struct QmpCommand
|
typedef struct QmpCommand
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
QmpCommandType type;
|
QmpCommandType type;
|
||||||
QmpCommandFunc *fn;
|
QmpCommandFunc *fn;
|
||||||
|
QmpCommandOptions options;
|
||||||
QTAILQ_ENTRY(QmpCommand) node;
|
QTAILQ_ENTRY(QmpCommand) node;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
} QmpCommand;
|
} QmpCommand;
|
||||||
|
|
||||||
void qmp_register_command(const char *name, QmpCommandFunc *fn);
|
void qmp_register_command(const char *name, QmpCommandFunc *fn,
|
||||||
|
QmpCommandOptions options);
|
||||||
QmpCommand *qmp_find_command(const char *name);
|
QmpCommand *qmp_find_command(const char *name);
|
||||||
QObject *qmp_dispatch(QObject *request);
|
QObject *qmp_dispatch(QObject *request);
|
||||||
void qmp_disable_command(const char *name);
|
void qmp_disable_command(const char *name);
|
||||||
|
@ -94,8 +94,12 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
|
|||||||
switch (cmd->type) {
|
switch (cmd->type) {
|
||||||
case QCT_NORMAL:
|
case QCT_NORMAL:
|
||||||
cmd->fn(args, &ret, errp);
|
cmd->fn(args, &ret, errp);
|
||||||
if (!error_is_set(errp) && ret == NULL) {
|
if (!error_is_set(errp)) {
|
||||||
ret = QOBJECT(qdict_new());
|
if (cmd->options & QCO_NO_SUCCESS_RESP) {
|
||||||
|
g_assert(!ret);
|
||||||
|
} else if (!ret) {
|
||||||
|
ret = QOBJECT(qdict_new());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
|
static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
|
||||||
QTAILQ_HEAD_INITIALIZER(qmp_commands);
|
QTAILQ_HEAD_INITIALIZER(qmp_commands);
|
||||||
|
|
||||||
void qmp_register_command(const char *name, QmpCommandFunc *fn)
|
void qmp_register_command(const char *name, QmpCommandFunc *fn,
|
||||||
|
QmpCommandOptions options)
|
||||||
{
|
{
|
||||||
QmpCommand *cmd = g_malloc0(sizeof(*cmd));
|
QmpCommand *cmd = g_malloc0(sizeof(*cmd));
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn)
|
|||||||
cmd->type = QCT_NORMAL;
|
cmd->type = QCT_NORMAL;
|
||||||
cmd->fn = fn;
|
cmd->fn = fn;
|
||||||
cmd->enabled = true;
|
cmd->enabled = true;
|
||||||
|
cmd->options = options;
|
||||||
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
|
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,14 +291,24 @@ out:
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def option_value_matches(opt, val, cmd):
|
||||||
|
if opt in cmd and cmd[opt] == val:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def gen_registry(commands):
|
def gen_registry(commands):
|
||||||
registry=""
|
registry=""
|
||||||
push_indent()
|
push_indent()
|
||||||
for cmd in commands:
|
for cmd in commands:
|
||||||
|
options = 'QCO_NO_OPTIONS'
|
||||||
|
if option_value_matches('success-response', 'no', cmd):
|
||||||
|
options = 'QCO_NO_SUCCESS_RESP'
|
||||||
|
|
||||||
registry += mcgen('''
|
registry += mcgen('''
|
||||||
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
|
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
|
||||||
''',
|
''',
|
||||||
name=cmd['command'], c_name=c_fun(cmd['command']))
|
name=cmd['command'], c_name=c_fun(cmd['command']),
|
||||||
|
opts=options)
|
||||||
pop_indent()
|
pop_indent()
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
static void qmp_init_marshal(void)
|
static void qmp_init_marshal(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user