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:
Anthony Liguori
2012-08-13 16:12:35 -05:00
35 changed files with 691 additions and 1121 deletions
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
-------------------
+1
View File
@@ -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);
+1
View 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
+1
View File
@@ -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)
Vendored
-10
View File
@@ -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
+27 -20
View File
@@ -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
+11 -84
View File
@@ -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;
}
+12 -22
View File
@@ -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
View File
@@ -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
+23 -46
View File
@@ -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);
+1
View File
@@ -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);
+2
View File
@@ -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
View File
@@ -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;
+14 -70
View File
@@ -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);
+1
View File
@@ -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,
+1 -1
View File
@@ -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
View File
@@ -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'] }
+1
View File
@@ -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