mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/ehabkost/tags/numa-next-pull-request' into staging
NUMA queue, 2018-05-30 * New command-line option: --preconfig This option allows pausing QEMU and allow the configuration using QMP commands before running board initialization code. * New QMP set-numa-node, now made possible because of --preconfig * Small update on -numa error messages # gpg: Signature made Thu 31 May 2018 00:02:59 BST # gpg: using RSA key 2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/numa-next-pull-request: tests: functional tests for QMP command set-numa-node qmp: add set-numa-node command qmp: permit query-hotpluggable-cpus in preconfig state tests: extend qmp test with preconfig checks cli: add --preconfig option tests: qapi-schema tests for allow-preconfig qapi: introduce new cmd option "allow-preconfig" hmp: disable monitor in preconfig state qapi: introduce preconfig runstate numa: split out NumaOptions parsing into set_numa_options() numa: postpone options post-processing till machine_run_board_init() numa: clarify error message when node index is out of range in -numa dist, ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -559,7 +559,7 @@ following example objects:
|
||||
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
|
||||
'*returns': TYPE-NAME, '*boxed': true,
|
||||
'*gen': false, '*success-response': false,
|
||||
'*allow-oob': true }
|
||||
'*allow-oob': true, '*allow-preconfig': true }
|
||||
|
||||
Commands are defined by using a dictionary containing several members,
|
||||
where three members are most common. The 'command' member is a
|
||||
@@ -683,6 +683,15 @@ OOB command handlers must satisfy the following conditions:
|
||||
|
||||
If in doubt, do not implement OOB execution support.
|
||||
|
||||
A command may use the optional 'allow-preconfig' key to permit its execution
|
||||
at early runtime configuration stage (preconfig runstate).
|
||||
If not specified then a command defaults to 'allow-preconfig': false.
|
||||
|
||||
An example of declaring a command that is enabled during preconfig:
|
||||
{ 'command': 'qmp_capabilities',
|
||||
'data': { '*enable': [ 'QMPCapability' ] },
|
||||
'allow-preconfig': true }
|
||||
|
||||
=== Events ===
|
||||
|
||||
Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
|
||||
|
||||
+3
-2
@@ -737,7 +737,7 @@ static char *cpu_slot_to_string(const CPUArchId *cpu)
|
||||
return g_string_free(s, false);
|
||||
}
|
||||
|
||||
static void machine_numa_finish_init(MachineState *machine)
|
||||
static void machine_numa_finish_cpu_init(MachineState *machine)
|
||||
{
|
||||
int i;
|
||||
bool default_mapping;
|
||||
@@ -792,7 +792,8 @@ void machine_run_board_init(MachineState *machine)
|
||||
MachineClass *machine_class = MACHINE_GET_CLASS(machine);
|
||||
|
||||
if (nb_numa_nodes) {
|
||||
machine_numa_finish_init(machine);
|
||||
numa_complete_configuration(machine);
|
||||
machine_numa_finish_cpu_init(machine);
|
||||
}
|
||||
|
||||
/* If the machine supports the valid_cpu_types check and the user
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef enum QmpCommandOptions
|
||||
QCO_NO_OPTIONS = 0x0,
|
||||
QCO_NO_SUCCESS_RESP = (1U << 0),
|
||||
QCO_ALLOW_OOB = (1U << 1),
|
||||
QCO_ALLOW_PRECONFIG = (1U << 2),
|
||||
} QmpCommandOptions;
|
||||
|
||||
typedef struct QmpCommand
|
||||
|
||||
@@ -22,7 +22,9 @@ struct NumaNodeMem {
|
||||
};
|
||||
|
||||
extern NodeInfo numa_info[MAX_NODES];
|
||||
int parse_numa(void *opaque, QemuOpts *opts, Error **errp);
|
||||
void parse_numa_opts(MachineState *ms);
|
||||
void numa_complete_configuration(MachineState *ms);
|
||||
void query_numa_node_mem(NumaNodeMem node_mem[]);
|
||||
extern QemuOptsList qemu_numa_opts;
|
||||
void numa_legacy_auto_assign_ram(MachineClass *mc, NodeInfo *nodes,
|
||||
|
||||
@@ -66,6 +66,7 @@ typedef enum WakeupReason {
|
||||
QEMU_WAKEUP_REASON_OTHER,
|
||||
} WakeupReason;
|
||||
|
||||
void qemu_exit_preconfig_request(void);
|
||||
void qemu_system_reset_request(ShutdownCause reason);
|
||||
void qemu_system_suspend_request(void);
|
||||
void qemu_register_suspend_notifier(Notifier *notifier);
|
||||
|
||||
@@ -1179,8 +1179,7 @@ static void monitor_init_qmp_commands(void)
|
||||
qmp_init_marshal(&qmp_commands);
|
||||
|
||||
qmp_register_command(&qmp_commands, "query-qmp-schema",
|
||||
qmp_query_qmp_schema,
|
||||
QCO_NO_OPTIONS);
|
||||
qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG);
|
||||
qmp_register_command(&qmp_commands, "device_add", qmp_device_add,
|
||||
QCO_NO_OPTIONS);
|
||||
qmp_register_command(&qmp_commands, "netdev_add", qmp_netdev_add,
|
||||
@@ -1190,7 +1189,7 @@ static void monitor_init_qmp_commands(void)
|
||||
|
||||
QTAILQ_INIT(&qmp_cap_negotiation_commands);
|
||||
qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
|
||||
qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS);
|
||||
qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
|
||||
}
|
||||
|
||||
static bool qmp_cap_enabled(Monitor *mon, QMPCapability cap)
|
||||
@@ -3371,6 +3370,12 @@ static void handle_hmp_command(Monitor *mon, const char *cmdline)
|
||||
|
||||
trace_handle_hmp_command(mon, cmdline);
|
||||
|
||||
if (runstate_check(RUN_STATE_PRECONFIG)) {
|
||||
monitor_printf(mon, "HMP not available in preconfig state, "
|
||||
"use QMP instead\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cmd = monitor_parse_command(mon, cmdline, &cmdline, mon->cmd_table);
|
||||
if (!cmd) {
|
||||
return;
|
||||
|
||||
@@ -141,9 +141,8 @@ static void parse_numa_distance(NumaDistOptions *dist, Error **errp)
|
||||
uint8_t val = dist->val;
|
||||
|
||||
if (src >= MAX_NODES || dst >= MAX_NODES) {
|
||||
error_setg(errp,
|
||||
"Invalid node %d, max possible could be %d",
|
||||
MAX(src, dst), MAX_NODES);
|
||||
error_setg(errp, "Parameter '%s' expects an integer between 0 and %d",
|
||||
src >= MAX_NODES ? "src" : "dst", MAX_NODES - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,28 +169,11 @@ static void parse_numa_distance(NumaDistOptions *dist, Error **errp)
|
||||
have_numa_distance = true;
|
||||
}
|
||||
|
||||
static int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
|
||||
static
|
||||
void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp)
|
||||
{
|
||||
NumaOptions *object = NULL;
|
||||
MachineState *ms = opaque;
|
||||
Error *err = NULL;
|
||||
|
||||
{
|
||||
Visitor *v = opts_visitor_new(opts);
|
||||
visit_type_NumaOptions(v, NULL, &object, &err);
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Fix up legacy suffix-less format */
|
||||
if ((object->type == NUMA_OPTIONS_TYPE_NODE) && object->u.node.has_mem) {
|
||||
const char *mem_str = qemu_opt_get(opts, "mem");
|
||||
qemu_strtosz_MiB(mem_str, NULL, &object->u.node.mem);
|
||||
}
|
||||
|
||||
switch (object->type) {
|
||||
case NUMA_OPTIONS_TYPE_NODE:
|
||||
parse_numa_node(ms, &object->u.node, &err);
|
||||
@@ -224,6 +206,31 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
|
||||
abort();
|
||||
}
|
||||
|
||||
end:
|
||||
error_propagate(errp, err);
|
||||
}
|
||||
|
||||
int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
NumaOptions *object = NULL;
|
||||
MachineState *ms = MACHINE(opaque);
|
||||
Error *err = NULL;
|
||||
Visitor *v = opts_visitor_new(opts);
|
||||
|
||||
visit_type_NumaOptions(v, NULL, &object, &err);
|
||||
visit_free(v);
|
||||
if (err) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Fix up legacy suffix-less format */
|
||||
if ((object->type == NUMA_OPTIONS_TYPE_NODE) && object->u.node.has_mem) {
|
||||
const char *mem_str = qemu_opt_get(opts, "mem");
|
||||
qemu_strtosz_MiB(mem_str, NULL, &object->u.node.mem);
|
||||
}
|
||||
|
||||
set_numa_options(ms, object, &err);
|
||||
|
||||
end:
|
||||
qapi_free_NumaOptions(object);
|
||||
if (err) {
|
||||
@@ -339,15 +346,11 @@ void numa_default_auto_assign_ram(MachineClass *mc, NodeInfo *nodes,
|
||||
nodes[i].node_mem = size - usedmem;
|
||||
}
|
||||
|
||||
void parse_numa_opts(MachineState *ms)
|
||||
void numa_complete_configuration(MachineState *ms)
|
||||
{
|
||||
int i;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
|
||||
if (qemu_opts_foreach(qemu_find_opts("numa"), parse_numa, ms, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If memory hotplug is enabled (slots > 0) but without '-numa'
|
||||
* options explicitly on CLI, guestes will break.
|
||||
@@ -434,6 +437,24 @@ void parse_numa_opts(MachineState *ms)
|
||||
}
|
||||
}
|
||||
|
||||
void parse_numa_opts(MachineState *ms)
|
||||
{
|
||||
if (qemu_opts_foreach(qemu_find_opts("numa"), parse_numa, ms, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
|
||||
{
|
||||
if (!runstate_check(RUN_STATE_PRECONFIG)) {
|
||||
error_setg(errp, "The command is permitted only in '%s' state",
|
||||
RunState_str(RUN_STATE_PRECONFIG));
|
||||
return;
|
||||
}
|
||||
|
||||
set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
|
||||
}
|
||||
|
||||
void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp)
|
||||
{
|
||||
int node_id = object_property_get_int(OBJECT(dev), "node-id", &error_abort);
|
||||
|
||||
@@ -262,13 +262,16 @@
|
||||
# @allow-oob: whether the command allows out-of-band execution.
|
||||
# (Since: 2.12)
|
||||
#
|
||||
# @allow-preconfig: command can be executed in preconfig runstate,
|
||||
# default: false (Since 3.0)
|
||||
#
|
||||
# TODO: @success-response (currently irrelevant, because it's QGA, not QMP)
|
||||
#
|
||||
# Since: 2.5
|
||||
##
|
||||
{ 'struct': 'SchemaInfoCommand',
|
||||
'data': { 'arg-type': 'str', 'ret-type': 'str',
|
||||
'allow-oob': 'bool' } }
|
||||
'allow-oob': 'bool', 'allow-preconfig': 'bool' } }
|
||||
|
||||
##
|
||||
# @SchemaInfoEvent:
|
||||
|
||||
+45
-4
@@ -37,7 +37,8 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'qmp_capabilities',
|
||||
'data': { '*enable': [ 'QMPCapability' ] } }
|
||||
'data': { '*enable': [ 'QMPCapability' ] },
|
||||
'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @QMPCapability:
|
||||
@@ -155,7 +156,8 @@
|
||||
# Note: This example has been shortened as the real response is too long.
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-commands', 'returns': ['CommandInfo'] }
|
||||
{ 'command': 'query-commands', 'returns': ['CommandInfo'],
|
||||
'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @LostTickPolicy:
|
||||
@@ -1242,6 +1244,29 @@
|
||||
##
|
||||
{ 'command': 'cont' }
|
||||
|
||||
##
|
||||
# @exit-preconfig:
|
||||
#
|
||||
# Exit from "preconfig" state
|
||||
#
|
||||
# This command makes QEMU exit the preconfig state and proceed with
|
||||
# VM initialization using configuration data provided on the command line
|
||||
# and via the QMP monitor during the preconfig state. The command is only
|
||||
# available during the preconfig state (i.e. when the --preconfig command
|
||||
# line option was in use).
|
||||
#
|
||||
# Since 3.0
|
||||
#
|
||||
# Returns: nothing
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "exit-preconfig" }
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'exit-preconfig', 'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @system_wakeup:
|
||||
#
|
||||
@@ -2648,7 +2673,8 @@
|
||||
#
|
||||
##
|
||||
{'command': 'query-command-line-options', 'data': { '*option': 'str' },
|
||||
'returns': ['CommandLineOptionInfo'] }
|
||||
'returns': ['CommandLineOptionInfo'],
|
||||
'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @X86CPURegister32:
|
||||
@@ -3259,7 +3285,8 @@
|
||||
# ]}
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'] }
|
||||
{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'],
|
||||
'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @GuidInfo:
|
||||
@@ -3483,3 +3510,17 @@
|
||||
##
|
||||
{ 'command': 'x-oob-test', 'data' : { 'lock': 'bool' },
|
||||
'allow-oob': true }
|
||||
|
||||
##
|
||||
# @set-numa-node:
|
||||
#
|
||||
# Runtime equivalent of '-numa' CLI option, available at
|
||||
# preconfigure stage to configure numa mapping before initializing
|
||||
# machine.
|
||||
#
|
||||
# Since 3.0
|
||||
##
|
||||
{ 'command': 'set-numa-node', 'boxed': true,
|
||||
'data': 'NumaOptions',
|
||||
'allow-preconfig': true
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
|
||||
{
|
||||
@@ -101,6 +102,13 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (runstate_check(RUN_STATE_PRECONFIG) &&
|
||||
!(cmd->options & QCO_ALLOW_PRECONFIG)) {
|
||||
error_setg(errp, "The command '%s' isn't permitted in '%s' state",
|
||||
cmd->name, RunState_str(RUN_STATE_PRECONFIG));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!qdict_haskey(dict, "arguments")) {
|
||||
args = qdict_new();
|
||||
} else {
|
||||
|
||||
+6
-2
@@ -49,12 +49,15 @@
|
||||
# @colo: guest is paused to save/restore VM state under colo checkpoint,
|
||||
# VM can not get into this state unless colo capability is enabled
|
||||
# for migration. (since 2.8)
|
||||
# @preconfig: QEMU is paused before board specific init callback is executed.
|
||||
# The state is reachable only if the --preconfig CLI option is used.
|
||||
# (Since 3.0)
|
||||
##
|
||||
{ 'enum': 'RunState',
|
||||
'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
|
||||
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
|
||||
'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
|
||||
'guest-panicked', 'colo' ] }
|
||||
'guest-panicked', 'colo', 'preconfig' ] }
|
||||
|
||||
##
|
||||
# @StatusInfo:
|
||||
@@ -91,7 +94,8 @@
|
||||
# "status": "running" } }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-status', 'returns': 'StatusInfo' }
|
||||
{ 'command': 'query-status', 'returns': 'StatusInfo',
|
||||
'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @SHUTDOWN:
|
||||
|
||||
@@ -3299,6 +3299,19 @@ STEXI
|
||||
Run the emulation in single step mode.
|
||||
ETEXI
|
||||
|
||||
DEF("preconfig", 0, QEMU_OPTION_preconfig, \
|
||||
"--preconfig pause QEMU before machine is initialized\n",
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item --preconfig
|
||||
@findex --preconfig
|
||||
Pause QEMU for interactive configuration before the machine is created,
|
||||
which allows querying and configuring properties that will affect
|
||||
machine initialization. Use the QMP command 'exit-preconfig' to exit
|
||||
the preconfig state and move to the next state (ie. run guest if -S
|
||||
isn't used or pause the second time if -S is used).
|
||||
ETEXI
|
||||
|
||||
DEF("S", 0, QEMU_OPTION_S, \
|
||||
"-S freeze CPU at startup (use 'c' to start execution)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* CPU emulation::
|
||||
* Translator Internals::
|
||||
* QEMU compared to other emulators::
|
||||
* Managed start up options::
|
||||
* Bibliography::
|
||||
@end menu
|
||||
|
||||
@@ -314,6 +315,45 @@ VirtualBox [9], Xen [10] and KVM [11] are based on QEMU. QEMU-SystemC
|
||||
[12] uses QEMU to simulate a system where some hardware devices are
|
||||
developed in SystemC.
|
||||
|
||||
@node Managed start up options
|
||||
@section Managed start up options
|
||||
|
||||
In system mode emulation, it's possible to create a VM in a paused state using
|
||||
the -S command line option. In this state the machine is completely initialized
|
||||
according to command line options and ready to execute VM code but VCPU threads
|
||||
are not executing any code. The VM state in this paused state depends on the way
|
||||
QEMU was started. It could be in:
|
||||
@table @asis
|
||||
@item initial state (after reset/power on state)
|
||||
@item with direct kernel loading, the initial state could be amended to execute
|
||||
code loaded by QEMU in the VM's RAM and with incoming migration
|
||||
@item with incoming migration, initial state will by amended with the migrated
|
||||
machine state after migration completes.
|
||||
@end table
|
||||
|
||||
This paused state is typically used by users to query machine state and/or
|
||||
additionally configure the machine (by hotplugging devices) in runtime before
|
||||
allowing VM code to run.
|
||||
|
||||
However, at the -S pause point, it's impossible to configure options that affect
|
||||
initial VM creation (like: -smp/-m/-numa ...) or cold plug devices. That's
|
||||
when the --preconfig command line option should be used. It allows pausing QEMU
|
||||
before the initial VM creation, in a new preconfig state, where additional
|
||||
queries and configuration can be performed via QMP before moving on to
|
||||
the resulting configuration startup. In the preconfig state, QEMU only allows
|
||||
a limited set of commands over the QMP monitor, where the commands do not
|
||||
depend on an initialized machine, including but not limited to:
|
||||
@table @asis
|
||||
@item qmp_capabilities
|
||||
@item query-qmp-schema
|
||||
@item query-commands
|
||||
@item query-status
|
||||
@item exit-preconfig
|
||||
@end table
|
||||
The full list of commands is in QMP schema which could be queried with
|
||||
query-qmp-schema, where commands supported at preconfig state have option
|
||||
'allow-preconfig' set to true.
|
||||
|
||||
@node Bibliography
|
||||
@section Bibliography
|
||||
|
||||
|
||||
@@ -161,6 +161,16 @@ SpiceInfo *qmp_query_spice(Error **errp)
|
||||
};
|
||||
#endif
|
||||
|
||||
void qmp_exit_preconfig(Error **errp)
|
||||
{
|
||||
if (!runstate_check(RUN_STATE_PRECONFIG)) {
|
||||
error_setg(errp, "The command is permitted only in '%s' state",
|
||||
RunState_str(RUN_STATE_PRECONFIG));
|
||||
return;
|
||||
}
|
||||
qemu_exit_preconfig_request();
|
||||
}
|
||||
|
||||
void qmp_cont(Error **errp)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
|
||||
@@ -193,13 +193,15 @@ out:
|
||||
return ret
|
||||
|
||||
|
||||
def gen_register_command(name, success_response, allow_oob):
|
||||
def gen_register_command(name, success_response, allow_oob, allow_preconfig):
|
||||
options = []
|
||||
|
||||
if not success_response:
|
||||
options += ['QCO_NO_SUCCESS_RESP']
|
||||
if allow_oob:
|
||||
options += ['QCO_ALLOW_OOB']
|
||||
if allow_preconfig:
|
||||
options += ['QCO_ALLOW_PRECONFIG']
|
||||
|
||||
if not options:
|
||||
options = ['QCO_NO_OPTIONS']
|
||||
@@ -275,8 +277,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
|
||||
c_prefix=c_name(self._prefix, protect=False)))
|
||||
genc.add(gen_registry(self._regy, self._prefix))
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response, boxed, allow_oob):
|
||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
if not gen:
|
||||
return
|
||||
self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
|
||||
@@ -285,7 +287,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
|
||||
self._genc.add(gen_marshal_output(ret_type))
|
||||
self._genh.add(gen_marshal_decl(name))
|
||||
self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
|
||||
self._regy += gen_register_command(name, success_response, allow_oob)
|
||||
self._regy += gen_register_command(name, success_response, allow_oob,
|
||||
allow_preconfig)
|
||||
|
||||
|
||||
def gen_commands(schema, output_dir, prefix):
|
||||
|
||||
+11
-7
@@ -872,7 +872,8 @@ def check_keys(expr_elem, meta, required, optional=[]):
|
||||
raise QAPISemError(info,
|
||||
"'%s' of %s '%s' should only use false value"
|
||||
% (key, meta, name))
|
||||
if (key == 'boxed' or key == 'allow-oob') and value is not True:
|
||||
if (key == 'boxed' or key == 'allow-oob' or
|
||||
key == 'allow-preconfig') and value is not True:
|
||||
raise QAPISemError(info,
|
||||
"'%s' of %s '%s' should only use true value"
|
||||
% (key, meta, name))
|
||||
@@ -922,7 +923,7 @@ def check_exprs(exprs):
|
||||
meta = 'command'
|
||||
check_keys(expr_elem, 'command', [],
|
||||
['data', 'returns', 'gen', 'success-response',
|
||||
'boxed', 'allow-oob'])
|
||||
'boxed', 'allow-oob', 'allow-preconfig'])
|
||||
elif 'event' in expr:
|
||||
meta = 'event'
|
||||
check_keys(expr_elem, 'event', [], ['data', 'boxed'])
|
||||
@@ -1044,8 +1045,8 @@ class QAPISchemaVisitor(object):
|
||||
def visit_alternate_type(self, name, info, variants):
|
||||
pass
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response, boxed, allow_oob):
|
||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
pass
|
||||
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
@@ -1422,7 +1423,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
||||
|
||||
class QAPISchemaCommand(QAPISchemaEntity):
|
||||
def __init__(self, name, info, doc, arg_type, ret_type,
|
||||
gen, success_response, boxed, allow_oob):
|
||||
gen, success_response, boxed, allow_oob, allow_preconfig):
|
||||
QAPISchemaEntity.__init__(self, name, info, doc)
|
||||
assert not arg_type or isinstance(arg_type, str)
|
||||
assert not ret_type or isinstance(ret_type, str)
|
||||
@@ -1434,6 +1435,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
||||
self.success_response = success_response
|
||||
self.boxed = boxed
|
||||
self.allow_oob = allow_oob
|
||||
self.allow_preconfig = allow_preconfig
|
||||
|
||||
def check(self, schema):
|
||||
if self._arg_type_name:
|
||||
@@ -1458,7 +1460,8 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
||||
visitor.visit_command(self.name, self.info,
|
||||
self.arg_type, self.ret_type,
|
||||
self.gen, self.success_response,
|
||||
self.boxed, self.allow_oob)
|
||||
self.boxed, self.allow_oob,
|
||||
self.allow_preconfig)
|
||||
|
||||
|
||||
class QAPISchemaEvent(QAPISchemaEntity):
|
||||
@@ -1678,6 +1681,7 @@ class QAPISchema(object):
|
||||
success_response = expr.get('success-response', True)
|
||||
boxed = expr.get('boxed', False)
|
||||
allow_oob = expr.get('allow-oob', False)
|
||||
allow_preconfig = expr.get('allow-preconfig', False)
|
||||
if isinstance(data, OrderedDict):
|
||||
data = self._make_implicit_object_type(
|
||||
name, info, doc, 'arg', self._make_members(data, info))
|
||||
@@ -1686,7 +1690,7 @@ class QAPISchema(object):
|
||||
rets = self._make_array_type(rets[0], info)
|
||||
self._def_entity(QAPISchemaCommand(name, info, doc, data, rets,
|
||||
gen, success_response,
|
||||
boxed, allow_oob))
|
||||
boxed, allow_oob, allow_preconfig))
|
||||
|
||||
def _def_event(self, expr, info, doc):
|
||||
name = expr['event']
|
||||
|
||||
+2
-2
@@ -226,8 +226,8 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
||||
name=doc.symbol,
|
||||
body=texi_entity(doc, 'Members')))
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response, boxed, allow_oob):
|
||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
doc = self.cur_doc
|
||||
if boxed:
|
||||
body = texi_body(doc)
|
||||
|
||||
@@ -171,14 +171,15 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
{'members': [{'type': self._use_type(m.type)}
|
||||
for m in variants.variants]})
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response, boxed, allow_oob):
|
||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
arg_type = arg_type or self._schema.the_empty_object_type
|
||||
ret_type = ret_type or self._schema.the_empty_object_type
|
||||
self._gen_qlit(name, 'command',
|
||||
{'arg-type': self._use_type(arg_type),
|
||||
'ret-type': self._use_type(ret_type),
|
||||
'allow-oob': allow_oob})
|
||||
'allow-oob': allow_oob,
|
||||
'allow-preconfig': allow_preconfig})
|
||||
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
arg_type = arg_type or self._schema.the_empty_object_type
|
||||
|
||||
@@ -525,6 +525,7 @@ qapi-schema += missing-type.json
|
||||
qapi-schema += nested-struct-data.json
|
||||
qapi-schema += non-objects.json
|
||||
qapi-schema += oob-test.json
|
||||
qapi-schema += allow-preconfig-test.json
|
||||
qapi-schema += pragma-doc-required-crap.json
|
||||
qapi-schema += pragma-extra-junk.json
|
||||
qapi-schema += pragma-name-case-whitelist-crap.json
|
||||
|
||||
@@ -1098,3 +1098,10 @@ void qtest_qmp_device_del(const char *id)
|
||||
qobject_unref(response1);
|
||||
qobject_unref(response2);
|
||||
}
|
||||
|
||||
bool qmp_rsp_is_err(QDict *rsp)
|
||||
{
|
||||
QDict *error = qdict_get_qdict(rsp, "error");
|
||||
qobject_unref(rsp);
|
||||
return !!error;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user