mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'qmp/queue/qmp' into staging
* qmp/queue/qmp: (48 commits) target-ppc: add implementation of query-cpu-definitions (v2) target-i386: add implementation of query-cpu-definitions (v2) qapi: add query-cpu-definitions command (v2) compiler: add macro for GCC weak symbols qapi: add query-machines command qapi: mark QOM commands stable qmp: introduce device-list-properties command qmp: add SUSPEND_DISK event qmp: qmp-events.txt: add missing doc for the SUSPEND event qmp: qmp-events.txt: put events in alphabetical order qmp: emit the WAKEUP event when the guest is put to run qmp: don't emit the RESET event on wakeup from S3 scripts: qapi-commands.py: qmp-commands.h: include qdict.h docs: writing-qmp-commands.txt: update error section error, qerror: drop QDict member qerror: drop qerror_table and qerror_format() error, qerror: pass desc string to error calls error: drop error_get_qobject()/error_set_qobject() qemu-ga: switch to the new error format on the wire qmp: switch to the new error format on the wire ...
This commit is contained in:
@@ -212,6 +212,7 @@ common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
|
||||
# qapi
|
||||
|
||||
qapi-obj-y = qapi/
|
||||
qapi-obj-y += qapi-types.o qapi-visit.o
|
||||
|
||||
common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o
|
||||
common-obj-y += qmp.o hmp.o
|
||||
|
||||
+162
-129
@@ -1,6 +1,23 @@
|
||||
QEMU Monitor Protocol Events
|
||||
============================
|
||||
|
||||
BALLOON_CHANGE
|
||||
--------------
|
||||
|
||||
Emitted when the guest changes the actual BALLOON level. This
|
||||
value is equivalent to the 'actual' field return by the
|
||||
'query-balloon' command
|
||||
|
||||
Data:
|
||||
|
||||
- "actual": actual level of the guest memory balloon in bytes (json-number)
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "BALLOON_CHANGE",
|
||||
"data": { "actual": 944766976 },
|
||||
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||
|
||||
BLOCK_IO_ERROR
|
||||
--------------
|
||||
|
||||
@@ -26,6 +43,57 @@ Example:
|
||||
Note: If action is "stop", a STOP event will eventually follow the
|
||||
BLOCK_IO_ERROR event.
|
||||
|
||||
BLOCK_JOB_CANCELLED
|
||||
-------------------
|
||||
|
||||
Emitted when a block job has been cancelled.
|
||||
|
||||
Data:
|
||||
|
||||
- "type": Job type ("stream" for image streaming, json-string)
|
||||
- "device": Device name (json-string)
|
||||
- "len": Maximum progress value (json-int)
|
||||
- "offset": Current progress value (json-int)
|
||||
On success this is equal to len.
|
||||
On failure this is less than len.
|
||||
- "speed": Rate limit, bytes per second (json-int)
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "BLOCK_JOB_CANCELLED",
|
||||
"data": { "type": "stream", "device": "virtio-disk0",
|
||||
"len": 10737418240, "offset": 134217728,
|
||||
"speed": 0 },
|
||||
"timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
|
||||
|
||||
BLOCK_JOB_COMPLETED
|
||||
-------------------
|
||||
|
||||
Emitted when a block job has completed.
|
||||
|
||||
Data:
|
||||
|
||||
- "type": Job type ("stream" for image streaming, json-string)
|
||||
- "device": Device name (json-string)
|
||||
- "len": Maximum progress value (json-int)
|
||||
- "offset": Current progress value (json-int)
|
||||
On success this is equal to len.
|
||||
On failure this is less than len.
|
||||
- "speed": Rate limit, bytes per second (json-int)
|
||||
- "error": Error message (json-string, optional)
|
||||
Only present on failure. This field contains a human-readable
|
||||
error message. There are no semantics other than that streaming
|
||||
has failed and clients should not try to interpret the error
|
||||
string.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "BLOCK_JOB_COMPLETED",
|
||||
"data": { "type": "stream", "device": "virtio-disk0",
|
||||
"len": 10737418240, "offset": 10737418240,
|
||||
"speed": 0 },
|
||||
"timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
|
||||
|
||||
DEVICE_TRAY_MOVED
|
||||
-----------------
|
||||
|
||||
@@ -98,6 +166,68 @@ Example:
|
||||
Note: If the command-line option "-no-shutdown" has been specified, a STOP
|
||||
event will eventually follow the SHUTDOWN event.
|
||||
|
||||
SPICE_CONNECTED, SPICE_DISCONNECTED
|
||||
-----------------------------------
|
||||
|
||||
Emitted when a SPICE client connects or disconnects.
|
||||
|
||||
Data:
|
||||
|
||||
- "server": Server information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
- "client": Client information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
|
||||
Example:
|
||||
|
||||
{ "timestamp": {"seconds": 1290688046, "microseconds": 388707},
|
||||
"event": "SPICE_CONNECTED",
|
||||
"data": {
|
||||
"server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
|
||||
"client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
|
||||
}}
|
||||
|
||||
SPICE_INITIALIZED
|
||||
-----------------
|
||||
|
||||
Emitted after initial handshake and authentication takes place (if any)
|
||||
and the SPICE channel is up'n'running
|
||||
|
||||
Data:
|
||||
|
||||
- "server": Server information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
- "auth": authentication method (json-string, optional)
|
||||
- "client": Client information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
- "connection-id": spice connection id. All channels with the same id
|
||||
belong to the same spice session (json-int)
|
||||
- "channel-type": channel type. "1" is the main control channel, filter for
|
||||
this one if you want track spice sessions only (json-int)
|
||||
- "channel-id": channel id. Usually "0", might be different needed when
|
||||
multiple channels of the same type exist, such as multiple
|
||||
display channels in a multihead setup (json-int)
|
||||
- "tls": whevener the channel is encrypted (json-bool)
|
||||
|
||||
Example:
|
||||
|
||||
{ "timestamp": {"seconds": 1290688046, "microseconds": 417172},
|
||||
"event": "SPICE_INITIALIZED",
|
||||
"data": {"server": {"auth": "spice", "port": "5921",
|
||||
"family": "ipv4", "host": "127.0.0.1"},
|
||||
"client": {"port": "49004", "family": "ipv4", "channel-type": 3,
|
||||
"connection-id": 1804289383, "host": "127.0.0.1",
|
||||
"channel-id": 0, "tls": true}
|
||||
}}
|
||||
|
||||
STOP
|
||||
----
|
||||
|
||||
@@ -110,6 +240,32 @@ Example:
|
||||
{ "event": "STOP",
|
||||
"timestamp": { "seconds": 1267041730, "microseconds": 281295 } }
|
||||
|
||||
SUSPEND
|
||||
-------
|
||||
|
||||
Emitted when guest enters S3 state.
|
||||
|
||||
Data: None.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "SUSPEND",
|
||||
"timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
|
||||
|
||||
SUSPEND_DISK
|
||||
------------
|
||||
|
||||
Emitted when the guest makes a request to enter S4 state.
|
||||
|
||||
Data: None.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "SUSPEND_DISK",
|
||||
"timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
|
||||
|
||||
Note: QEMU shuts down when entering S4 state.
|
||||
|
||||
VNC_CONNECTED
|
||||
-------------
|
||||
|
||||
@@ -200,69 +356,17 @@ Example:
|
||||
"host": "127.0.0.1", "sasl_username": "luiz" } },
|
||||
"timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
|
||||
|
||||
SPICE_CONNECTED, SPICE_DISCONNECTED
|
||||
-----------------------------------
|
||||
WAKEUP
|
||||
------
|
||||
|
||||
Emitted when a SPICE client connects or disconnects.
|
||||
Emitted when the guest has woken up from S3 and is running.
|
||||
|
||||
Data:
|
||||
|
||||
- "server": Server information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
- "client": Client information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
Data: None.
|
||||
|
||||
Example:
|
||||
|
||||
{ "timestamp": {"seconds": 1290688046, "microseconds": 388707},
|
||||
"event": "SPICE_CONNECTED",
|
||||
"data": {
|
||||
"server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
|
||||
"client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
|
||||
}}
|
||||
|
||||
|
||||
SPICE_INITIALIZED
|
||||
-----------------
|
||||
|
||||
Emitted after initial handshake and authentication takes place (if any)
|
||||
and the SPICE channel is up'n'running
|
||||
|
||||
Data:
|
||||
|
||||
- "server": Server information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
- "auth": authentication method (json-string, optional)
|
||||
- "client": Client information (json-object)
|
||||
- "host": IP address (json-string)
|
||||
- "port": port number (json-string)
|
||||
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||
- "connection-id": spice connection id. All channels with the same id
|
||||
belong to the same spice session (json-int)
|
||||
- "channel-type": channel type. "1" is the main control channel, filter for
|
||||
this one if you want track spice sessions only (json-int)
|
||||
- "channel-id": channel id. Usually "0", might be different needed when
|
||||
multiple channels of the same type exist, such as multiple
|
||||
display channels in a multihead setup (json-int)
|
||||
- "tls": whevener the channel is encrypted (json-bool)
|
||||
|
||||
Example:
|
||||
|
||||
{ "timestamp": {"seconds": 1290688046, "microseconds": 417172},
|
||||
"event": "SPICE_INITIALIZED",
|
||||
"data": {"server": {"auth": "spice", "port": "5921",
|
||||
"family": "ipv4", "host": "127.0.0.1"},
|
||||
"client": {"port": "49004", "family": "ipv4", "channel-type": 3,
|
||||
"connection-id": 1804289383, "host": "127.0.0.1",
|
||||
"channel-id": 0, "tls": true}
|
||||
}}
|
||||
|
||||
{ "event": "WATCHDOG",
|
||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
|
||||
WATCHDOG
|
||||
--------
|
||||
@@ -282,74 +386,3 @@ Example:
|
||||
|
||||
Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
|
||||
followed respectively by the RESET, SHUTDOWN, or STOP events.
|
||||
|
||||
|
||||
BLOCK_JOB_COMPLETED
|
||||
-------------------
|
||||
|
||||
Emitted when a block job has completed.
|
||||
|
||||
Data:
|
||||
|
||||
- "type": Job type ("stream" for image streaming, json-string)
|
||||
- "device": Device name (json-string)
|
||||
- "len": Maximum progress value (json-int)
|
||||
- "offset": Current progress value (json-int)
|
||||
On success this is equal to len.
|
||||
On failure this is less than len.
|
||||
- "speed": Rate limit, bytes per second (json-int)
|
||||
- "error": Error message (json-string, optional)
|
||||
Only present on failure. This field contains a human-readable
|
||||
error message. There are no semantics other than that streaming
|
||||
has failed and clients should not try to interpret the error
|
||||
string.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "BLOCK_JOB_COMPLETED",
|
||||
"data": { "type": "stream", "device": "virtio-disk0",
|
||||
"len": 10737418240, "offset": 10737418240,
|
||||
"speed": 0 },
|
||||
"timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
|
||||
|
||||
|
||||
BLOCK_JOB_CANCELLED
|
||||
-------------------
|
||||
|
||||
Emitted when a block job has been cancelled.
|
||||
|
||||
Data:
|
||||
|
||||
- "type": Job type ("stream" for image streaming, json-string)
|
||||
- "device": Device name (json-string)
|
||||
- "len": Maximum progress value (json-int)
|
||||
- "offset": Current progress value (json-int)
|
||||
On success this is equal to len.
|
||||
On failure this is less than len.
|
||||
- "speed": Rate limit, bytes per second (json-int)
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "BLOCK_JOB_CANCELLED",
|
||||
"data": { "type": "stream", "device": "virtio-disk0",
|
||||
"len": 10737418240, "offset": 134217728,
|
||||
"speed": 0 },
|
||||
"timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
|
||||
|
||||
|
||||
BALLOON_CHANGE
|
||||
----------
|
||||
|
||||
Emitted when the guest changes the actual BALLOON level. This
|
||||
value is equivalent to the 'actual' field return by the
|
||||
'query-balloon' command
|
||||
|
||||
Data:
|
||||
|
||||
- "actual": actual level of the guest memory balloon in bytes (json-number)
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "BALLOON_CHANGE",
|
||||
"data": { "actual": 944766976 },
|
||||
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||
|
||||
+3
-7
@@ -106,14 +106,11 @@ completed because of an error condition.
|
||||
|
||||
The format is:
|
||||
|
||||
{ "error": { "class": json-string, "data": json-object, "desc": json-string },
|
||||
"id": json-value }
|
||||
{ "error": { "class": json-string, "desc": json-string }, "id": json-value }
|
||||
|
||||
Where,
|
||||
|
||||
- The "class" member contains the error class name (eg. "ServiceUnavailable")
|
||||
- The "data" member contains specific error data and is defined in a
|
||||
per-command basis, it will be an empty json-object if the error has no data
|
||||
- The "class" member contains the error class name (eg. "GenericError")
|
||||
- The "desc" member is a human-readable error message. Clients should
|
||||
not attempt to parse this message.
|
||||
- The "id" member contains the transaction identification associated with
|
||||
@@ -173,8 +170,7 @@ S: {"return": {"enabled": true, "present": true}, "id": "example"}
|
||||
------------------
|
||||
|
||||
C: { "execute": }
|
||||
S: {"error": {"class": "JSONParsing", "desc": "Invalid JSON syntax", "data":
|
||||
{}}}
|
||||
S: {"error": {"class": "GenericError", "desc": "Invalid JSON syntax" } }
|
||||
|
||||
3.5 Powerdown event
|
||||
-------------------
|
||||
|
||||
@@ -2445,6 +2445,7 @@ BlockInfoList *qmp_query_block(Error **errp)
|
||||
info->value->inserted->ro = bs->read_only;
|
||||
info->value->inserted->drv = g_strdup(bs->drv->format_name);
|
||||
info->value->inserted->encrypted = bs->encrypted;
|
||||
info->value->inserted->encryption_key_missing = bdrv_key_required(bs);
|
||||
if (bs->backing_file[0]) {
|
||||
info->value->inserted->has_backing_file = true;
|
||||
info->value->inserted->backing_file = g_strdup(bs->backing_file);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "qemu-coroutine.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "qapi-types.h"
|
||||
#include "qerror.h"
|
||||
|
||||
#define BLOCK_FLAG_ENCRYPT 1
|
||||
#define BLOCK_FLAG_COMPAT6 4
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
# define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
|
||||
# endif
|
||||
#define GCC_WEAK __attribute__((weak))
|
||||
#else
|
||||
#define GCC_ATTR /**/
|
||||
#define GCC_FMT_ATTR(n, m)
|
||||
|
||||
@@ -171,7 +171,6 @@ vhost_net="no"
|
||||
kvm="no"
|
||||
gprof="no"
|
||||
debug_tcg="no"
|
||||
debug_mon="no"
|
||||
debug="no"
|
||||
strip_opt="yes"
|
||||
tcg_interpreter="no"
|
||||
@@ -657,14 +656,9 @@ for opt do
|
||||
;;
|
||||
--disable-debug-tcg) debug_tcg="no"
|
||||
;;
|
||||
--enable-debug-mon) debug_mon="yes"
|
||||
;;
|
||||
--disable-debug-mon) debug_mon="no"
|
||||
;;
|
||||
--enable-debug)
|
||||
# Enable debugging options that aren't excessively noisy
|
||||
debug_tcg="yes"
|
||||
debug_mon="yes"
|
||||
debug="yes"
|
||||
strip_opt="no"
|
||||
;;
|
||||
@@ -3064,7 +3058,6 @@ echo "host CPU $cpu"
|
||||
echo "host big endian $bigendian"
|
||||
echo "target list $target_list"
|
||||
echo "tcg debug enabled $debug_tcg"
|
||||
echo "Mon debug enabled $debug_mon"
|
||||
echo "gprof enabled $gprof"
|
||||
echo "sparse enabled $sparse"
|
||||
echo "strip binaries $strip_opt"
|
||||
@@ -3157,9 +3150,6 @@ echo "ARCH=$ARCH" >> $config_host_mak
|
||||
if test "$debug_tcg" = "yes" ; then
|
||||
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$debug_mon" = "yes" ; then
|
||||
echo "CONFIG_DEBUG_MONITOR=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$debug" = "yes" ; then
|
||||
echo "CONFIG_DEBUG_EXEC=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
@@ -210,19 +210,17 @@ if you don't see these strings, then something went wrong.
|
||||
=== Errors ===
|
||||
|
||||
QMP commands should use the error interface exported by the error.h header
|
||||
file. The basic function used to set an error is the error_set() one.
|
||||
file. Basically, errors are set by calling the error_set() function.
|
||||
|
||||
Let's say we don't accept the string "message" to contain the word "love". If
|
||||
it does contain it, we want the "hello-world" command to the return the
|
||||
InvalidParameter error.
|
||||
|
||||
Only one change is required, and it's in the C implementation:
|
||||
it does contain it, we want the "hello-world" command to return an error:
|
||||
|
||||
void qmp_hello_world(bool has_message, const char *message, Error **errp)
|
||||
{
|
||||
if (has_message) {
|
||||
if (strstr(message, "love")) {
|
||||
error_set(errp, QERR_INVALID_PARAMETER, "message");
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"the word 'love' is not allowed");
|
||||
return;
|
||||
}
|
||||
printf("%s\n", message);
|
||||
@@ -231,30 +229,40 @@ void qmp_hello_world(bool has_message, const char *message, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
Let's test it. Build qemu, run it as defined in the "Testing" section, and
|
||||
then issue the following command:
|
||||
The first argument to the error_set() function is the Error pointer to pointer,
|
||||
which is passed to all QMP functions. The second argument is a ErrorClass
|
||||
value, which should be ERROR_CLASS_GENERIC_ERROR most of the time (more
|
||||
details about error classes are given below). The third argument is a human
|
||||
description of the error, this is a free-form printf-like string.
|
||||
|
||||
{ "execute": "hello-world", "arguments": { "message": "we love qemu" } }
|
||||
Let's test the example above. Build qemu, run it as defined in the "Testing"
|
||||
section, and then issue the following command:
|
||||
|
||||
{ "execute": "hello-world", "arguments": { "message": "all you need is love" } }
|
||||
|
||||
The QMP server's response should be:
|
||||
|
||||
{
|
||||
"error": {
|
||||
"class": "InvalidParameter",
|
||||
"desc": "Invalid parameter 'message'",
|
||||
"data": {
|
||||
"name": "message"
|
||||
}
|
||||
"class": "GenericError",
|
||||
"desc": "the word 'love' is not allowed"
|
||||
}
|
||||
}
|
||||
|
||||
Which is the InvalidParameter error.
|
||||
As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR. There
|
||||
are two exceptions to this rule:
|
||||
|
||||
When you have to return an error but you're unsure what error to return or
|
||||
which arguments an error takes, you should look at the qerror.h file. Note
|
||||
that you might be required to add new errors if needed.
|
||||
1. A non-generic ErrorClass value exists* for the failure you want to report
|
||||
(eg. DeviceNotFound)
|
||||
|
||||
FIXME: describe better the error API and how to add new errors.
|
||||
2. Management applications have to take special action on the failure you
|
||||
want to report, hence you have to add a new ErrorClass value so that they
|
||||
can check for it
|
||||
|
||||
If the failure you want to report doesn't fall in one of the two cases above,
|
||||
just report ERROR_CLASS_GENERIC_ERROR.
|
||||
|
||||
* All existing ErrorClass values are defined in the qapi-schema.json file
|
||||
|
||||
=== Command Documentation ===
|
||||
|
||||
@@ -275,7 +283,6 @@ here goes "hello-world"'s new entry for the qapi-schema.json file:
|
||||
# @message: #optional string to be printed
|
||||
#
|
||||
# Returns: Nothing on success.
|
||||
# If @message contains "love", InvalidParameter
|
||||
#
|
||||
# Notes: if @message is not provided, the "Hello, world" string will
|
||||
# be printed instead
|
||||
|
||||
@@ -14,17 +14,16 @@
|
||||
#include "error.h"
|
||||
#include "qjson.h"
|
||||
#include "qdict.h"
|
||||
#include "error_int.h"
|
||||
#include "qapi-types.h"
|
||||
#include "qerror.h"
|
||||
|
||||
struct Error
|
||||
{
|
||||
QDict *obj;
|
||||
const char *fmt;
|
||||
char *msg;
|
||||
ErrorClass err_class;
|
||||
};
|
||||
|
||||
void error_set(Error **errp, const char *fmt, ...)
|
||||
void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
|
||||
{
|
||||
Error *err;
|
||||
va_list ap;
|
||||
@@ -37,9 +36,9 @@ void error_set(Error **errp, const char *fmt, ...)
|
||||
err = g_malloc0(sizeof(*err));
|
||||
|
||||
va_start(ap, fmt);
|
||||
err->obj = qobject_to_qdict(qobject_from_jsonv(fmt, &ap));
|
||||
err->msg = g_strdup_vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
err->fmt = fmt;
|
||||
err->err_class = err_class;
|
||||
|
||||
*errp = err;
|
||||
}
|
||||
@@ -50,9 +49,7 @@ Error *error_copy(const Error *err)
|
||||
|
||||
err_new = g_malloc0(sizeof(*err));
|
||||
err_new->msg = g_strdup(err->msg);
|
||||
err_new->fmt = err->fmt;
|
||||
err_new->obj = err->obj;
|
||||
QINCREF(err_new->obj);
|
||||
err_new->err_class = err->err_class;
|
||||
|
||||
return err_new;
|
||||
}
|
||||
@@ -62,75 +59,24 @@ bool error_is_set(Error **errp)
|
||||
return (errp && *errp);
|
||||
}
|
||||
|
||||
ErrorClass error_get_class(const Error *err)
|
||||
{
|
||||
return err->err_class;
|
||||
}
|
||||
|
||||
const char *error_get_pretty(Error *err)
|
||||
{
|
||||
if (err->msg == NULL) {
|
||||
QString *str;
|
||||
str = qerror_format(err->fmt, err->obj);
|
||||
err->msg = g_strdup(qstring_get_str(str));
|
||||
QDECREF(str);
|
||||
}
|
||||
|
||||
return err->msg;
|
||||
}
|
||||
|
||||
const char *error_get_field(Error *err, const char *field)
|
||||
{
|
||||
if (strcmp(field, "class") == 0) {
|
||||
return qdict_get_str(err->obj, field);
|
||||
} else {
|
||||
QDict *dict = qdict_get_qdict(err->obj, "data");
|
||||
return qdict_get_str(dict, field);
|
||||
}
|
||||
}
|
||||
|
||||
QDict *error_get_data(Error *err)
|
||||
{
|
||||
QDict *data = qdict_get_qdict(err->obj, "data");
|
||||
QINCREF(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void error_set_field(Error *err, const char *field, const char *value)
|
||||
{
|
||||
QDict *dict = qdict_get_qdict(err->obj, "data");
|
||||
qdict_put(dict, field, qstring_from_str(value));
|
||||
}
|
||||
|
||||
void error_free(Error *err)
|
||||
{
|
||||
if (err) {
|
||||
QDECREF(err->obj);
|
||||
g_free(err->msg);
|
||||
g_free(err);
|
||||
}
|
||||
}
|
||||
|
||||
bool error_is_type(Error *err, const char *fmt)
|
||||
{
|
||||
const char *error_class;
|
||||
char *ptr;
|
||||
char *end;
|
||||
|
||||
if (!err) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ptr = strstr(fmt, "'class': '");
|
||||
assert(ptr != NULL);
|
||||
ptr += strlen("'class': '");
|
||||
|
||||
end = strchr(ptr, '\'');
|
||||
assert(end != NULL);
|
||||
|
||||
error_class = error_get_field(err, "class");
|
||||
if (strlen(error_class) != end - ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strncmp(ptr, error_class, end - ptr) == 0;
|
||||
}
|
||||
|
||||
void error_propagate(Error **dst_err, Error *local_err)
|
||||
{
|
||||
if (dst_err && !*dst_err) {
|
||||
@@ -139,22 +85,3 @@ void error_propagate(Error **dst_err, Error *local_err)
|
||||
error_free(local_err);
|
||||
}
|
||||
}
|
||||
|
||||
QObject *error_get_qobject(Error *err)
|
||||
{
|
||||
QINCREF(err->obj);
|
||||
return QOBJECT(err->obj);
|
||||
}
|
||||
|
||||
void error_set_qobject(Error **errp, QObject *obj)
|
||||
{
|
||||
Error *err;
|
||||
if (errp == NULL) {
|
||||
return;
|
||||
}
|
||||
err = g_malloc0(sizeof(*err));
|
||||
err->obj = qobject_to_qdict(obj);
|
||||
qobject_incref(obj);
|
||||
|
||||
*errp = err;
|
||||
}
|
||||
|
||||
@@ -13,20 +13,21 @@
|
||||
#define ERROR_H
|
||||
|
||||
#include "compiler.h"
|
||||
#include "qapi-types.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* A class representing internal errors within QEMU. An error has a string
|
||||
* typename and optionally a set of named string parameters.
|
||||
* A class representing internal errors within QEMU. An error has a ErrorClass
|
||||
* code and a human message.
|
||||
*/
|
||||
typedef struct Error Error;
|
||||
|
||||
/**
|
||||
* Set an indirect pointer to an error given a printf-style format parameter.
|
||||
* Currently, qerror.h defines these error formats. This function is not
|
||||
* meant to be used outside of QEMU.
|
||||
* Set an indirect pointer to an error given a ErrorClass value and a
|
||||
* printf-style human message. This function is not meant to be used outside
|
||||
* of QEMU.
|
||||
*/
|
||||
void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4);
|
||||
|
||||
/**
|
||||
* Returns true if an indirect pointer to an error is pointing to a valid
|
||||
@@ -34,6 +35,11 @@ void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
*/
|
||||
bool error_is_set(Error **err);
|
||||
|
||||
/*
|
||||
* Get the error class of an error object.
|
||||
*/
|
||||
ErrorClass error_get_class(const Error *err);
|
||||
|
||||
/**
|
||||
* Returns an exact copy of the error passed as an argument.
|
||||
*/
|
||||
@@ -44,16 +50,6 @@ Error *error_copy(const Error *err);
|
||||
*/
|
||||
const char *error_get_pretty(Error *err);
|
||||
|
||||
/**
|
||||
* Get an individual named error field.
|
||||
*/
|
||||
const char *error_get_field(Error *err, const char *field);
|
||||
|
||||
/**
|
||||
* Get an individual named error field.
|
||||
*/
|
||||
void error_set_field(Error *err, const char *field, const char *value);
|
||||
|
||||
/**
|
||||
* Propagate an error to an indirect pointer to an error. This function will
|
||||
* always transfer ownership of the error reference and handles the case where
|
||||
@@ -66,10 +62,4 @@ void error_propagate(Error **dst_err, Error *local_err);
|
||||
*/
|
||||
void error_free(Error *err);
|
||||
|
||||
/**
|
||||
* Determine if an error is of a speific type (based on the qerror format).
|
||||
* Non-QEMU users should get the `class' field to identify the error type.
|
||||
*/
|
||||
bool error_is_type(Error *err, const char *fmt);
|
||||
|
||||
#endif
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* QEMU Error Objects
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2. See
|
||||
* the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
#ifndef QEMU_ERROR_INT_H
|
||||
#define QEMU_ERROR_INT_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qobject.h"
|
||||
#include "qdict.h"
|
||||
#include "error.h"
|
||||
|
||||
/**
|
||||
* Internal QEMU functions for working with Error.
|
||||
*
|
||||
* These are used to convert QErrors to Errors
|
||||
*/
|
||||
QDict *error_get_data(Error *err);
|
||||
QObject *error_get_qobject(Error *err);
|
||||
void error_set_qobject(Error **errp, QObject *obj);
|
||||
|
||||
#endif
|
||||
@@ -670,34 +670,35 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict)
|
||||
|
||||
static void hmp_cont_cb(void *opaque, int err)
|
||||
{
|
||||
Monitor *mon = opaque;
|
||||
|
||||
if (!err) {
|
||||
hmp_cont(mon, NULL);
|
||||
qmp_cont(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static bool key_is_missing(const BlockInfo *bdev)
|
||||
{
|
||||
return (bdev->inserted && bdev->inserted->encryption_key_missing);
|
||||
}
|
||||
|
||||
void hmp_cont(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
BlockInfoList *bdev_list, *bdev;
|
||||
Error *errp = NULL;
|
||||
|
||||
qmp_cont(&errp);
|
||||
if (error_is_set(&errp)) {
|
||||
if (error_is_type(errp, QERR_DEVICE_ENCRYPTED)) {
|
||||
const char *device;
|
||||
|
||||
/* The device is encrypted. Ask the user for the password
|
||||
and retry */
|
||||
|
||||
device = error_get_field(errp, "device");
|
||||
assert(device != NULL);
|
||||
|
||||
monitor_read_block_device_key(mon, device, hmp_cont_cb, mon);
|
||||
error_free(errp);
|
||||
return;
|
||||
bdev_list = qmp_query_block(NULL);
|
||||
for (bdev = bdev_list; bdev; bdev = bdev->next) {
|
||||
if (key_is_missing(bdev->value)) {
|
||||
monitor_read_block_device_key(mon, bdev->value->device,
|
||||
hmp_cont_cb, NULL);
|
||||
goto out;
|
||||
}
|
||||
hmp_handle_error(mon, &errp);
|
||||
}
|
||||
|
||||
qmp_cont(&errp);
|
||||
hmp_handle_error(mon, &errp);
|
||||
|
||||
out:
|
||||
qapi_free_BlockInfoList(bdev_list);
|
||||
}
|
||||
|
||||
void hmp_system_wakeup(Monitor *mon, const QDict *qdict)
|
||||
@@ -878,22 +879,6 @@ static void hmp_change_read_arg(Monitor *mon, const char *password,
|
||||
monitor_read_command(mon, 1);
|
||||
}
|
||||
|
||||
static void cb_hmp_change_bdrv_pwd(Monitor *mon, const char *password,
|
||||
void *opaque)
|
||||
{
|
||||
Error *encryption_err = opaque;
|
||||
Error *err = NULL;
|
||||
const char *device;
|
||||
|
||||
device = error_get_field(encryption_err, "device");
|
||||
|
||||
qmp_block_passwd(device, password, &err);
|
||||
hmp_handle_error(mon, &err);
|
||||
error_free(encryption_err);
|
||||
|
||||
monitor_read_command(mon, 1);
|
||||
}
|
||||
|
||||
void hmp_change(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
@@ -911,18 +896,10 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
|
||||
qmp_change(device, target, !!arg, arg, &err);
|
||||
if (error_is_type(err, QERR_DEVICE_ENCRYPTED)) {
|
||||
monitor_printf(mon, "%s (%s) is encrypted.\n",
|
||||
error_get_field(err, "device"),
|
||||
error_get_field(err, "filename"));
|
||||
if (!monitor_get_rs(mon)) {
|
||||
monitor_printf(mon,
|
||||
"terminal does not support password prompting\n");
|
||||
error_free(err);
|
||||
return;
|
||||
}
|
||||
readline_start(monitor_get_rs(mon), "Password: ", 1,
|
||||
cb_hmp_change_bdrv_pwd, err);
|
||||
if (error_is_set(&err) &&
|
||||
error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
|
||||
error_free(err);
|
||||
monitor_read_block_device_key(mon, device, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
hmp_handle_error(mon, &err);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qapi-types.h"
|
||||
#include "qdict.h"
|
||||
|
||||
void hmp_info_name(Monitor *mon);
|
||||
void hmp_info_version(Monitor *mon);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "hw.h"
|
||||
#include "pc.h"
|
||||
#include "acpi.h"
|
||||
#include "monitor.h"
|
||||
|
||||
struct acpi_table_header {
|
||||
uint16_t _length; /* our length, not actual part of the hdr */
|
||||
@@ -386,6 +387,7 @@ void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4)
|
||||
break;
|
||||
default:
|
||||
if (sus_typ == s4) { /* S4 request */
|
||||
monitor_protocol_event(QEVENT_SUSPEND_DISK, NULL);
|
||||
qemu_system_shutdown_request();
|
||||
}
|
||||
break;
|
||||
|
||||
+10
-14
@@ -82,27 +82,23 @@ static void tcp_wait_for_connect(void *opaque)
|
||||
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
|
||||
Error **errp)
|
||||
{
|
||||
bool in_progress;
|
||||
|
||||
s->get_error = socket_errno;
|
||||
s->write = socket_write;
|
||||
s->close = tcp_close;
|
||||
|
||||
s->fd = inet_connect(host_port, false, errp);
|
||||
|
||||
if (!error_is_set(errp)) {
|
||||
migrate_fd_connect(s);
|
||||
} else if (error_is_type(*errp, QERR_SOCKET_CONNECT_IN_PROGRESS)) {
|
||||
DPRINTF("connect in progress\n");
|
||||
qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
|
||||
} else if (error_is_type(*errp, QERR_SOCKET_CREATE_FAILED)) {
|
||||
DPRINTF("connect failed\n");
|
||||
return -1;
|
||||
} else if (error_is_type(*errp, QERR_SOCKET_CONNECT_FAILED)) {
|
||||
DPRINTF("connect failed\n");
|
||||
s->fd = inet_connect(host_port, false, &in_progress, errp);
|
||||
if (error_is_set(errp)) {
|
||||
migrate_fd_error(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (in_progress) {
|
||||
DPRINTF("connect in progress\n");
|
||||
qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
|
||||
} else {
|
||||
DPRINTF("unknown error\n");
|
||||
return -1;
|
||||
migrate_fd_connect(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -172,41 +172,11 @@ struct Monitor {
|
||||
CPUArchState *mon_cpu;
|
||||
BlockDriverCompletionFunc *password_completion_cb;
|
||||
void *password_opaque;
|
||||
#ifdef CONFIG_DEBUG_MONITOR
|
||||
int print_calls_nr;
|
||||
#endif
|
||||
QError *error;
|
||||
QLIST_HEAD(,mon_fd_t) fds;
|
||||
QLIST_ENTRY(Monitor) entry;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_MONITOR
|
||||
#define MON_DEBUG(fmt, ...) do { \
|
||||
fprintf(stderr, "Monitor: "); \
|
||||
fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
|
||||
|
||||
static inline void mon_print_count_inc(Monitor *mon)
|
||||
{
|
||||
mon->print_calls_nr++;
|
||||
}
|
||||
|
||||
static inline void mon_print_count_init(Monitor *mon)
|
||||
{
|
||||
mon->print_calls_nr = 0;
|
||||
}
|
||||
|
||||
static inline int mon_print_count_get(const Monitor *mon)
|
||||
{
|
||||
return mon->print_calls_nr;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_DEBUG_MONITOR */
|
||||
#define MON_DEBUG(fmt, ...) do { } while (0)
|
||||
static inline void mon_print_count_inc(Monitor *mon) { }
|
||||
static inline void mon_print_count_init(Monitor *mon) { }
|
||||
static inline int mon_print_count_get(const Monitor *mon) { return 0; }
|
||||
#endif /* CONFIG_DEBUG_MONITOR */
|
||||
|
||||
/* QMP checker flags */
|
||||
#define QMP_ACCEPT_UNKNOWNS 1
|
||||
|
||||
@@ -299,8 +269,6 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
|
||||
if (!mon)
|
||||
return;
|
||||
|
||||
mon_print_count_inc(mon);
|
||||
|
||||
if (monitor_ctrl_mode(mon)) {
|
||||
return;
|
||||
}
|
||||
@@ -385,16 +353,26 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
|
||||
QDECREF(json);
|
||||
}
|
||||
|
||||
static QDict *build_qmp_error_dict(const QError *err)
|
||||
{
|
||||
QObject *obj;
|
||||
|
||||
obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %p } }",
|
||||
ErrorClass_lookup[err->err_class],
|
||||
qerror_human(err));
|
||||
|
||||
return qobject_to_qdict(obj);
|
||||
}
|
||||
|
||||
static void monitor_protocol_emitter(Monitor *mon, QObject *data)
|
||||
{
|
||||
QDict *qmp;
|
||||
|
||||
trace_monitor_protocol_emitter(mon);
|
||||
|
||||
qmp = qdict_new();
|
||||
|
||||
if (!monitor_has_error(mon)) {
|
||||
/* success response */
|
||||
qmp = qdict_new();
|
||||
if (data) {
|
||||
qobject_incref(data);
|
||||
qdict_put_obj(qmp, "return", data);
|
||||
@@ -404,9 +382,7 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
|
||||
}
|
||||
} else {
|
||||
/* error response */
|
||||
qdict_put(mon->error->error, "desc", qerror_human(mon->error));
|
||||
qdict_put(qmp, "error", mon->error->error);
|
||||
QINCREF(mon->error->error);
|
||||
qmp = build_qmp_error_dict(mon->error);
|
||||
QDECREF(mon->error);
|
||||
mon->error = NULL;
|
||||
}
|
||||
@@ -456,6 +432,7 @@ static const char *monitor_event_names[] = {
|
||||
[QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
|
||||
[QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
|
||||
[QEVENT_SUSPEND] = "SUSPEND",
|
||||
[QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
|
||||
[QEVENT_WAKEUP] = "WAKEUP",
|
||||
[QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
|
||||
};
|
||||
@@ -3874,8 +3851,6 @@ void monitor_set_error(Monitor *mon, QError *qerror)
|
||||
if (!mon->error) {
|
||||
mon->error = qerror;
|
||||
} else {
|
||||
MON_DEBUG("Additional error report at %s:%d\n",
|
||||
qerror->file, qerror->linenr);
|
||||
QDECREF(qerror);
|
||||
}
|
||||
}
|
||||
@@ -3889,36 +3864,7 @@ static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
|
||||
* Action: Report an internal error to the client if in QMP.
|
||||
*/
|
||||
qerror_report(QERR_UNDEFINED_ERROR);
|
||||
MON_DEBUG("command '%s' returned failure but did not pass an error\n",
|
||||
cmd->name);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_MONITOR
|
||||
if (!ret && monitor_has_error(mon)) {
|
||||
/*
|
||||
* If it returns success, it must not have passed an error.
|
||||
*
|
||||
* Action: Report the passed error to the client.
|
||||
*/
|
||||
MON_DEBUG("command '%s' returned success but passed an error\n",
|
||||
cmd->name);
|
||||
}
|
||||
|
||||
if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
|
||||
/*
|
||||
* Handlers should not call Monitor print functions.
|
||||
*
|
||||
* Action: Ignore them in QMP.
|
||||
*
|
||||
* (XXX: we don't check any 'info' or 'query' command here
|
||||
* because the user print function _is_ called by do_info(), hence
|
||||
* we will trigger this check. This problem will go away when we
|
||||
* make 'query' commands real and kill do_info())
|
||||
*/
|
||||
MON_DEBUG("command '%s' called print functions %d time(s)\n",
|
||||
cmd->name, mon_print_count_get(mon));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void handle_user_command(Monitor *mon, const char *cmdline)
|
||||
@@ -4447,8 +4393,6 @@ static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd,
|
||||
int ret;
|
||||
QObject *data = NULL;
|
||||
|
||||
mon_print_count_init(mon);
|
||||
|
||||
ret = cmd->mhandler.cmd_new(mon, params, &data);
|
||||
handler_audit(mon, cmd, ret);
|
||||
monitor_protocol_emitter(mon, data);
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef enum MonitorEvent {
|
||||
QEVENT_BLOCK_JOB_CANCELLED,
|
||||
QEVENT_DEVICE_TRAY_MOVED,
|
||||
QEVENT_SUSPEND,
|
||||
QEVENT_SUSPEND_DISK,
|
||||
QEVENT_WAKEUP,
|
||||
QEVENT_BALLOON_CHANGE,
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ int tcp_socket_outgoing(const char *address, uint16_t port)
|
||||
|
||||
int tcp_socket_outgoing_spec(const char *address_and_port)
|
||||
{
|
||||
return inet_connect(address_and_port, true, NULL);
|
||||
return inet_connect(address_and_port, true, NULL, NULL);
|
||||
}
|
||||
|
||||
int tcp_socket_incoming(const char *address, uint16_t port)
|
||||
|
||||
+119
-73
@@ -2,6 +2,36 @@
|
||||
#
|
||||
# QAPI Schema
|
||||
|
||||
##
|
||||
# @ErrorClass
|
||||
#
|
||||
# QEMU error classes
|
||||
#
|
||||
# @GenericError: this is used for errors that don't require a specific error
|
||||
# class. This should be the default case for most errors
|
||||
#
|
||||
# @CommandNotFound: the requested command has not been found
|
||||
#
|
||||
# @DeviceEncrypted: the requested operation can't be fulfilled because the
|
||||
# selected device is encrypted
|
||||
#
|
||||
# @DeviceNotActive: a device has failed to be become active
|
||||
#
|
||||
# @DeviceNotFound: the requested device has not been found
|
||||
#
|
||||
# @KVMMissingCap: the requested operation can't be fulfilled because a
|
||||
# required KVM capability is missing
|
||||
#
|
||||
# @MigrationExpected: the requested operation can't be fulfilled because a
|
||||
# migration process is expected
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'enum': 'ErrorClass',
|
||||
'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',
|
||||
'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap',
|
||||
'MigrationExpected' ] }
|
||||
|
||||
##
|
||||
# @NameInfo:
|
||||
#
|
||||
@@ -486,6 +516,9 @@
|
||||
#
|
||||
# @encrypted: true if the backing device is encrypted
|
||||
#
|
||||
# @encryption_key_missing: true if the backing device is encrypted but an
|
||||
# valid encryption key is missing
|
||||
#
|
||||
# @bps: total throughput limit in bytes per second is specified
|
||||
#
|
||||
# @bps_rd: read throughput limit in bytes per second is specified
|
||||
@@ -505,9 +538,9 @@
|
||||
{ 'type': 'BlockDeviceInfo',
|
||||
'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str',
|
||||
'*backing_file': 'str', 'backing_file_depth': 'int',
|
||||
'encrypted': 'bool', 'bps': 'int', 'bps_rd': 'int',
|
||||
'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int',
|
||||
'iops_wr': 'int'} }
|
||||
'encrypted': 'bool', 'encryption_key_missing': 'bool',
|
||||
'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
|
||||
'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }
|
||||
|
||||
##
|
||||
# @BlockDeviceIoStatus:
|
||||
@@ -709,7 +742,6 @@
|
||||
# Returns information about the current VNC server
|
||||
#
|
||||
# Returns: @VncInfo
|
||||
# If VNC support is not compiled in, FeatureDisabled
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
@@ -1093,9 +1125,6 @@
|
||||
# virtual address (defaults to CPU 0)
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @cpu is not a valid VCPU, InvalidParameterValue
|
||||
# If @filename cannot be opened, OpenFileFailed
|
||||
# If an I/O error occurs while writing the file, IOError
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
@@ -1116,8 +1145,6 @@
|
||||
# @filename: the file to save the memory to as binary data
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @filename cannot be opened, OpenFileFailed
|
||||
# If an I/O error occurs while writing the file, IOError
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
@@ -1159,7 +1186,6 @@
|
||||
# Injects an Non-Maskable Interrupt into all guest's VCPUs.
|
||||
#
|
||||
# Returns: If successful, nothing
|
||||
# If the Virtual Machine doesn't support NMI injection, Unsupported
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
@@ -1210,7 +1236,6 @@
|
||||
# Returns: nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
# If @device is not encrypted, DeviceNotEncrypted
|
||||
# If @password is not valid for this device, InvalidPassword
|
||||
#
|
||||
# Notes: Not all block formats support encryption and some that do are not
|
||||
# able to validate that a password is correct. Disk corruption may
|
||||
@@ -1251,11 +1276,6 @@
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
# If @size is negative, InvalidParameterValue
|
||||
# If the block device has no medium inserted, DeviceHasNoMedium
|
||||
# If the block device does not support resize, Unsupported
|
||||
# If the block device is read-only, DeviceIsReadOnly
|
||||
# If a long-running operation is using the device, DeviceInUse
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
@@ -1317,10 +1337,6 @@
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
# If @device is busy, DeviceInUse will be returned
|
||||
# If @snapshot-file can't be created, OpenFileFailed
|
||||
# If @snapshot-file can't be opened, OpenFileFailed
|
||||
# If @format is invalid, InvalidBlockFormat
|
||||
#
|
||||
# Note: The transaction aborts on the first failure. Therefore, there will
|
||||
# be only one device or snapshot file returned in an error condition, and
|
||||
@@ -1349,8 +1365,6 @@
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
# If @snapshot-file can't be opened, OpenFileFailed
|
||||
# If @format is invalid, InvalidBlockFormat
|
||||
#
|
||||
# Since 0.14.0
|
||||
##
|
||||
@@ -1474,9 +1488,7 @@
|
||||
# 4) A link type in the form 'link<subtype>' where subtype is a qdev
|
||||
# device type name. Link properties form the device model graph.
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Notes: This type is experimental. Its syntax may change in future releases.
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'type': 'ObjectPropertyInfo',
|
||||
'data': { 'name': 'str', 'type': 'str' } }
|
||||
@@ -1493,10 +1505,7 @@
|
||||
# Returns: a list of @ObjectPropertyInfo that describe the properties of the
|
||||
# object.
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Notes: This command is experimental. It's syntax may change in future
|
||||
# releases.
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'command': 'qom-list',
|
||||
'data': { 'path': 'str' },
|
||||
@@ -1532,9 +1541,7 @@
|
||||
# returns as #str pathnames. All integer property types (u8, u16, etc)
|
||||
# are returned as #int.
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Notes: This command is experimental and may change syntax in future releases.
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'command': 'qom-get',
|
||||
'data': { 'path': 'str', 'property': 'str' },
|
||||
@@ -1553,9 +1560,7 @@
|
||||
# @value: a value who's type is appropriate for the property type. See @qom-get
|
||||
# for a description of type mapping.
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Notes: This command is experimental and may change syntax in future releases.
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'command': 'qom-set',
|
||||
'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' },
|
||||
@@ -1579,11 +1584,6 @@
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If Spice is not enabled, DeviceNotFound
|
||||
# If @protocol does not support connected, InvalidParameter
|
||||
# If @protocol is invalid, InvalidParameter
|
||||
# If any other error occurs, SetPasswdFailed
|
||||
#
|
||||
# Notes: If VNC is not enabled, SetPasswdFailed is returned.
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
@@ -1605,8 +1605,6 @@
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @protocol is `spice' and Spice is not active, DeviceNotFound
|
||||
# If an error occurs setting password expiration, SetPasswdFailed
|
||||
# If @protocol is not `spice' or 'vnc', InvalidParameter
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
@@ -1629,8 +1627,6 @@
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
# If @device is not removable and @force is false, DeviceNotRemovable
|
||||
# If @force is false and @device is locked, DeviceLocked
|
||||
#
|
||||
# Notes: Ejecting a device will no media results in success
|
||||
#
|
||||
@@ -1673,7 +1669,6 @@
|
||||
#
|
||||
# Returns: Nothing on success.
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
# If @format is not a valid block format, InvalidBlockFormat
|
||||
# If the new block device is encrypted, DeviceEncrypted. Note that
|
||||
# if this error is returned, the device has been opened successfully
|
||||
# and an additional call to @block_passwd is required to set the
|
||||
@@ -1709,7 +1704,6 @@
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @device is not a valid block device, DeviceNotFound
|
||||
# If the argument combination is invalid, InvalidParameterCombination
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
@@ -1743,11 +1737,7 @@
|
||||
# @speed: #optional the maximum speed, in bytes per second
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If streaming is already active on this device, DeviceInUse
|
||||
# If @device does not exist, DeviceNotFound
|
||||
# If image streaming is not supported by this device, NotSupported
|
||||
# If @base does not exist, BaseNotFound
|
||||
# If @speed is invalid, InvalidParameter
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
@@ -1769,8 +1759,6 @@
|
||||
# Defaults to 0.
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If the job type does not support throttling, NotSupported
|
||||
# If the speed value is invalid, InvalidParameter
|
||||
# If no background operation is active on this device, DeviceNotActive
|
||||
#
|
||||
# Since: 1.1
|
||||
@@ -1800,7 +1788,6 @@
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If no background operation is active on this device, DeviceNotActive
|
||||
# If cancellation already in progress, DeviceInUse
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
@@ -1832,13 +1819,39 @@
|
||||
# Returns: a list of @ObjectTypeInfo or an empty list if no results are found
|
||||
#
|
||||
# Since: 1.1
|
||||
#
|
||||
# Notes: This command is experimental and may change syntax in future releases.
|
||||
##
|
||||
{ 'command': 'qom-list-types',
|
||||
'data': { '*implements': 'str', '*abstract': 'bool' },
|
||||
'returns': [ 'ObjectTypeInfo' ] }
|
||||
|
||||
##
|
||||
# @DevicePropertyInfo:
|
||||
#
|
||||
# Information about device properties.
|
||||
#
|
||||
# @name: the name of the property
|
||||
# @type: the typename of the property
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'type': 'DevicePropertyInfo',
|
||||
'data': { 'name': 'str', 'type': 'str' } }
|
||||
|
||||
##
|
||||
# @device-list-properties:
|
||||
#
|
||||
# List properties associated with a device.
|
||||
#
|
||||
# @typename: the type name of a device
|
||||
#
|
||||
# Returns: a list of DevicePropertyInfo describing a devices properties
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'command': 'device-list-properties',
|
||||
'data': { 'typename': 'str'},
|
||||
'returns': [ 'DevicePropertyInfo' ] }
|
||||
|
||||
##
|
||||
# @migrate
|
||||
#
|
||||
@@ -1870,8 +1883,6 @@
|
||||
# format.
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @filename cannot be opened, OpenFileFailed
|
||||
# If an I/O error occurs while writing the file, IOError
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
@@ -1886,7 +1897,6 @@
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @id is not a valid device, DeviceNotFound
|
||||
# If the device does not support unplug, BusNoHotplug
|
||||
#
|
||||
# Notes: When this command completes, the device may not be removed from the
|
||||
# guest. Hot removal is an operation that requires guest cooperation.
|
||||
@@ -1927,14 +1937,6 @@
|
||||
# want to dump all guest's memory, please specify the start @begin and @length
|
||||
#
|
||||
# Returns: nothing on success
|
||||
# If @begin contains an invalid address, InvalidParameter
|
||||
# If only one of @begin and @length is specified, MissingParameter
|
||||
# If @protocol stats with "fd:", and the fd cannot be found, FdNotFound
|
||||
# If @protocol starts with "file:", and the file cannot be
|
||||
# opened, OpenFileFailed
|
||||
# If @protocol does not start with "fd:" or "file:", InvalidParameter
|
||||
# If an I/O error occurs while writing the file, IOError
|
||||
# If the target does not support this command, Unsupported
|
||||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
@@ -1961,10 +1963,6 @@
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @type is not a valid network backend, DeviceNotFound
|
||||
# If @id is not a valid identifier, InvalidParameterValue
|
||||
# if @id already exists, DuplicateId
|
||||
# If @props contains an invalid parameter for this backend,
|
||||
# InvalidParameter
|
||||
##
|
||||
{ 'command': 'netdev_add',
|
||||
'data': {'type': 'str', 'id': 'str', '*props': '**'},
|
||||
@@ -2284,8 +2282,6 @@
|
||||
# @fdname: file descriptor name
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If file descriptor was not received, FdNotSupplied
|
||||
# If @fdname is not valid, InvalidParameterType
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
@@ -2305,8 +2301,58 @@
|
||||
# @fdname: file descriptor name
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If @fdname is not found, FdNotFound
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'command': 'closefd', 'data': {'fdname': 'str'} }
|
||||
|
||||
##
|
||||
# @MachineInfo:
|
||||
#
|
||||
# Information describing a machine.
|
||||
#
|
||||
# @name: the name of the machine
|
||||
#
|
||||
# @alias: #optional an alias for the machine name
|
||||
#
|
||||
# @default: #optional whether the machine is default
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'type': 'MachineInfo',
|
||||
'data': { 'name': 'str', '*alias': 'str',
|
||||
'*is-default': 'bool' } }
|
||||
|
||||
##
|
||||
# @query-machines:
|
||||
#
|
||||
# Return a list of supported machines
|
||||
#
|
||||
# Returns: a list of MachineInfo
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'command': 'query-machines', 'returns': ['MachineInfo'] }
|
||||
|
||||
##
|
||||
# @CpuDefinitionInfo:
|
||||
#
|
||||
# Virtual CPU definition.
|
||||
#
|
||||
# @name: the name of the CPU definition
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'type': 'CpuDefinitionInfo',
|
||||
'data': { 'name': 'str' } }
|
||||
|
||||
##
|
||||
# @query-cpu-definitions:
|
||||
#
|
||||
# Return a list of supported virtual CPU definitions
|
||||
#
|
||||
# Returns: a list of CpuDefInfo
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }
|
||||
|
||||
@@ -49,6 +49,7 @@ void qmp_disable_command(const char *name);
|
||||
void qmp_enable_command(const char *name);
|
||||
bool qmp_command_is_enabled(const char *name);
|
||||
char **qmp_get_command_list(void);
|
||||
QObject *qmp_build_error_object(Error *errp);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user