common-obj-y += block-migration.o iohandler.o
common-obj-y += pflib.o
common-obj-y += bitmap.o bitops.o
+common-obj-y += page_cache.o
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
common-obj-$(CONFIG_WIN32) += version.o
# 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
kvm="no"
gprof="no"
debug_tcg="no"
- debug_mon="no"
debug="no"
strip_opt="yes"
tcg_interpreter="no"
;;
--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"
;;
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"
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
mkdir -p linux-headers
case "$cpu" in
i386|x86_64)
- symlink "$source_path/linux-headers/asm-x86" linux-headers/asm
+ linux_arch=x86
;;
ppcemb|ppc|ppc64)
- symlink "$source_path/linux-headers/asm-powerpc" linux-headers/asm
+ linux_arch=powerpc
;;
s390x)
- symlink "$source_path/linux-headers/asm-s390" linux-headers/asm
+ linux_arch=s390
+ ;;
+ *)
+ # For most CPUs the kernel architecture name and QEMU CPU name match.
+ linux_arch="$cpu"
;;
esac
+ # For non-KVM architectures we will not have asm headers
+ if [ -e "$source_path/linux-headers/asm-$linux_arch" ]; then
+ symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm
+ fi
fi
for target in $target_list; do
void hmp_info_migrate(Monitor *mon)
{
MigrationInfo *info;
+ MigrationCapabilityStatusList *caps, *cap;
info = qmp_query_migrate(NULL);
+ caps = qmp_query_migrate_capabilities(NULL);
+
+ /* do not display parameters during setup */
+ if (info->has_status && caps) {
+ monitor_printf(mon, "capabilities: ");
+ for (cap = caps; cap; cap = cap->next) {
+ monitor_printf(mon, "%s: %s ",
+ MigrationCapability_lookup[cap->value->capability],
+ cap->value->state ? "on" : "off");
+ }
+ monitor_printf(mon, "\n");
+ }
if (info->has_status) {
monitor_printf(mon, "Migration status: %s\n", info->status);
info->ram->total >> 10);
monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
info->ram->total_time);
+ monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
+ info->ram->duplicate);
+ monitor_printf(mon, "normal: %" PRIu64 " pages\n",
+ info->ram->normal);
+ monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
+ info->ram->normal_bytes >> 10);
}
if (info->has_disk) {
info->disk->total >> 10);
}
+ if (info->has_xbzrle_cache) {
+ monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
+ info->xbzrle_cache->cache_size);
+ monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
+ info->xbzrle_cache->bytes >> 10);
+ monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
+ info->xbzrle_cache->pages);
+ monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
+ info->xbzrle_cache->cache_miss);
+ monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
+ info->xbzrle_cache->overflow);
+ }
+
qapi_free_MigrationInfo(info);
+ qapi_free_MigrationCapabilityStatusList(caps);
+}
+
+void hmp_info_migrate_capabilities(Monitor *mon)
+{
+ MigrationCapabilityStatusList *caps, *cap;
+
+ caps = qmp_query_migrate_capabilities(NULL);
+
+ if (caps) {
+ monitor_printf(mon, "capabilities: ");
+ for (cap = caps; cap; cap = cap->next) {
+ monitor_printf(mon, "%s: %s ",
+ MigrationCapability_lookup[cap->value->capability],
+ cap->value->state ? "on" : "off");
+ }
+ monitor_printf(mon, "\n");
+ }
+
+ qapi_free_MigrationCapabilityStatusList(caps);
+}
+
+void hmp_info_migrate_cache_size(Monitor *mon)
+{
+ monitor_printf(mon, "xbzrel cache size: %" PRId64 " kbytes\n",
+ qmp_query_migrate_cache_size(NULL) >> 10);
}
void hmp_info_cpus(Monitor *mon)
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)
qmp_migrate_set_downtime(value, NULL);
}
+void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict)
+{
+ int64_t value = qdict_get_int(qdict, "value");
+ Error *err = NULL;
+
+ qmp_migrate_set_cache_size(value, &err);
+ if (err) {
+ monitor_printf(mon, "%s\n", error_get_pretty(err));
+ error_free(err);
+ return;
+ }
+}
+
void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
{
int64_t value = qdict_get_int(qdict, "value");
qmp_migrate_set_speed(value, NULL);
}
+void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
+{
+ const char *cap = qdict_get_str(qdict, "capability");
+ bool state = qdict_get_bool(qdict, "state");
+ Error *err = NULL;
+ MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
+ int i;
+
+ for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+ if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
+ caps->value = g_malloc0(sizeof(*caps->value));
+ caps->value->capability = i;
+ caps->value->state = state;
+ caps->next = NULL;
+ qmp_migrate_set_capabilities(caps, &err);
+ break;
+ }
+ }
+
+ if (i == MIGRATION_CAPABILITY_MAX) {
+ error_set(&err, QERR_INVALID_PARAMETER, cap);
+ }
+
+ qapi_free_MigrationCapabilityStatusList(caps);
+
+ if (err) {
+ monitor_printf(mon, "migrate_set_parameter: %s\n",
+ error_get_pretty(err));
+ error_free(err);
+ }
+}
+
void hmp_set_password(Monitor *mon, const QDict *qdict)
{
const char *protocol = qdict_get_str(qdict, "protocol");
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");
}
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);
#include "qemu-common.h"
#include "qapi-types.h"
+ #include "qdict.h"
void hmp_info_name(Monitor *mon);
void hmp_info_version(Monitor *mon);
void hmp_info_chardev(Monitor *mon);
void hmp_info_mice(Monitor *mon);
void hmp_info_migrate(Monitor *mon);
+void hmp_info_migrate_capabilities(Monitor *mon);
+void hmp_info_migrate_cache_size(Monitor *mon);
void hmp_info_cpus(Monitor *mon);
void hmp_info_block(Monitor *mon);
void hmp_info_blockstats(Monitor *mon);
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
void hmp_set_password(Monitor *mon, const QDict *qdict);
void hmp_expire_password(Monitor *mon, const QDict *qdict);
void hmp_eject(Monitor *mon, const QDict *qdict);
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
if (!mon)
return;
- mon_print_count_inc(mon);
-
if (monitor_ctrl_mode(mon)) {
return;
}
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);
}
} 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;
}
[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",
};
.help = "show migration status",
.mhandler.info = hmp_info_migrate,
},
+ {
+ .name = "migrate_capabilities",
+ .args_type = "",
+ .params = "",
+ .help = "show current migration capabilities",
+ .mhandler.info = hmp_info_migrate_capabilities,
+ },
+ {
+ .name = "migrate_cache_size",
+ .args_type = "",
+ .params = "",
+ .help = "show current migration xbzrle cache size",
+ .mhandler.info = hmp_info_migrate_cache_size,
+ },
{
.name = "balloon",
.args_type = "",
if (!mon->error) {
mon->error = qerror;
} else {
- MON_DEBUG("Additional error report at %s:%d\n",
- qerror->file, qerror->linenr);
QDECREF(qerror);
}
}
* 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)
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);
#
# 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:
#
#
# @total: total amount of bytes involved in the migration process
#
-# @total_time: tota0l amount of ms since migration started. If
+# @total-time: total amount of ms since migration started. If
# migration has ended, it returns the total migration
# time. (since 1.2)
#
-# Since: 0.14.0.
+# @duplicate: number of duplicate pages (since 1.2)
+#
+# @normal : number of normal pages (since 1.2)
+#
+# @normal-bytes : number of normal bytes sent (since 1.2)
+#
+# Since: 0.14.0
##
{ 'type': 'MigrationStats',
'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
- 'total_time': 'int' } }
+ 'total-time': 'int', 'duplicate': 'int', 'normal': 'int',
+ 'normal-bytes': 'int' } }
+
+##
+# @XBZRLECacheStats
+#
+# Detailed XBZRLE migration cache statistics
+#
+# @cache-size: XBZRLE cache size
+#
+# @bytes: amount of bytes already transferred to the target VM
+#
+# @pages: amount of pages transferred to the target VM
+#
+# @cache-miss: number of cache miss
+#
+# @overflow: number of overflows
+#
+# Since: 1.2
+##
+{ 'type': 'XBZRLECacheStats',
+ 'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int',
+ 'cache-miss': 'int', 'overflow': 'int' } }
##
# @MigrationInfo
# status, only returned if status is 'active' and it is a block
# migration
#
+# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
+# migration statistics, only returned if XBZRLE feature is on and
+# status is 'active' or 'completed' (since 1.2)
+#
# Since: 0.14.0
##
{ 'type': 'MigrationInfo',
'data': {'*status': 'str', '*ram': 'MigrationStats',
- '*disk': 'MigrationStats'} }
+ '*disk': 'MigrationStats',
+ '*xbzrle-cache': 'XBZRLECacheStats'} }
##
# @query-migrate
##
{ 'command': 'query-migrate', 'returns': 'MigrationInfo' }
+##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
+# This feature allows us to minimize migration traffic for certain work
+# loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+ 'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+ 'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @migrate-set-capabilities
+#
+# Enable/Disable the following migration capabilities (like xbzrle)
+#
+# @capabilities: json array of capability modifications to make
+#
+# Since: 1.2
+##
+{ 'command': 'migrate-set-capabilities',
+ 'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
+
+##
+# @query-migrate-capabilities
+#
+# Returns information about the current migration capabilities status
+#
+# Returns: @MigrationCapabilitiesStatus
+#
+# Since: 1.2
+##
+{ 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']}
+
##
# @MouseInfo:
#
#
# @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
{ '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:
# Returns information about the current VNC server
#
# Returns: @VncInfo
- # If VNC support is not compiled in, FeatureDisabled
#
# Since: 0.14.0
##
# 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
#
# @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
#
# 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
#
# 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
#
# 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
##
#
# 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
#
# 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
##
##
{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
+##
+# @migrate-set-cache-size
+#
+# Set XBZRLE cache size
+#
+# @value: cache size in bytes
+#
+# The size will be rounded down to the nearest power of 2.
+# The cache size can be modified before and during ongoing migration
+#
+# Returns: nothing on success
+#
+# Since: 1.2
+##
+{ 'command': 'migrate-set-cache-size', 'data': {'value': 'int'} }
+
+##
+# @query-migrate-cache-size
+#
+# query XBZRLE cache size
+#
+# Returns: XBZRLE cache size in bytes
+#
+# Since: 1.2
+##
+{ 'command': 'query-migrate-cache-size', 'returns': 'int' }
+
##
# @ObjectPropertyInfo:
#
# 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' } }
# 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' },
# 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' },
# @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' },
#
# 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
##
#
# 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
#
#
# 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
#
#
# 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
#
# Returns: Nothing on success
# If @device is not a valid block device, DeviceNotFound
- # If the argument combination is invalid, InvalidParameterCombination
#
# Since: 1.1
##
# @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
##
# 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
#
# Returns: Nothing on success
# If no background operation is active on this device, DeviceNotActive
- # If cancellation already in progress, DeviceInUse
#
# Since: 1.1
##
# 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
#
# 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
##
#
# 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.
# 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
##
#
# 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': '**'},
# @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
#
# @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'] }
-> { "execute": "inject-nmi" }
<- { "return": {} }
- Note: inject-nmi is only supported for x86 guest currently, it will
- returns "Unsupported" error for non-x86 guest.
+ Note: inject-nmi fails when the guest doesn't support injecting.
+ Currently, only x86 guests do.
EQMP
-> { "execute": "migrate_cancel" }
<- { "return": {} }
+EQMP
+{
+ .name = "migrate-set-cache-size",
+ .args_type = "value:o",
+ .mhandler.cmd_new = qmp_marshal_input_migrate_set_cache_size,
+ },
+
+SQMP
+migrate-set-cache-size
+---------------------
+
+Set cache size to be used by XBZRLE migration, the cache size will be rounded
+down to the nearest power of 2
+
+Arguments:
+
+- "value": cache size in bytes (json-int)
+
+Example:
+
+-> { "execute": "migrate-set-cache-size", "arguments": { "value": 536870912 } }
+<- { "return": {} }
+
+EQMP
+ {
+ .name = "query-migrate-cache-size",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_migrate_cache_size,
+ },
+
+SQMP
+query-migrate-cache-size
+---------------------
+
+Show cache size to be used by XBZRLE migration
+
+returns a json-object with the following information:
+- "size" : json-int
+
+Example:
+
+-> { "execute": "query-migrate-cache-size" }
+<- { "return": 67108864 }
+
EQMP
{
- "transferred": amount transferred (json-int)
- "remaining": amount remaining (json-int)
- "total": total (json-int)
+ - "total-time": total amount of ms since migration started. If
+ migration has ended, it returns the total migration time
+ (json-int)
+ - "duplicate": number of duplicated pages (json-int)
+ - "normal" : number of normal pages transferred (json-int)
+ - "normal-bytes" : number of normal bytes transferred (json-int)
- "disk": only present if "status" is "active" and it is a block migration,
it is a json-object with the following disk information (in bytes):
- "transferred": amount transferred (json-int)
- "remaining": amount remaining (json-int)
- "total": total (json-int)
-
+- "xbzrle-cache": only present if XBZRLE is active.
+ It is a json-object with the following XBZRLE information:
+ - "cache-size": XBZRLE cache size
+ - "bytes": total XBZRLE bytes transferred
+ - "pages": number of XBZRLE compressed pages
+ - "cache-miss": number of cache misses
+ - "overflow": number of XBZRLE overflows
Examples:
1. Before the first migration
2. Migration is done and has succeeded
-> { "execute": "query-migrate" }
-<- { "return": { "status": "completed" } }
+<- { "return": {
+ "status": "completed",
+ "ram":{
+ "transferred":123,
+ "remaining":123,
+ "total":246,
+ "total-time":12345,
+ "duplicate":123,
+ "normal":123,
+ "normal-bytes":123456
+ }
+ }
+ }
3. Migration is done and has failed
"ram":{
"transferred":123,
"remaining":123,
- "total":246
+ "total":246,
+ "total-time":12345,
+ "duplicate":123,
+ "normal":123,
+ "normal-bytes":123456
}
}
}
"ram":{
"total":1057024,
"remaining":1053304,
- "transferred":3720
+ "transferred":3720,
+ "total-time":12345,
+ "duplicate":123,
+ "normal":123,
+ "normal-bytes":123456
},
"disk":{
"total":20971520,
}
}
+6. Migration is being performed and XBZRLE is active:
+
+-> { "execute": "query-migrate" }
+<- {
+ "return":{
+ "status":"active",
+ "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
+ "ram":{
+ "total":1057024,
+ "remaining":1053304,
+ "transferred":3720,
+ "total-time":12345,
+ "duplicate":10,
+ "normal":3333,
+ "normal-bytes":3412992
+ },
+ "xbzrle-cache":{
+ "cache-size":67108864,
+ "bytes":20971520,
+ "pages":2444343,
+ "cache-miss":2244,
+ "overflow":34434
+ }
+ }
+ }
+
EQMP
{
.mhandler.cmd_new = qmp_marshal_input_query_migrate,
},
+SQMP
+migrate-set-capabilities
+-------
+
+Enable/Disable migration capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "migrate-set-capabilities" , "arguments":
+ { "capabilities": [ { "capability": "xbzrle", "state": true } ] } }
+
+EQMP
+
+ {
+ .name = "migrate-set-capabilities",
+ .args_type = "capabilities:O",
+ .params = "capability:s,state:b",
+ .mhandler.cmd_new = qmp_marshal_input_migrate_set_capabilities,
+ },
+SQMP
+query-migrate-capabilities
+-------
+
+Query current migration capabilities
+
+- "capabilities": migration capabilities state
+ - "xbzrle" : XBZRLE state (json-bool)
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migrate-capabilities" }
+<- { "return": {
+ "capabilities" : [ { "capability" : "xbzrle", "state" : false } ]
+ }
+ }
+EQMP
+
+ {
+ .name = "query-migrate-capabilities",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_migrate_capabilities,
+ },
+
SQMP
query-balloon
-------------
.args_type = "implements:s?,abstract:b?",
.mhandler.cmd_new = qmp_marshal_input_qom_list_types,
},
+
+ {
+ .name = "device-list-properties",
+ .args_type = "typename:s",
+ .mhandler.cmd_new = qmp_marshal_input_device_list_properties,
+ },
+
+ {
+ .name = "query-machines",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_machines,
+ },
+
+ {
+ .name = "query-cpu-definitions",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_cpu_definitions,
+ },
+