diff options
Diffstat (limited to 'qapi')
53 files changed, 24588 insertions, 0 deletions
diff --git a/qapi/acpi.json b/qapi/acpi.json new file mode 100644 index 000000000..51f0d55db --- /dev/null +++ b/qapi/acpi.json @@ -0,0 +1,141 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# SPDX-License-Identifier: GPL-2.0-or-later + +## +# = ACPI +## + +## +# @AcpiTableOptions: +# +# Specify an ACPI table on the command line to load. +# +# At most one of @file and @data can be specified. The list of files specified +# by any one of them is loaded and concatenated in order. If both are omitted, +# @data is implied. +# +# Other fields / optargs can be used to override fields of the generic ACPI +# table header; refer to the ACPI specification 5.0, section 5.2.6 System +# Description Table Header. If a header field is not overridden, then the +# corresponding value from the concatenated blob is used (in case of @file), or +# it is filled in with a hard-coded value (in case of @data). +# +# String fields are copied into the matching ACPI member from lowest address +# upwards, and silently truncated / NUL-padded to length. +# +# @sig: table signature / identifier (4 bytes) +# +# @rev: table revision number (dependent on signature, 1 byte) +# +# @oem_id: OEM identifier (6 bytes) +# +# @oem_table_id: OEM table identifier (8 bytes) +# +# @oem_rev: OEM-supplied revision number (4 bytes) +# +# @asl_compiler_id: identifier of the utility that created the table +# (4 bytes) +# +# @asl_compiler_rev: revision number of the utility that created the +# table (4 bytes) +# +# @file: colon (:) separated list of pathnames to load and +# concatenate as table data. The resultant binary blob is expected to +# have an ACPI table header. At least one file is required. This field +# excludes @data. +# +# @data: colon (:) separated list of pathnames to load and +# concatenate as table data. The resultant binary blob must not have an +# ACPI table header. At least one file is required. This field excludes +# @file. +# +# Since: 1.5 +## +{ 'struct': 'AcpiTableOptions', + 'data': { + '*sig': 'str', + '*rev': 'uint8', + '*oem_id': 'str', + '*oem_table_id': 'str', + '*oem_rev': 'uint32', + '*asl_compiler_id': 'str', + '*asl_compiler_rev': 'uint32', + '*file': 'str', + '*data': 'str' }} + +## +# @ACPISlotType: +# +# @DIMM: memory slot +# @CPU: logical CPU slot (since 2.7) +## +{ 'enum': 'ACPISlotType', 'data': [ 'DIMM', 'CPU' ] } + +## +# @ACPIOSTInfo: +# +# OSPM Status Indication for a device +# For description of possible values of @source and @status fields +# see "_OST (OSPM Status Indication)" chapter of ACPI5.0 spec. +# +# @device: device ID associated with slot +# +# @slot: slot ID, unique per slot of a given @slot-type +# +# @slot-type: type of the slot +# +# @source: an integer containing the source event +# +# @status: an integer containing the status code +# +# Since: 2.1 +## +{ 'struct': 'ACPIOSTInfo', + 'data' : { '*device': 'str', + 'slot': 'str', + 'slot-type': 'ACPISlotType', + 'source': 'int', + 'status': 'int' } } + +## +# @query-acpi-ospm-status: +# +# Return a list of ACPIOSTInfo for devices that support status +# reporting via ACPI _OST method. +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "query-acpi-ospm-status" } +# <- { "return": [ { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0}, +# { "slot": "1", "slot-type": "DIMM", "source": 0, "status": 0}, +# { "slot": "2", "slot-type": "DIMM", "source": 0, "status": 0}, +# { "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0} +# ]} +# +## +{ 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] } + +## +# @ACPI_DEVICE_OST: +# +# Emitted when guest executes ACPI _OST method. +# +# @info: OSPM Status Indication +# +# Since: 2.1 +# +# Example: +# +# <- { "event": "ACPI_DEVICE_OST", +# "data": { "device": "d1", "slot": "0", +# "slot-type": "DIMM", "source": 1, "status": 0 } } +# +## +{ 'event': 'ACPI_DEVICE_OST', + 'data': { 'info': 'ACPIOSTInfo' } } diff --git a/qapi/audio.json b/qapi/audio.json new file mode 100644 index 000000000..9cba0df8a --- /dev/null +++ b/qapi/audio.json @@ -0,0 +1,421 @@ +# -*- mode: python -*- +# +# Copyright (C) 2015-2019 Zoltán Kővágó <DirtY.iCE.hu@gmail.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Audio +## + +## +# @AudiodevPerDirectionOptions: +# +# General audio backend options that are used for both playback and +# recording. +# +# @mixing-engine: use QEMU's mixing engine to mix all streams inside QEMU and +# convert audio formats when not supported by the backend. When +# set to off, fixed-settings must be also off (default on, +# since 4.2) +# +# @fixed-settings: use fixed settings for host input/output. When off, +# frequency, channels and format must not be +# specified (default true) +# +# @frequency: frequency to use when using fixed settings +# (default 44100) +# +# @channels: number of channels when using fixed settings (default 2) +# +# @voices: number of voices to use (default 1) +# +# @format: sample format to use when using fixed settings +# (default s16) +# +# @buffer-length: the buffer length in microseconds +# +# Since: 4.0 +## +{ 'struct': 'AudiodevPerDirectionOptions', + 'data': { + '*mixing-engine': 'bool', + '*fixed-settings': 'bool', + '*frequency': 'uint32', + '*channels': 'uint32', + '*voices': 'uint32', + '*format': 'AudioFormat', + '*buffer-length': 'uint32' } } + +## +# @AudiodevGenericOptions: +# +# Generic driver-specific options. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# Since: 4.0 +## +{ 'struct': 'AudiodevGenericOptions', + 'data': { + '*in': 'AudiodevPerDirectionOptions', + '*out': 'AudiodevPerDirectionOptions' } } + +## +# @AudiodevAlsaPerDirectionOptions: +# +# Options of the ALSA backend that are used for both playback and +# recording. +# +# @dev: the name of the ALSA device to use (default 'default') +# +# @period-length: the period length in microseconds +# +# @try-poll: attempt to use poll mode, falling back to non-polling +# access on failure (default true) +# +# Since: 4.0 +## +{ 'struct': 'AudiodevAlsaPerDirectionOptions', + 'base': 'AudiodevPerDirectionOptions', + 'data': { + '*dev': 'str', + '*period-length': 'uint32', + '*try-poll': 'bool' } } + +## +# @AudiodevAlsaOptions: +# +# Options of the ALSA audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @threshold: set the threshold (in microseconds) when playback starts +# +# Since: 4.0 +## +{ 'struct': 'AudiodevAlsaOptions', + 'data': { + '*in': 'AudiodevAlsaPerDirectionOptions', + '*out': 'AudiodevAlsaPerDirectionOptions', + '*threshold': 'uint32' } } + +## +# @AudiodevCoreaudioPerDirectionOptions: +# +# Options of the Core Audio backend that are used for both playback and +# recording. +# +# @buffer-count: number of buffers +# +# Since: 4.0 +## +{ 'struct': 'AudiodevCoreaudioPerDirectionOptions', + 'base': 'AudiodevPerDirectionOptions', + 'data': { + '*buffer-count': 'uint32' } } + +## +# @AudiodevCoreaudioOptions: +# +# Options of the coreaudio audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# Since: 4.0 +## +{ 'struct': 'AudiodevCoreaudioOptions', + 'data': { + '*in': 'AudiodevCoreaudioPerDirectionOptions', + '*out': 'AudiodevCoreaudioPerDirectionOptions' } } + +## +# @AudiodevDsoundOptions: +# +# Options of the DirectSound audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @latency: add extra latency to playback in microseconds +# (default 10000) +# +# Since: 4.0 +## +{ 'struct': 'AudiodevDsoundOptions', + 'data': { + '*in': 'AudiodevPerDirectionOptions', + '*out': 'AudiodevPerDirectionOptions', + '*latency': 'uint32' } } + +## +# @AudiodevJackPerDirectionOptions: +# +# Options of the JACK backend that are used for both playback and +# recording. +# +# @server-name: select from among several possible concurrent server instances +# (default: environment variable $JACK_DEFAULT_SERVER if set, else "default") +# +# @client-name: the client name to use. The server will modify this name to +# create a unique variant, if needed unless @exact-name is true (default: the +# guest's name) +# +# @connect-ports: if set, a regular expression of JACK client port name(s) to +# monitor for and automatically connect to +# +# @start-server: start a jack server process if one is not already present +# (default: false) +# +# @exact-name: use the exact name requested otherwise JACK automatically +# generates a unique one, if needed (default: false) +# +# Since: 5.1 +## +{ 'struct': 'AudiodevJackPerDirectionOptions', + 'base': 'AudiodevPerDirectionOptions', + 'data': { + '*server-name': 'str', + '*client-name': 'str', + '*connect-ports': 'str', + '*start-server': 'bool', + '*exact-name': 'bool' } } + +## +# @AudiodevJackOptions: +# +# Options of the JACK audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# Since: 5.1 +## +{ 'struct': 'AudiodevJackOptions', + 'data': { + '*in': 'AudiodevJackPerDirectionOptions', + '*out': 'AudiodevJackPerDirectionOptions' } } + +## +# @AudiodevOssPerDirectionOptions: +# +# Options of the OSS backend that are used for both playback and +# recording. +# +# @dev: file name of the OSS device (default '/dev/dsp') +# +# @buffer-count: number of buffers +# +# @try-poll: attempt to use poll mode, falling back to non-polling +# access on failure (default true) +# +# Since: 4.0 +## +{ 'struct': 'AudiodevOssPerDirectionOptions', + 'base': 'AudiodevPerDirectionOptions', + 'data': { + '*dev': 'str', + '*buffer-count': 'uint32', + '*try-poll': 'bool' } } + +## +# @AudiodevOssOptions: +# +# Options of the OSS audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @try-mmap: try using memory-mapped access, falling back to +# non-memory-mapped access on failure (default true) +# +# @exclusive: open device in exclusive mode (vmix won't work) +# (default false) +# +# @dsp-policy: set the timing policy of the device (between 0 and 10, +# where smaller number means smaller latency but higher +# CPU usage) or -1 to use fragment mode (option ignored +# on some platforms) (default 5) +# +# Since: 4.0 +## +{ 'struct': 'AudiodevOssOptions', + 'data': { + '*in': 'AudiodevOssPerDirectionOptions', + '*out': 'AudiodevOssPerDirectionOptions', + '*try-mmap': 'bool', + '*exclusive': 'bool', + '*dsp-policy': 'uint32' } } + +## +# @AudiodevPaPerDirectionOptions: +# +# Options of the Pulseaudio backend that are used for both playback and +# recording. +# +# @name: name of the sink/source to use +# +# @stream-name: name of the PulseAudio stream created by qemu. Can be +# used to identify the stream in PulseAudio when you +# create multiple PulseAudio devices or run multiple qemu +# instances (default: audiodev's id, since 4.2) +# +# @latency: latency you want PulseAudio to achieve in microseconds +# (default 15000) +# +# Since: 4.0 +## +{ 'struct': 'AudiodevPaPerDirectionOptions', + 'base': 'AudiodevPerDirectionOptions', + 'data': { + '*name': 'str', + '*stream-name': 'str', + '*latency': 'uint32' } } + +## +# @AudiodevPaOptions: +# +# Options of the PulseAudio audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @server: PulseAudio server address (default: let PulseAudio choose) +# +# Since: 4.0 +## +{ 'struct': 'AudiodevPaOptions', + 'data': { + '*in': 'AudiodevPaPerDirectionOptions', + '*out': 'AudiodevPaPerDirectionOptions', + '*server': 'str' } } + +## +# @AudiodevSdlPerDirectionOptions: +# +# Options of the SDL audio backend that are used for both playback and +# recording. +# +# @buffer-count: number of buffers (default 4) +# +# Since: 6.0 +## +{ 'struct': 'AudiodevSdlPerDirectionOptions', + 'base': 'AudiodevPerDirectionOptions', + 'data': { + '*buffer-count': 'uint32' } } + +## +# @AudiodevSdlOptions: +# +# Options of the SDL audio backend. +# +# @in: options of the recording stream +# +# @out: options of the playback stream +# +# Since: 6.0 +## +{ 'struct': 'AudiodevSdlOptions', + 'data': { + '*in': 'AudiodevSdlPerDirectionOptions', + '*out': 'AudiodevSdlPerDirectionOptions' } } + +## +# @AudiodevWavOptions: +# +# Options of the wav audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @path: name of the wav file to record (default 'qemu.wav') +# +# Since: 4.0 +## +{ 'struct': 'AudiodevWavOptions', + 'data': { + '*in': 'AudiodevPerDirectionOptions', + '*out': 'AudiodevPerDirectionOptions', + '*path': 'str' } } + + +## +# @AudioFormat: +# +# An enumeration of possible audio formats. +# +# @u8: unsigned 8 bit integer +# +# @s8: signed 8 bit integer +# +# @u16: unsigned 16 bit integer +# +# @s16: signed 16 bit integer +# +# @u32: unsigned 32 bit integer +# +# @s32: signed 32 bit integer +# +# @f32: single precision floating-point (since 5.0) +# +# Since: 4.0 +## +{ 'enum': 'AudioFormat', + 'data': [ 'u8', 's8', 'u16', 's16', 'u32', 's32', 'f32' ] } + +## +# @AudiodevDriver: +# +# An enumeration of possible audio backend drivers. +# +# @jack: JACK audio backend (since 5.1) +# +# Since: 4.0 +## +{ 'enum': 'AudiodevDriver', + 'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'jack', 'oss', 'pa', + 'sdl', 'spice', 'wav' ] } + +## +# @Audiodev: +# +# Options of an audio backend. +# +# @id: identifier of the backend +# +# @driver: the backend driver to use +# +# @timer-period: timer period (in microseconds, 0: use lowest possible) +# +# Since: 4.0 +## +{ 'union': 'Audiodev', + 'base': { + 'id': 'str', + 'driver': 'AudiodevDriver', + '*timer-period': 'uint32' }, + 'discriminator': 'driver', + 'data': { + 'none': 'AudiodevGenericOptions', + 'alsa': 'AudiodevAlsaOptions', + 'coreaudio': 'AudiodevCoreaudioOptions', + 'dsound': 'AudiodevDsoundOptions', + 'jack': 'AudiodevJackOptions', + 'oss': 'AudiodevOssOptions', + 'pa': 'AudiodevPaOptions', + 'sdl': 'AudiodevSdlOptions', + 'spice': 'AudiodevGenericOptions', + 'wav': 'AudiodevWavOptions' } } diff --git a/qapi/authz.json b/qapi/authz.json new file mode 100644 index 000000000..51845e37c --- /dev/null +++ b/qapi/authz.json @@ -0,0 +1,112 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# = User authorization +## + +## +# @QAuthZListPolicy: +# +# The authorization policy result +# +# @deny: deny access +# @allow: allow access +# +# Since: 4.0 +## +{ 'enum': 'QAuthZListPolicy', + 'prefix': 'QAUTHZ_LIST_POLICY', + 'data': ['deny', 'allow']} + +## +# @QAuthZListFormat: +# +# The authorization policy match format +# +# @exact: an exact string match +# @glob: string with ? and * shell wildcard support +# +# Since: 4.0 +## +{ 'enum': 'QAuthZListFormat', + 'prefix': 'QAUTHZ_LIST_FORMAT', + 'data': ['exact', 'glob']} + +## +# @QAuthZListRule: +# +# A single authorization rule. +# +# @match: a string or glob to match against a user identity +# @policy: the result to return if @match evaluates to true +# @format: the format of the @match rule (default 'exact') +# +# Since: 4.0 +## +{ 'struct': 'QAuthZListRule', + 'data': {'match': 'str', + 'policy': 'QAuthZListPolicy', + '*format': 'QAuthZListFormat'}} + +## +# @AuthZListProperties: +# +# Properties for authz-list objects. +# +# @policy: Default policy to apply when no rule matches (default: deny) +# +# @rules: Authorization rules based on matching user +# +# Since: 4.0 +## +{ 'struct': 'AuthZListProperties', + 'data': { '*policy': 'QAuthZListPolicy', + '*rules': ['QAuthZListRule'] } } + +## +# @AuthZListFileProperties: +# +# Properties for authz-listfile objects. +# +# @filename: File name to load the configuration from. The file must +# contain valid JSON for AuthZListProperties. +# +# @refresh: If true, inotify is used to monitor the file, automatically +# reloading changes. If an error occurs during reloading, all +# authorizations will fail until the file is next successfully +# loaded. (default: true if the binary was built with +# CONFIG_INOTIFY1, false otherwise) +# +# Since: 4.0 +## +{ 'struct': 'AuthZListFileProperties', + 'data': { 'filename': 'str', + '*refresh': 'bool' } } + +## +# @AuthZPAMProperties: +# +# Properties for authz-pam objects. +# +# @service: PAM service name to use for authorization +# +# Since: 4.0 +## +{ 'struct': 'AuthZPAMProperties', + 'data': { 'service': 'str' } } + +## +# @AuthZSimpleProperties: +# +# Properties for authz-simple objects. +# +# @identity: Identifies the allowed user. Its format depends on the network +# service that authorization object is associated with. For +# authorizing based on TLS x509 certificates, the identity must be +# the x509 distinguished name. +# +# Since: 4.0 +## +{ 'struct': 'AuthZSimpleProperties', + 'data': { 'identity': 'str' } } diff --git a/qapi/block-core.json b/qapi/block-core.json new file mode 100644 index 000000000..1d3dd9cb4 --- /dev/null +++ b/qapi/block-core.json @@ -0,0 +1,5572 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# == Block core (VM unrelated) +## + +{ 'include': 'common.json' } +{ 'include': 'crypto.json' } +{ 'include': 'job.json' } +{ 'include': 'sockets.json' } + +## +# @SnapshotInfo: +# +# @id: unique snapshot id +# +# @name: user chosen name +# +# @vm-state-size: size of the VM state +# +# @date-sec: UTC date of the snapshot in seconds +# +# @date-nsec: fractional part in nano seconds to be used with date-sec +# +# @vm-clock-sec: VM clock relative to boot in seconds +# +# @vm-clock-nsec: fractional part in nano seconds to be used with vm-clock-sec +# +# @icount: Current instruction count. Appears when execution record/replay +# is enabled. Used for "time-traveling" to match the moment +# in the recorded execution with the snapshots. This counter may +# be obtained through @query-replay command (since 5.2) +# +# Since: 1.3 +# +## +{ 'struct': 'SnapshotInfo', + 'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int', + 'date-sec': 'int', 'date-nsec': 'int', + 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int', + '*icount': 'int' } } + +## +# @ImageInfoSpecificQCow2EncryptionBase: +# +# @format: The encryption format +# +# Since: 2.10 +## +{ 'struct': 'ImageInfoSpecificQCow2EncryptionBase', + 'data': { 'format': 'BlockdevQcow2EncryptionFormat'}} + +## +# @ImageInfoSpecificQCow2Encryption: +# +# Since: 2.10 +## +{ 'union': 'ImageInfoSpecificQCow2Encryption', + 'base': 'ImageInfoSpecificQCow2EncryptionBase', + 'discriminator': 'format', + 'data': { 'luks': 'QCryptoBlockInfoLUKS' } } + +## +# @ImageInfoSpecificQCow2: +# +# @compat: compatibility level +# +# @data-file: the filename of the external data file that is stored in the +# image and used as a default for opening the image (since: 4.0) +# +# @data-file-raw: True if the external data file must stay valid as a +# standalone (read-only) raw image without looking at qcow2 +# metadata (since: 4.0) +# +# @extended-l2: true if the image has extended L2 entries; only valid for +# compat >= 1.1 (since 5.2) +# +# @lazy-refcounts: on or off; only valid for compat >= 1.1 +# +# @corrupt: true if the image has been marked corrupt; only valid for +# compat >= 1.1 (since 2.2) +# +# @refcount-bits: width of a refcount entry in bits (since 2.3) +# +# @encrypt: details about encryption parameters; only set if image +# is encrypted (since 2.10) +# +# @bitmaps: A list of qcow2 bitmap details (since 4.0) +# +# @compression-type: the image cluster compression method (since 5.1) +# +# Since: 1.7 +## +{ 'struct': 'ImageInfoSpecificQCow2', + 'data': { + 'compat': 'str', + '*data-file': 'str', + '*data-file-raw': 'bool', + '*extended-l2': 'bool', + '*lazy-refcounts': 'bool', + '*corrupt': 'bool', + 'refcount-bits': 'int', + '*encrypt': 'ImageInfoSpecificQCow2Encryption', + '*bitmaps': ['Qcow2BitmapInfo'], + 'compression-type': 'Qcow2CompressionType' + } } + +## +# @ImageInfoSpecificVmdk: +# +# @create-type: The create type of VMDK image +# +# @cid: Content id of image +# +# @parent-cid: Parent VMDK image's cid +# +# @extents: List of extent files +# +# Since: 1.7 +## +{ 'struct': 'ImageInfoSpecificVmdk', + 'data': { + 'create-type': 'str', + 'cid': 'int', + 'parent-cid': 'int', + 'extents': ['ImageInfo'] + } } + +## +# @ImageInfoSpecificRbd: +# +# @encryption-format: Image encryption format +# +# Since: 6.1 +## +{ 'struct': 'ImageInfoSpecificRbd', + 'data': { + '*encryption-format': 'RbdImageEncryptionFormat' + } } + +## +# @ImageInfoSpecificKind: +# +# @luks: Since 2.7 +# @rbd: Since 6.1 +# +# Since: 1.7 +## +{ 'enum': 'ImageInfoSpecificKind', + 'data': [ 'qcow2', 'vmdk', 'luks', 'rbd' ] } + +## +# @ImageInfoSpecificQCow2Wrapper: +# +# Since: 1.7 +## +{ 'struct': 'ImageInfoSpecificQCow2Wrapper', + 'data': { 'data': 'ImageInfoSpecificQCow2' } } + +## +# @ImageInfoSpecificVmdkWrapper: +# +# Since: 6.1 +## +{ 'struct': 'ImageInfoSpecificVmdkWrapper', + 'data': { 'data': 'ImageInfoSpecificVmdk' } } + +## +# @ImageInfoSpecificLUKSWrapper: +# +# Since: 2.7 +## +{ 'struct': 'ImageInfoSpecificLUKSWrapper', + 'data': { 'data': 'QCryptoBlockInfoLUKS' } } +# If we need to add block driver specific parameters for +# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS +# to define a ImageInfoSpecificLUKS + +## +# @ImageInfoSpecificRbdWrapper: +# +# Since: 6.1 +## +{ 'struct': 'ImageInfoSpecificRbdWrapper', + 'data': { 'data': 'ImageInfoSpecificRbd' } } + +## +# @ImageInfoSpecific: +# +# A discriminated record of image format specific information structures. +# +# Since: 1.7 +## +{ 'union': 'ImageInfoSpecific', + 'base': { 'type': 'ImageInfoSpecificKind' }, + 'discriminator': 'type', + 'data': { + 'qcow2': 'ImageInfoSpecificQCow2Wrapper', + 'vmdk': 'ImageInfoSpecificVmdkWrapper', + 'luks': 'ImageInfoSpecificLUKSWrapper', + 'rbd': 'ImageInfoSpecificRbdWrapper' + } } + +## +# @ImageInfo: +# +# Information about a QEMU image file +# +# @filename: name of the image file +# +# @format: format of the image file +# +# @virtual-size: maximum capacity in bytes of the image +# +# @actual-size: actual size on disk in bytes of the image +# +# @dirty-flag: true if image is not cleanly closed +# +# @cluster-size: size of a cluster in bytes +# +# @encrypted: true if the image is encrypted +# +# @compressed: true if the image is compressed (Since 1.7) +# +# @backing-filename: name of the backing file +# +# @full-backing-filename: full path of the backing file +# +# @backing-filename-format: the format of the backing file +# +# @snapshots: list of VM snapshots +# +# @backing-image: info of the backing image (since 1.6) +# +# @format-specific: structure supplying additional format-specific +# information (since 1.7) +# +# Since: 1.3 +# +## +{ 'struct': 'ImageInfo', + 'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool', + '*actual-size': 'int', 'virtual-size': 'int', + '*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool', + '*backing-filename': 'str', '*full-backing-filename': 'str', + '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'], + '*backing-image': 'ImageInfo', + '*format-specific': 'ImageInfoSpecific' } } + +## +# @ImageCheck: +# +# Information about a QEMU image file check +# +# @filename: name of the image file checked +# +# @format: format of the image file checked +# +# @check-errors: number of unexpected errors occurred during check +# +# @image-end-offset: offset (in bytes) where the image ends, this +# field is present if the driver for the image format +# supports it +# +# @corruptions: number of corruptions found during the check if any +# +# @leaks: number of leaks found during the check if any +# +# @corruptions-fixed: number of corruptions fixed during the check +# if any +# +# @leaks-fixed: number of leaks fixed during the check if any +# +# @total-clusters: total number of clusters, this field is present +# if the driver for the image format supports it +# +# @allocated-clusters: total number of allocated clusters, this +# field is present if the driver for the image format +# supports it +# +# @fragmented-clusters: total number of fragmented clusters, this +# field is present if the driver for the image format +# supports it +# +# @compressed-clusters: total number of compressed clusters, this +# field is present if the driver for the image format +# supports it +# +# Since: 1.4 +# +## +{ 'struct': 'ImageCheck', + 'data': {'filename': 'str', 'format': 'str', 'check-errors': 'int', + '*image-end-offset': 'int', '*corruptions': 'int', '*leaks': 'int', + '*corruptions-fixed': 'int', '*leaks-fixed': 'int', + '*total-clusters': 'int', '*allocated-clusters': 'int', + '*fragmented-clusters': 'int', '*compressed-clusters': 'int' } } + +## +# @MapEntry: +# +# Mapping information from a virtual block range to a host file range +# +# @start: virtual (guest) offset of the first byte described by this +# entry +# +# @length: the number of bytes of the mapped virtual range +# +# @data: reading the image will actually read data from a file (in +# particular, if @offset is present this means that the sectors +# are not simply preallocated, but contain actual data in raw +# format) +# +# @zero: whether the virtual blocks read as zeroes +# +# @depth: number of layers (0 = top image, 1 = top image's backing +# file, ..., n - 1 = bottom image (where n is the number of +# images in the chain)) before reaching one for which the +# range is allocated +# +# @present: true if this layer provides the data, false if adding a backing +# layer could impact this region (since 6.1) +# +# @offset: if present, the image file stores the data for this range +# in raw format at the given (host) offset +# +# @filename: filename that is referred to by @offset +# +# Since: 2.6 +# +## +{ 'struct': 'MapEntry', + 'data': {'start': 'int', 'length': 'int', 'data': 'bool', + 'zero': 'bool', 'depth': 'int', 'present': 'bool', + '*offset': 'int', '*filename': 'str' } } + +## +# @BlockdevCacheInfo: +# +# Cache mode information for a block device +# +# @writeback: true if writeback mode is enabled +# @direct: true if the host page cache is bypassed (O_DIRECT) +# @no-flush: true if flush requests are ignored for the device +# +# Since: 2.3 +## +{ 'struct': 'BlockdevCacheInfo', + 'data': { 'writeback': 'bool', + 'direct': 'bool', + 'no-flush': 'bool' } } + +## +# @BlockDeviceInfo: +# +# Information about the backing device for a block device. +# +# @file: the filename of the backing device +# +# @node-name: the name of the block driver node (Since 2.0) +# +# @ro: true if the backing device was open read-only +# +# @drv: the name of the block format used to open the backing device. As of +# 0.14 this can be: 'blkdebug', 'bochs', 'cloop', 'cow', 'dmg', +# 'file', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device', +# 'http', 'https', 'luks', 'nbd', 'parallels', 'qcow', +# 'qcow2', 'raw', 'vdi', 'vmdk', 'vpc', 'vvfat' +# 2.2: 'archipelago' added, 'cow' dropped +# 2.3: 'host_floppy' deprecated +# 2.5: 'host_floppy' dropped +# 2.6: 'luks' added +# 2.8: 'replication' added, 'tftp' dropped +# 2.9: 'archipelago' dropped +# +# @backing_file: the name of the backing file (for copy-on-write) +# +# @backing_file_depth: number of files in the backing file chain (since: 1.2) +# +# @encrypted: true if the backing device is encrypted +# +# @detect_zeroes: detect and optimize zero writes (Since 2.1) +# +# @bps: total throughput limit in bytes per second is specified +# +# @bps_rd: read throughput limit in bytes per second is specified +# +# @bps_wr: write throughput limit in bytes per second is specified +# +# @iops: total I/O operations per second is specified +# +# @iops_rd: read I/O operations per second is specified +# +# @iops_wr: write I/O operations per second is specified +# +# @image: the info of image used (since: 1.6) +# +# @bps_max: total throughput limit during bursts, +# in bytes (Since 1.7) +# +# @bps_rd_max: read throughput limit during bursts, +# in bytes (Since 1.7) +# +# @bps_wr_max: write throughput limit during bursts, +# in bytes (Since 1.7) +# +# @iops_max: total I/O operations per second during bursts, +# in bytes (Since 1.7) +# +# @iops_rd_max: read I/O operations per second during bursts, +# in bytes (Since 1.7) +# +# @iops_wr_max: write I/O operations per second during bursts, +# in bytes (Since 1.7) +# +# @bps_max_length: maximum length of the @bps_max burst +# period, in seconds. (Since 2.6) +# +# @bps_rd_max_length: maximum length of the @bps_rd_max +# burst period, in seconds. (Since 2.6) +# +# @bps_wr_max_length: maximum length of the @bps_wr_max +# burst period, in seconds. (Since 2.6) +# +# @iops_max_length: maximum length of the @iops burst +# period, in seconds. (Since 2.6) +# +# @iops_rd_max_length: maximum length of the @iops_rd_max +# burst period, in seconds. (Since 2.6) +# +# @iops_wr_max_length: maximum length of the @iops_wr_max +# burst period, in seconds. (Since 2.6) +# +# @iops_size: an I/O size in bytes (Since 1.7) +# +# @group: throttle group name (Since 2.4) +# +# @cache: the cache mode used for the block device (since: 2.3) +# +# @write_threshold: configured write threshold for the device. +# 0 if disabled. (Since 2.3) +# +# @dirty-bitmaps: dirty bitmaps information (only present if node +# has one or more dirty bitmaps) (Since 4.2) +# +# Since: 0.14 +# +## +{ 'struct': 'BlockDeviceInfo', + 'data': { 'file': 'str', '*node-name': 'str', 'ro': 'bool', 'drv': 'str', + '*backing_file': 'str', 'backing_file_depth': 'int', + 'encrypted': 'bool', + 'detect_zeroes': 'BlockdevDetectZeroesOptions', + 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', + 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int', + 'image': 'ImageInfo', + '*bps_max': 'int', '*bps_rd_max': 'int', + '*bps_wr_max': 'int', '*iops_max': 'int', + '*iops_rd_max': 'int', '*iops_wr_max': 'int', + '*bps_max_length': 'int', '*bps_rd_max_length': 'int', + '*bps_wr_max_length': 'int', '*iops_max_length': 'int', + '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int', + '*iops_size': 'int', '*group': 'str', 'cache': 'BlockdevCacheInfo', + 'write_threshold': 'int', '*dirty-bitmaps': ['BlockDirtyInfo'] } } + +## +# @BlockDeviceIoStatus: +# +# An enumeration of block device I/O status. +# +# @ok: The last I/O operation has succeeded +# +# @failed: The last I/O operation has failed +# +# @nospace: The last I/O operation has failed due to a no-space condition +# +# Since: 1.0 +## +{ 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] } + +## +# @BlockDirtyInfo: +# +# Block dirty bitmap information. +# +# @name: the name of the dirty bitmap (Since 2.4) +# +# @count: number of dirty bytes according to the dirty bitmap +# +# @granularity: granularity of the dirty bitmap in bytes (since 1.4) +# +# @recording: true if the bitmap is recording new writes from the guest. +# Replaces ``active`` and ``disabled`` statuses. (since 4.0) +# +# @busy: true if the bitmap is in-use by some operation (NBD or jobs) +# and cannot be modified via QMP or used by another operation. +# Replaces ``locked`` and ``frozen`` statuses. (since 4.0) +# +# @persistent: true if the bitmap was stored on disk, is scheduled to be stored +# on disk, or both. (since 4.0) +# +# @inconsistent: true if this is a persistent bitmap that was improperly +# stored. Implies @persistent to be true; @recording and +# @busy to be false. This bitmap cannot be used. To remove +# it, use @block-dirty-bitmap-remove. (Since 4.0) +# +# Since: 1.3 +## +{ 'struct': 'BlockDirtyInfo', + 'data': {'*name': 'str', 'count': 'int', 'granularity': 'uint32', + 'recording': 'bool', 'busy': 'bool', + 'persistent': 'bool', '*inconsistent': 'bool' } } + +## +# @Qcow2BitmapInfoFlags: +# +# An enumeration of flags that a bitmap can report to the user. +# +# @in-use: This flag is set by any process actively modifying the qcow2 file, +# and cleared when the updated bitmap is flushed to the qcow2 image. +# The presence of this flag in an offline image means that the bitmap +# was not saved correctly after its last usage, and may contain +# inconsistent data. +# +# @auto: The bitmap must reflect all changes of the virtual disk by any +# application that would write to this qcow2 file. +# +# Since: 4.0 +## +{ 'enum': 'Qcow2BitmapInfoFlags', + 'data': ['in-use', 'auto'] } + +## +# @Qcow2BitmapInfo: +# +# Qcow2 bitmap information. +# +# @name: the name of the bitmap +# +# @granularity: granularity of the bitmap in bytes +# +# @flags: flags of the bitmap +# +# Since: 4.0 +## +{ 'struct': 'Qcow2BitmapInfo', + 'data': {'name': 'str', 'granularity': 'uint32', + 'flags': ['Qcow2BitmapInfoFlags'] } } + +## +# @BlockLatencyHistogramInfo: +# +# Block latency histogram. +# +# @boundaries: list of interval boundary values in nanoseconds, all greater +# than zero and in ascending order. +# For example, the list [10, 50, 100] produces the following +# histogram intervals: [0, 10), [10, 50), [50, 100), [100, +inf). +# +# @bins: list of io request counts corresponding to histogram intervals. +# len(@bins) = len(@boundaries) + 1 +# For the example above, @bins may be something like [3, 1, 5, 2], +# and corresponding histogram looks like: +# +# :: +# +# 5| * +# 4| * +# 3| * * +# 2| * * * +# 1| * * * * +# +------------------ +# 10 50 100 +# +# Since: 4.0 +## +{ 'struct': 'BlockLatencyHistogramInfo', + 'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } } + +## +# @BlockInfo: +# +# Block device information. This structure describes a virtual device and +# the backing device associated with it. +# +# @device: The device name associated with the virtual device. +# +# @qdev: The qdev ID, or if no ID is assigned, the QOM path of the block +# device. (since 2.10) +# +# @type: This field is returned only for compatibility reasons, it should +# not be used (always returns 'unknown') +# +# @removable: True if the device supports removable media. +# +# @locked: True if the guest has locked this device from having its media +# removed +# +# @tray_open: True if the device's tray is open +# (only present if it has a tray) +# +# @io-status: @BlockDeviceIoStatus. Only present if the device +# supports it and the VM is configured to stop on errors +# (supported device models: virtio-blk, IDE, SCSI except +# scsi-generic) +# +# @inserted: @BlockDeviceInfo describing the device if media is +# present +# +# Since: 0.14 +## +{ 'struct': 'BlockInfo', + 'data': {'device': 'str', '*qdev': 'str', 'type': 'str', 'removable': 'bool', + 'locked': 'bool', '*inserted': 'BlockDeviceInfo', + '*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus' } } + +## +# @BlockMeasureInfo: +# +# Image file size calculation information. This structure describes the size +# requirements for creating a new image file. +# +# The size requirements depend on the new image file format. File size always +# equals virtual disk size for the 'raw' format, even for sparse POSIX files. +# Compact formats such as 'qcow2' represent unallocated and zero regions +# efficiently so file size may be smaller than virtual disk size. +# +# The values are upper bounds that are guaranteed to fit the new image file. +# Subsequent modification, such as internal snapshot or further bitmap +# creation, may require additional space and is not covered here. +# +# @required: Size required for a new image file, in bytes, when copying just +# allocated guest-visible contents. +# +# @fully-allocated: Image file size, in bytes, once data has been written +# to all sectors, when copying just guest-visible contents. +# +# @bitmaps: Additional size required if all the top-level bitmap metadata +# in the source image were to be copied to the destination, +# present only when source and destination both support +# persistent bitmaps. (since 5.1) +# +# Since: 2.10 +## +{ 'struct': 'BlockMeasureInfo', + 'data': {'required': 'int', 'fully-allocated': 'int', '*bitmaps': 'int'} } + +## +# @query-block: +# +# Get a list of BlockInfo for all virtual block devices. +# +# Returns: a list of @BlockInfo describing each virtual block device. Filter +# nodes that were created implicitly are skipped over. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-block" } +# <- { +# "return":[ +# { +# "io-status": "ok", +# "device":"ide0-hd0", +# "locked":false, +# "removable":false, +# "inserted":{ +# "ro":false, +# "drv":"qcow2", +# "encrypted":false, +# "file":"disks/test.qcow2", +# "backing_file_depth":1, +# "bps":1000000, +# "bps_rd":0, +# "bps_wr":0, +# "iops":1000000, +# "iops_rd":0, +# "iops_wr":0, +# "bps_max": 8000000, +# "bps_rd_max": 0, +# "bps_wr_max": 0, +# "iops_max": 0, +# "iops_rd_max": 0, +# "iops_wr_max": 0, +# "iops_size": 0, +# "detect_zeroes": "on", +# "write_threshold": 0, +# "image":{ +# "filename":"disks/test.qcow2", +# "format":"qcow2", +# "virtual-size":2048000, +# "backing_file":"base.qcow2", +# "full-backing-filename":"disks/base.qcow2", +# "backing-filename-format":"qcow2", +# "snapshots":[ +# { +# "id": "1", +# "name": "snapshot1", +# "vm-state-size": 0, +# "date-sec": 10000200, +# "date-nsec": 12, +# "vm-clock-sec": 206, +# "vm-clock-nsec": 30 +# } +# ], +# "backing-image":{ +# "filename":"disks/base.qcow2", +# "format":"qcow2", +# "virtual-size":2048000 +# } +# } +# }, +# "qdev": "ide_disk", +# "type":"unknown" +# }, +# { +# "io-status": "ok", +# "device":"ide1-cd0", +# "locked":false, +# "removable":true, +# "qdev": "/machine/unattached/device[23]", +# "tray_open": false, +# "type":"unknown" +# }, +# { +# "device":"floppy0", +# "locked":false, +# "removable":true, +# "qdev": "/machine/unattached/device[20]", +# "type":"unknown" +# }, +# { +# "device":"sd0", +# "locked":false, +# "removable":true, +# "type":"unknown" +# } +# ] +# } +# +## +{ 'command': 'query-block', 'returns': ['BlockInfo'] } + + +## +# @BlockDeviceTimedStats: +# +# Statistics of a block device during a given interval of time. +# +# @interval_length: Interval used for calculating the statistics, +# in seconds. +# +# @min_rd_latency_ns: Minimum latency of read operations in the +# defined interval, in nanoseconds. +# +# @min_wr_latency_ns: Minimum latency of write operations in the +# defined interval, in nanoseconds. +# +# @min_flush_latency_ns: Minimum latency of flush operations in the +# defined interval, in nanoseconds. +# +# @max_rd_latency_ns: Maximum latency of read operations in the +# defined interval, in nanoseconds. +# +# @max_wr_latency_ns: Maximum latency of write operations in the +# defined interval, in nanoseconds. +# +# @max_flush_latency_ns: Maximum latency of flush operations in the +# defined interval, in nanoseconds. +# +# @avg_rd_latency_ns: Average latency of read operations in the +# defined interval, in nanoseconds. +# +# @avg_wr_latency_ns: Average latency of write operations in the +# defined interval, in nanoseconds. +# +# @avg_flush_latency_ns: Average latency of flush operations in the +# defined interval, in nanoseconds. +# +# @avg_rd_queue_depth: Average number of pending read operations +# in the defined interval. +# +# @avg_wr_queue_depth: Average number of pending write operations +# in the defined interval. +# +# Since: 2.5 +## +{ 'struct': 'BlockDeviceTimedStats', + 'data': { 'interval_length': 'int', 'min_rd_latency_ns': 'int', + 'max_rd_latency_ns': 'int', 'avg_rd_latency_ns': 'int', + 'min_wr_latency_ns': 'int', 'max_wr_latency_ns': 'int', + 'avg_wr_latency_ns': 'int', 'min_flush_latency_ns': 'int', + 'max_flush_latency_ns': 'int', 'avg_flush_latency_ns': 'int', + 'avg_rd_queue_depth': 'number', 'avg_wr_queue_depth': 'number' } } + +## +# @BlockDeviceStats: +# +# Statistics of a virtual block device or a block backing device. +# +# @rd_bytes: The number of bytes read by the device. +# +# @wr_bytes: The number of bytes written by the device. +# +# @unmap_bytes: The number of bytes unmapped by the device (Since 4.2) +# +# @rd_operations: The number of read operations performed by the device. +# +# @wr_operations: The number of write operations performed by the device. +# +# @flush_operations: The number of cache flush operations performed by the +# device (since 0.15) +# +# @unmap_operations: The number of unmap operations performed by the device +# (Since 4.2) +# +# @rd_total_time_ns: Total time spent on reads in nanoseconds (since 0.15). +# +# @wr_total_time_ns: Total time spent on writes in nanoseconds (since 0.15). +# +# @flush_total_time_ns: Total time spent on cache flushes in nanoseconds +# (since 0.15). +# +# @unmap_total_time_ns: Total time spent on unmap operations in nanoseconds +# (Since 4.2) +# +# @wr_highest_offset: The offset after the greatest byte written to the +# device. The intended use of this information is for +# growable sparse files (like qcow2) that are used on top +# of a physical device. +# +# @rd_merged: Number of read requests that have been merged into another +# request (Since 2.3). +# +# @wr_merged: Number of write requests that have been merged into another +# request (Since 2.3). +# +# @unmap_merged: Number of unmap requests that have been merged into another +# request (Since 4.2) +# +# @idle_time_ns: Time since the last I/O operation, in +# nanoseconds. If the field is absent it means that +# there haven't been any operations yet (Since 2.5). +# +# @failed_rd_operations: The number of failed read operations +# performed by the device (Since 2.5) +# +# @failed_wr_operations: The number of failed write operations +# performed by the device (Since 2.5) +# +# @failed_flush_operations: The number of failed flush operations +# performed by the device (Since 2.5) +# +# @failed_unmap_operations: The number of failed unmap operations performed +# by the device (Since 4.2) +# +# @invalid_rd_operations: The number of invalid read operations +# performed by the device (Since 2.5) +# +# @invalid_wr_operations: The number of invalid write operations +# performed by the device (Since 2.5) +# +# @invalid_flush_operations: The number of invalid flush operations +# performed by the device (Since 2.5) +# +# @invalid_unmap_operations: The number of invalid unmap operations performed +# by the device (Since 4.2) +# +# @account_invalid: Whether invalid operations are included in the +# last access statistics (Since 2.5) +# +# @account_failed: Whether failed operations are included in the +# latency and last access statistics (Since 2.5) +# +# @timed_stats: Statistics specific to the set of previously defined +# intervals of time (Since 2.5) +# +# @rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0) +# +# @wr_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0) +# +# @flush_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0) +# +# Since: 0.14 +## +{ 'struct': 'BlockDeviceStats', + 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'unmap_bytes' : 'int', + 'rd_operations': 'int', 'wr_operations': 'int', + 'flush_operations': 'int', 'unmap_operations': 'int', + 'rd_total_time_ns': 'int', 'wr_total_time_ns': 'int', + 'flush_total_time_ns': 'int', 'unmap_total_time_ns': 'int', + 'wr_highest_offset': 'int', + 'rd_merged': 'int', 'wr_merged': 'int', 'unmap_merged': 'int', + '*idle_time_ns': 'int', + 'failed_rd_operations': 'int', 'failed_wr_operations': 'int', + 'failed_flush_operations': 'int', 'failed_unmap_operations': 'int', + 'invalid_rd_operations': 'int', 'invalid_wr_operations': 'int', + 'invalid_flush_operations': 'int', 'invalid_unmap_operations': 'int', + 'account_invalid': 'bool', 'account_failed': 'bool', + 'timed_stats': ['BlockDeviceTimedStats'], + '*rd_latency_histogram': 'BlockLatencyHistogramInfo', + '*wr_latency_histogram': 'BlockLatencyHistogramInfo', + '*flush_latency_histogram': 'BlockLatencyHistogramInfo' } } + +## +# @BlockStatsSpecificFile: +# +# File driver statistics +# +# @discard-nb-ok: The number of successful discard operations performed by +# the driver. +# +# @discard-nb-failed: The number of failed discard operations performed by +# the driver. +# +# @discard-bytes-ok: The number of bytes discarded by the driver. +# +# Since: 4.2 +## +{ 'struct': 'BlockStatsSpecificFile', + 'data': { + 'discard-nb-ok': 'uint64', + 'discard-nb-failed': 'uint64', + 'discard-bytes-ok': 'uint64' } } + +## +# @BlockStatsSpecificNvme: +# +# NVMe driver statistics +# +# @completion-errors: The number of completion errors. +# +# @aligned-accesses: The number of aligned accesses performed by +# the driver. +# +# @unaligned-accesses: The number of unaligned accesses performed by +# the driver. +# +# Since: 5.2 +## +{ 'struct': 'BlockStatsSpecificNvme', + 'data': { + 'completion-errors': 'uint64', + 'aligned-accesses': 'uint64', + 'unaligned-accesses': 'uint64' } } + +## +# @BlockStatsSpecific: +# +# Block driver specific statistics +# +# Since: 4.2 +## +{ 'union': 'BlockStatsSpecific', + 'base': { 'driver': 'BlockdevDriver' }, + 'discriminator': 'driver', + 'data': { + 'file': 'BlockStatsSpecificFile', + 'host_device': { 'type': 'BlockStatsSpecificFile', + 'if': 'HAVE_HOST_BLOCK_DEVICE' }, + 'nvme': 'BlockStatsSpecificNvme' } } + +## +# @BlockStats: +# +# Statistics of a virtual block device or a block backing device. +# +# @device: If the stats are for a virtual block device, the name +# corresponding to the virtual block device. +# +# @node-name: The node name of the device. (Since 2.3) +# +# @qdev: The qdev ID, or if no ID is assigned, the QOM path of the block +# device. (since 3.0) +# +# @stats: A @BlockDeviceStats for the device. +# +# @driver-specific: Optional driver-specific stats. (Since 4.2) +# +# @parent: This describes the file block device if it has one. +# Contains recursively the statistics of the underlying +# protocol (e.g. the host file for a qcow2 image). If there is +# no underlying protocol, this field is omitted +# +# @backing: This describes the backing block device if it has one. +# (Since 2.0) +# +# Since: 0.14 +## +{ 'struct': 'BlockStats', + 'data': {'*device': 'str', '*qdev': 'str', '*node-name': 'str', + 'stats': 'BlockDeviceStats', + '*driver-specific': 'BlockStatsSpecific', + '*parent': 'BlockStats', + '*backing': 'BlockStats'} } + +## +# @query-blockstats: +# +# Query the @BlockStats for all virtual block devices. +# +# @query-nodes: If true, the command will query all the block nodes +# that have a node name, in a list which will include "parent" +# information, but not "backing". +# If false or omitted, the behavior is as before - query all the +# device backends, recursively including their "parent" and +# "backing". Filter nodes that were created implicitly are +# skipped over in this mode. (Since 2.3) +# +# Returns: A list of @BlockStats for each virtual block devices. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-blockstats" } +# <- { +# "return":[ +# { +# "device":"ide0-hd0", +# "parent":{ +# "stats":{ +# "wr_highest_offset":3686448128, +# "wr_bytes":9786368, +# "wr_operations":751, +# "rd_bytes":122567168, +# "rd_operations":36772 +# "wr_total_times_ns":313253456 +# "rd_total_times_ns":3465673657 +# "flush_total_times_ns":49653 +# "flush_operations":61, +# "rd_merged":0, +# "wr_merged":0, +# "idle_time_ns":2953431879, +# "account_invalid":true, +# "account_failed":false +# } +# }, +# "stats":{ +# "wr_highest_offset":2821110784, +# "wr_bytes":9786368, +# "wr_operations":692, +# "rd_bytes":122739200, +# "rd_operations":36604 +# "flush_operations":51, +# "wr_total_times_ns":313253456 +# "rd_total_times_ns":3465673657 +# "flush_total_times_ns":49653, +# "rd_merged":0, +# "wr_merged":0, +# "idle_time_ns":2953431879, +# "account_invalid":true, +# "account_failed":false +# }, +# "qdev": "/machine/unattached/device[23]" +# }, +# { +# "device":"ide1-cd0", +# "stats":{ +# "wr_highest_offset":0, +# "wr_bytes":0, +# "wr_operations":0, +# "rd_bytes":0, +# "rd_operations":0 +# "flush_operations":0, +# "wr_total_times_ns":0 +# "rd_total_times_ns":0 +# "flush_total_times_ns":0, +# "rd_merged":0, +# "wr_merged":0, +# "account_invalid":false, +# "account_failed":false +# }, +# "qdev": "/machine/unattached/device[24]" +# }, +# { +# "device":"floppy0", +# "stats":{ +# "wr_highest_offset":0, +# "wr_bytes":0, +# "wr_operations":0, +# "rd_bytes":0, +# "rd_operations":0 +# "flush_operations":0, +# "wr_total_times_ns":0 +# "rd_total_times_ns":0 +# "flush_total_times_ns":0, +# "rd_merged":0, +# "wr_merged":0, +# "account_invalid":false, +# "account_failed":false +# }, +# "qdev": "/machine/unattached/device[16]" +# }, +# { +# "device":"sd0", +# "stats":{ +# "wr_highest_offset":0, +# "wr_bytes":0, +# "wr_operations":0, +# "rd_bytes":0, +# "rd_operations":0 +# "flush_operations":0, +# "wr_total_times_ns":0 +# "rd_total_times_ns":0 +# "flush_total_times_ns":0, +# "rd_merged":0, +# "wr_merged":0, +# "account_invalid":false, +# "account_failed":false +# } +# } +# ] +# } +# +## +{ 'command': 'query-blockstats', + 'data': { '*query-nodes': 'bool' }, + 'returns': ['BlockStats'] } + +## +# @BlockdevOnError: +# +# An enumeration of possible behaviors for errors on I/O operations. +# The exact meaning depends on whether the I/O was initiated by a guest +# or by a block job +# +# @report: for guest operations, report the error to the guest; +# for jobs, cancel the job +# +# @ignore: ignore the error, only report a QMP event (BLOCK_IO_ERROR +# or BLOCK_JOB_ERROR). The backup, mirror and commit block jobs retry +# the failing request later and may still complete successfully. The +# stream block job continues to stream and will complete with an +# error. +# +# @enospc: same as @stop on ENOSPC, same as @report otherwise. +# +# @stop: for guest operations, stop the virtual machine; +# for jobs, pause the job +# +# @auto: inherit the error handling policy of the backend (since: 2.7) +# +# Since: 1.3 +## +{ 'enum': 'BlockdevOnError', + 'data': ['report', 'ignore', 'enospc', 'stop', 'auto'] } + +## +# @MirrorSyncMode: +# +# An enumeration of possible behaviors for the initial synchronization +# phase of storage mirroring. +# +# @top: copies data in the topmost image to the destination +# +# @full: copies data from all images to the destination +# +# @none: only copy data written from now on +# +# @incremental: only copy data described by the dirty bitmap. (since: 2.4) +# +# @bitmap: only copy data described by the dirty bitmap. (since: 4.2) +# Behavior on completion is determined by the BitmapSyncMode. +# +# Since: 1.3 +## +{ 'enum': 'MirrorSyncMode', + 'data': ['top', 'full', 'none', 'incremental', 'bitmap'] } + +## +# @BitmapSyncMode: +# +# An enumeration of possible behaviors for the synchronization of a bitmap +# when used for data copy operations. +# +# @on-success: The bitmap is only synced when the operation is successful. +# This is the behavior always used for 'INCREMENTAL' backups. +# +# @never: The bitmap is never synchronized with the operation, and is +# treated solely as a read-only manifest of blocks to copy. +# +# @always: The bitmap is always synchronized with the operation, +# regardless of whether or not the operation was successful. +# +# Since: 4.2 +## +{ 'enum': 'BitmapSyncMode', + 'data': ['on-success', 'never', 'always'] } + +## +# @MirrorCopyMode: +# +# An enumeration whose values tell the mirror block job when to +# trigger writes to the target. +# +# @background: copy data in background only. +# +# @write-blocking: when data is written to the source, write it +# (synchronously) to the target as well. In +# addition, data is copied in background just like in +# @background mode. +# +# Since: 3.0 +## +{ 'enum': 'MirrorCopyMode', + 'data': ['background', 'write-blocking'] } + +## +# @BlockJobInfo: +# +# Information about a long-running block device operation. +# +# @type: the job type ('stream' for image streaming) +# +# @device: The job identifier. Originally the device name but other +# values are allowed since QEMU 2.7 +# +# @len: Estimated @offset value at the completion of the job. This value can +# arbitrarily change while the job is running, in both directions. +# +# @offset: Progress made until now. The unit is arbitrary and the value can +# only meaningfully be used for the ratio of @offset to @len. The +# value is monotonically increasing. +# +# @busy: false if the job is known to be in a quiescent state, with +# no pending I/O. Since 1.3. +# +# @paused: whether the job is paused or, if @busy is true, will +# pause itself as soon as possible. Since 1.3. +# +# @speed: the rate limit, bytes per second +# +# @io-status: the status of the job (since 1.3) +# +# @ready: true if the job may be completed (since 2.2) +# +# @status: Current job state/status (since 2.12) +# +# @auto-finalize: Job will finalize itself when PENDING, moving to +# the CONCLUDED state. (since 2.12) +# +# @auto-dismiss: Job will dismiss itself when CONCLUDED, moving to the NULL +# state and disappearing from the query list. (since 2.12) +# +# @error: Error information if the job did not complete successfully. +# Not set if the job completed successfully. (since 2.12.1) +# +# Since: 1.1 +## +{ 'struct': 'BlockJobInfo', + 'data': {'type': 'str', 'device': 'str', 'len': 'int', + 'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int', + 'io-status': 'BlockDeviceIoStatus', 'ready': 'bool', + 'status': 'JobStatus', + 'auto-finalize': 'bool', 'auto-dismiss': 'bool', + '*error': 'str' } } + +## +# @query-block-jobs: +# +# Return information about long-running block device operations. +# +# Returns: a list of @BlockJobInfo for each active block job +# +# Since: 1.1 +## +{ 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] } + +## +# @block_resize: +# +# Resize a block image while a guest is running. +# +# Either @device or @node-name must be set but not both. +# +# @device: the name of the device to get the image resized +# +# @node-name: graph node name to get the image resized (Since 2.0) +# +# @size: new image size in bytes +# +# Returns: - nothing on success +# - If @device is not a valid block device, DeviceNotFound +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "block_resize", +# "arguments": { "device": "scratch", "size": 1073741824 } } +# <- { "return": {} } +# +## +{ 'command': 'block_resize', + 'data': { '*device': 'str', + '*node-name': 'str', + 'size': 'int' }, + 'coroutine': true } + +## +# @NewImageMode: +# +# An enumeration that tells QEMU how to set the backing file path in +# a new image file. +# +# @existing: QEMU should look for an existing image file. +# +# @absolute-paths: QEMU should create a new image with absolute paths +# for the backing file. If there is no backing file available, the new +# image will not be backed either. +# +# Since: 1.1 +## +{ 'enum': 'NewImageMode', + 'data': [ 'existing', 'absolute-paths' ] } + +## +# @BlockdevSnapshotSync: +# +# Either @device or @node-name must be set but not both. +# +# @device: the name of the device to take a snapshot of. +# +# @node-name: graph node name to generate the snapshot from (Since 2.0) +# +# @snapshot-file: the target of the new overlay image. If the file +# exists, or if it is a device, the overlay will be created in the +# existing file/device. Otherwise, a new file will be created. +# +# @snapshot-node-name: the graph node name of the new image (Since 2.0) +# +# @format: the format of the overlay image, default is 'qcow2'. +# +# @mode: whether and how QEMU should create a new image, default is +# 'absolute-paths'. +## +{ 'struct': 'BlockdevSnapshotSync', + 'data': { '*device': 'str', '*node-name': 'str', + 'snapshot-file': 'str', '*snapshot-node-name': 'str', + '*format': 'str', '*mode': 'NewImageMode' } } + +## +# @BlockdevSnapshot: +# +# @node: device or node name that will have a snapshot taken. +# +# @overlay: reference to the existing block device that will become +# the overlay of @node, as part of taking the snapshot. +# It must not have a current backing file (this can be +# achieved by passing "backing": null to blockdev-add). +# +# Since: 2.5 +## +{ 'struct': 'BlockdevSnapshot', + 'data': { 'node': 'str', 'overlay': 'str' } } + +## +# @BackupPerf: +# +# Optional parameters for backup. These parameters don't affect +# functionality, but may significantly affect performance. +# +# @use-copy-range: Use copy offloading. Default false. +# +# @max-workers: Maximum number of parallel requests for the sustained background +# copying process. Doesn't influence copy-before-write operations. +# Default 64. +# +# @max-chunk: Maximum request length for the sustained background copying +# process. Doesn't influence copy-before-write operations. +# 0 means unlimited. If max-chunk is non-zero then it should not be +# less than job cluster size which is calculated as maximum of +# target image cluster size and 64k. Default 0. +# +# Since: 6.0 +## +{ 'struct': 'BackupPerf', + 'data': { '*use-copy-range': 'bool', + '*max-workers': 'int', '*max-chunk': 'int64' } } + +## +# @BackupCommon: +# +# @job-id: identifier for the newly-created block job. If +# omitted, the device name will be used. (Since 2.7) +# +# @device: the device name or node-name of a root node which should be copied. +# +# @sync: what parts of the disk image should be copied to the destination +# (all the disk, only the sectors allocated in the topmost image, from a +# dirty bitmap, or only new I/O). +# +# @speed: the maximum speed, in bytes per second. The default is 0, +# for unlimited. +# +# @bitmap: The name of a dirty bitmap to use. +# Must be present if sync is "bitmap" or "incremental". +# Can be present if sync is "full" or "top". +# Must not be present otherwise. +# (Since 2.4 (drive-backup), 3.1 (blockdev-backup)) +# +# @bitmap-mode: Specifies the type of data the bitmap should contain after +# the operation concludes. +# Must be present if a bitmap was provided, +# Must NOT be present otherwise. (Since 4.2) +# +# @compress: true to compress data, if the target format supports it. +# (default: false) (since 2.8) +# +# @on-source-error: the action to take on an error on the source, +# default 'report'. 'stop' and 'enospc' can only be used +# if the block device supports io-status (see BlockInfo). +# +# @on-target-error: the action to take on an error on the target, +# default 'report' (no limitations, since this applies to +# a different block device than @device). +# +# @auto-finalize: When false, this job will wait in a PENDING state after it has +# finished its work, waiting for @block-job-finalize before +# making any block graph changes. +# When true, this job will automatically +# perform its abort or commit actions. +# Defaults to true. (Since 2.12) +# +# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it +# has completely ceased all work, and awaits @block-job-dismiss. +# When true, this job will automatically disappear from the query +# list without user intervention. +# Defaults to true. (Since 2.12) +# +# @filter-node-name: the node name that should be assigned to the +# filter driver that the backup job inserts into the graph +# above node specified by @drive. If this option is not given, +# a node name is autogenerated. (Since: 4.2) +# +# @x-perf: Performance options. (Since 6.0) +# +# Features: +# @unstable: Member @x-perf is experimental. +# +# Note: @on-source-error and @on-target-error only affect background +# I/O. If an error occurs during a guest write request, the device's +# rerror/werror actions will be used. +# +# Since: 4.2 +## +{ 'struct': 'BackupCommon', + 'data': { '*job-id': 'str', 'device': 'str', + 'sync': 'MirrorSyncMode', '*speed': 'int', + '*bitmap': 'str', '*bitmap-mode': 'BitmapSyncMode', + '*compress': 'bool', + '*on-source-error': 'BlockdevOnError', + '*on-target-error': 'BlockdevOnError', + '*auto-finalize': 'bool', '*auto-dismiss': 'bool', + '*filter-node-name': 'str', + '*x-perf': { 'type': 'BackupPerf', + 'features': [ 'unstable' ] } } } + +## +# @DriveBackup: +# +# @target: the target of the new image. If the file exists, or if it +# is a device, the existing file/device will be used as the new +# destination. If it does not exist, a new file will be created. +# +# @format: the format of the new destination, default is to +# probe if @mode is 'existing', else the format of the source +# +# @mode: whether and how QEMU should create a new image, default is +# 'absolute-paths'. +# +# Since: 1.6 +## +{ 'struct': 'DriveBackup', + 'base': 'BackupCommon', + 'data': { 'target': 'str', + '*format': 'str', + '*mode': 'NewImageMode' } } + +## +# @BlockdevBackup: +# +# @target: the device name or node-name of the backup target node. +# +# Since: 2.3 +## +{ 'struct': 'BlockdevBackup', + 'base': 'BackupCommon', + 'data': { 'target': 'str' } } + +## +# @blockdev-snapshot-sync: +# +# Takes a synchronous snapshot of a block device. +# +# For the arguments, see the documentation of BlockdevSnapshotSync. +# +# Returns: - nothing on success +# - If @device is not a valid block device, DeviceNotFound +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "blockdev-snapshot-sync", +# "arguments": { "device": "ide-hd0", +# "snapshot-file": +# "/some/place/my-image", +# "format": "qcow2" } } +# <- { "return": {} } +# +## +{ 'command': 'blockdev-snapshot-sync', + 'data': 'BlockdevSnapshotSync' } + + +## +# @blockdev-snapshot: +# +# Takes a snapshot of a block device. +# +# Take a snapshot, by installing 'node' as the backing image of +# 'overlay'. Additionally, if 'node' is associated with a block +# device, the block device changes to using 'overlay' as its new active +# image. +# +# For the arguments, see the documentation of BlockdevSnapshot. +# +# Features: +# @allow-write-only-overlay: If present, the check whether this operation is safe +# was relaxed so that it can be used to change +# backing file of a destination of a blockdev-mirror. +# (since 5.0) +# +# Since: 2.5 +# +# Example: +# +# -> { "execute": "blockdev-add", +# "arguments": { "driver": "qcow2", +# "node-name": "node1534", +# "file": { "driver": "file", +# "filename": "hd1.qcow2" }, +# "backing": null } } +# +# <- { "return": {} } +# +# -> { "execute": "blockdev-snapshot", +# "arguments": { "node": "ide-hd0", +# "overlay": "node1534" } } +# <- { "return": {} } +# +## +{ 'command': 'blockdev-snapshot', + 'data': 'BlockdevSnapshot', + 'features': [ 'allow-write-only-overlay' ] } + +## +# @change-backing-file: +# +# Change the backing file in the image file metadata. This does not +# cause QEMU to reopen the image file to reparse the backing filename +# (it may, however, perform a reopen to change permissions from +# r/o -> r/w -> r/o, if needed). The new backing file string is written +# into the image file metadata, and the QEMU internal strings are +# updated. +# +# @image-node-name: The name of the block driver state node of the +# image to modify. The "device" argument is used +# to verify "image-node-name" is in the chain +# described by "device". +# +# @device: The device name or node-name of the root node that owns +# image-node-name. +# +# @backing-file: The string to write as the backing file. This +# string is not validated, so care should be taken +# when specifying the string or the image chain may +# not be able to be reopened again. +# +# Returns: - Nothing on success +# - If "device" does not exist or cannot be determined, DeviceNotFound +# +# Since: 2.1 +## +{ 'command': 'change-backing-file', + 'data': { 'device': 'str', 'image-node-name': 'str', + 'backing-file': 'str' } } + +## +# @block-commit: +# +# Live commit of data from overlay image nodes into backing nodes - i.e., +# writes data between 'top' and 'base' into 'base'. +# +# If top == base, that is an error. +# If top has no overlays on top of it, or if it is in use by a writer, +# the job will not be completed by itself. The user needs to complete +# the job with the block-job-complete command after getting the ready +# event. (Since 2.0) +# +# If the base image is smaller than top, then the base image will be +# resized to be the same size as top. If top is smaller than the base +# image, the base will not be truncated. If you want the base image +# size to match the size of the smaller top, you can safely truncate +# it yourself once the commit operation successfully completes. +# +# @job-id: identifier for the newly-created block job. If +# omitted, the device name will be used. (Since 2.7) +# +# @device: the device name or node-name of a root node +# +# @base-node: The node name of the backing image to write data into. +# If not specified, this is the deepest backing image. +# (since: 3.1) +# +# @base: Same as @base-node, except that it is a file name rather than a node +# name. This must be the exact filename string that was used to open the +# node; other strings, even if addressing the same file, are not +# accepted +# +# @top-node: The node name of the backing image within the image chain +# which contains the topmost data to be committed down. If +# not specified, this is the active layer. (since: 3.1) +# +# @top: Same as @top-node, except that it is a file name rather than a node +# name. This must be the exact filename string that was used to open the +# node; other strings, even if addressing the same file, are not +# accepted +# +# @backing-file: The backing file string to write into the overlay +# image of 'top'. If 'top' does not have an overlay +# image, or if 'top' is in use by a writer, specifying +# a backing file string is an error. +# +# This filename is not validated. If a pathname string +# is such that it cannot be resolved by QEMU, that +# means that subsequent QMP or HMP commands must use +# node-names for the image in question, as filename +# lookup methods will fail. +# +# If not specified, QEMU will automatically determine +# the backing file string to use, or error out if +# there is no obvious choice. Care should be taken +# when specifying the string, to specify a valid +# filename or protocol. +# (Since 2.1) +# +# @speed: the maximum speed, in bytes per second +# +# @on-error: the action to take on an error. 'ignore' means that the request +# should be retried. (default: report; Since: 5.0) +# +# @filter-node-name: the node name that should be assigned to the +# filter driver that the commit job inserts into the graph +# above @top. If this option is not given, a node name is +# autogenerated. (Since: 2.9) +# +# @auto-finalize: When false, this job will wait in a PENDING state after it has +# finished its work, waiting for @block-job-finalize before +# making any block graph changes. +# When true, this job will automatically +# perform its abort or commit actions. +# Defaults to true. (Since 3.1) +# +# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it +# has completely ceased all work, and awaits @block-job-dismiss. +# When true, this job will automatically disappear from the query +# list without user intervention. +# Defaults to true. (Since 3.1) +# +# Features: +# @deprecated: Members @base and @top are deprecated. Use @base-node +# and @top-node instead. +# +# Returns: - Nothing on success +# - If @device does not exist, DeviceNotFound +# - Any other error returns a GenericError. +# +# Since: 1.3 +# +# Example: +# +# -> { "execute": "block-commit", +# "arguments": { "device": "virtio0", +# "top": "/tmp/snap1.qcow2" } } +# <- { "return": {} } +# +## +{ 'command': 'block-commit', + 'data': { '*job-id': 'str', 'device': 'str', '*base-node': 'str', + '*base': { 'type': 'str', 'features': [ 'deprecated' ] }, + '*top-node': 'str', + '*top': { 'type': 'str', 'features': [ 'deprecated' ] }, + '*backing-file': 'str', '*speed': 'int', + '*on-error': 'BlockdevOnError', + '*filter-node-name': 'str', + '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } + +## +# @drive-backup: +# +# Start a point-in-time copy of a block device to a new destination. The +# status of ongoing drive-backup operations can be checked with +# query-block-jobs where the BlockJobInfo.type field has the value 'backup'. +# The operation can be stopped before it has completed using the +# block-job-cancel command. +# +# Features: +# @deprecated: This command is deprecated. Use @blockdev-backup instead. +# +# Returns: - nothing on success +# - If @device is not a valid block device, GenericError +# +# Since: 1.6 +# +# Example: +# +# -> { "execute": "drive-backup", +# "arguments": { "device": "drive0", +# "sync": "full", +# "target": "backup.img" } } +# <- { "return": {} } +# +## +{ 'command': 'drive-backup', 'boxed': true, + 'data': 'DriveBackup', 'features': ['deprecated'] } + +## +# @blockdev-backup: +# +# Start a point-in-time copy of a block device to a new destination. The +# status of ongoing blockdev-backup operations can be checked with +# query-block-jobs where the BlockJobInfo.type field has the value 'backup'. +# The operation can be stopped before it has completed using the +# block-job-cancel command. +# +# Returns: - nothing on success +# - If @device is not a valid block device, DeviceNotFound +# +# Since: 2.3 +# +# Example: +# -> { "execute": "blockdev-backup", +# "arguments": { "device": "src-id", +# "sync": "full", +# "target": "tgt-id" } } +# <- { "return": {} } +# +## +{ 'command': 'blockdev-backup', 'boxed': true, + 'data': 'BlockdevBackup' } + + +## +# @query-named-block-nodes: +# +# Get the named block driver list +# +# @flat: Omit the nested data about backing image ("backing-image" key) if true. +# Default is false (Since 5.0) +# +# Returns: the list of BlockDeviceInfo +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "query-named-block-nodes" } +# <- { "return": [ { "ro":false, +# "drv":"qcow2", +# "encrypted":false, +# "file":"disks/test.qcow2", +# "node-name": "my-node", +# "backing_file_depth":1, +# "bps":1000000, +# "bps_rd":0, +# "bps_wr":0, +# "iops":1000000, +# "iops_rd":0, +# "iops_wr":0, +# "bps_max": 8000000, +# "bps_rd_max": 0, +# "bps_wr_max": 0, +# "iops_max": 0, +# "iops_rd_max": 0, +# "iops_wr_max": 0, +# "iops_size": 0, +# "write_threshold": 0, +# "image":{ +# "filename":"disks/test.qcow2", +# "format":"qcow2", +# "virtual-size":2048000, +# "backing_file":"base.qcow2", +# "full-backing-filename":"disks/base.qcow2", +# "backing-filename-format":"qcow2", +# "snapshots":[ +# { +# "id": "1", +# "name": "snapshot1", +# "vm-state-size": 0, +# "date-sec": 10000200, +# "date-nsec": 12, +# "vm-clock-sec": 206, +# "vm-clock-nsec": 30 +# } +# ], +# "backing-image":{ +# "filename":"disks/base.qcow2", +# "format":"qcow2", +# "virtual-size":2048000 +# } +# } } ] } +# +## +{ 'command': 'query-named-block-nodes', + 'returns': [ 'BlockDeviceInfo' ], + 'data': { '*flat': 'bool' } } + +## +# @XDbgBlockGraphNodeType: +# +# @block-backend: corresponds to BlockBackend +# +# @block-job: corresponds to BlockJob +# +# @block-driver: corresponds to BlockDriverState +# +# Since: 4.0 +## +{ 'enum': 'XDbgBlockGraphNodeType', + 'data': [ 'block-backend', 'block-job', 'block-driver' ] } + +## +# @XDbgBlockGraphNode: +# +# @id: Block graph node identifier. This @id is generated only for +# x-debug-query-block-graph and does not relate to any other identifiers in +# Qemu. +# +# @type: Type of graph node. Can be one of block-backend, block-job or +# block-driver-state. +# +# @name: Human readable name of the node. Corresponds to node-name for +# block-driver-state nodes; is not guaranteed to be unique in the whole +# graph (with block-jobs and block-backends). +# +# Since: 4.0 +## +{ 'struct': 'XDbgBlockGraphNode', + 'data': { 'id': 'uint64', 'type': 'XDbgBlockGraphNodeType', 'name': 'str' } } + +## +# @BlockPermission: +# +# Enum of base block permissions. +# +# @consistent-read: A user that has the "permission" of consistent reads is +# guaranteed that their view of the contents of the block +# device is complete and self-consistent, representing the +# contents of a disk at a specific point. +# For most block devices (including their backing files) this +# is true, but the property cannot be maintained in a few +# situations like for intermediate nodes of a commit block +# job. +# +# @write: This permission is required to change the visible disk contents. +# +# @write-unchanged: This permission (which is weaker than BLK_PERM_WRITE) is +# both enough and required for writes to the block node when +# the caller promises that the visible disk content doesn't +# change. +# As the BLK_PERM_WRITE permission is strictly stronger, +# either is sufficient to perform an unchanging write. +# +# @resize: This permission is required to change the size of a block node. +# +# @graph-mod: This permission is required to change the node that this +# BdrvChild points to. +# +# Since: 4.0 +## +{ 'enum': 'BlockPermission', + 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize', + 'graph-mod' ] } +## +# @XDbgBlockGraphEdge: +# +# Block Graph edge description for x-debug-query-block-graph. +# +# @parent: parent id +# +# @child: child id +# +# @name: name of the relation (examples are 'file' and 'backing') +# +# @perm: granted permissions for the parent operating on the child +# +# @shared-perm: permissions that can still be granted to other users of the +# child while it is still attached to this parent +# +# Since: 4.0 +## +{ 'struct': 'XDbgBlockGraphEdge', + 'data': { 'parent': 'uint64', 'child': 'uint64', + 'name': 'str', 'perm': [ 'BlockPermission' ], + 'shared-perm': [ 'BlockPermission' ] } } + +## +# @XDbgBlockGraph: +# +# Block Graph - list of nodes and list of edges. +# +# Since: 4.0 +## +{ 'struct': 'XDbgBlockGraph', + 'data': { 'nodes': ['XDbgBlockGraphNode'], 'edges': ['XDbgBlockGraphEdge'] } } + +## +# @x-debug-query-block-graph: +# +# Get the block graph. +# +# Features: +# @unstable: This command is meant for debugging. +# +# Since: 4.0 +## +{ 'command': 'x-debug-query-block-graph', 'returns': 'XDbgBlockGraph', + 'features': [ 'unstable' ] } + +## +# @drive-mirror: +# +# Start mirroring a block device's writes to a new destination. target +# specifies the target of the new image. If the file exists, or if it +# is a device, it will be used as the new destination for writes. If +# it does not exist, a new file will be created. format specifies the +# format of the mirror image, default is to probe if mode='existing', +# else the format of the source. +# +# Returns: - nothing on success +# - If @device is not a valid block device, GenericError +# +# Since: 1.3 +# +# Example: +# +# -> { "execute": "drive-mirror", +# "arguments": { "device": "ide-hd0", +# "target": "/some/place/my-image", +# "sync": "full", +# "format": "qcow2" } } +# <- { "return": {} } +# +## +{ 'command': 'drive-mirror', 'boxed': true, + 'data': 'DriveMirror' } + +## +# @DriveMirror: +# +# A set of parameters describing drive mirror setup. +# +# @job-id: identifier for the newly-created block job. If +# omitted, the device name will be used. (Since 2.7) +# +# @device: the device name or node-name of a root node whose writes should be +# mirrored. +# +# @target: the target of the new image. If the file exists, or if it +# is a device, the existing file/device will be used as the new +# destination. If it does not exist, a new file will be created. +# +# @format: the format of the new destination, default is to +# probe if @mode is 'existing', else the format of the source +# +# @node-name: the new block driver state node name in the graph +# (Since 2.1) +# +# @replaces: with sync=full graph node name to be replaced by the new +# image when a whole image copy is done. This can be used to repair +# broken Quorum files. By default, @device is replaced, although +# implicitly created filters on it are kept. (Since 2.1) +# +# @mode: whether and how QEMU should create a new image, default is +# 'absolute-paths'. +# +# @speed: the maximum speed, in bytes per second +# +# @sync: what parts of the disk image should be copied to the destination +# (all the disk, only the sectors allocated in the topmost image, or +# only new I/O). +# +# @granularity: granularity of the dirty bitmap, default is 64K +# if the image format doesn't have clusters, 4K if the clusters +# are smaller than that, else the cluster size. Must be a +# power of 2 between 512 and 64M (since 1.4). +# +# @buf-size: maximum amount of data in flight from source to +# target (since 1.4). +# +# @on-source-error: the action to take on an error on the source, +# default 'report'. 'stop' and 'enospc' can only be used +# if the block device supports io-status (see BlockInfo). +# +# @on-target-error: the action to take on an error on the target, +# default 'report' (no limitations, since this applies to +# a different block device than @device). +# @unmap: Whether to try to unmap target sectors where source has +# only zero. If true, and target unallocated sectors will read as zero, +# target image sectors will be unmapped; otherwise, zeroes will be +# written. Both will result in identical contents. +# Default is true. (Since 2.4) +# +# @copy-mode: when to copy data to the destination; defaults to 'background' +# (Since: 3.0) +# +# @auto-finalize: When false, this job will wait in a PENDING state after it has +# finished its work, waiting for @block-job-finalize before +# making any block graph changes. +# When true, this job will automatically +# perform its abort or commit actions. +# Defaults to true. (Since 3.1) +# +# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it +# has completely ceased all work, and awaits @block-job-dismiss. +# When true, this job will automatically disappear from the query +# list without user intervention. +# Defaults to true. (Since 3.1) +# Since: 1.3 +## +{ 'struct': 'DriveMirror', + 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', + '*format': 'str', '*node-name': 'str', '*replaces': 'str', + 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', + '*speed': 'int', '*granularity': 'uint32', + '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', + '*on-target-error': 'BlockdevOnError', + '*unmap': 'bool', '*copy-mode': 'MirrorCopyMode', + '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } + +## +# @BlockDirtyBitmap: +# +# @node: name of device/node which the bitmap is tracking +# +# @name: name of the dirty bitmap +# +# Since: 2.4 +## +{ 'struct': 'BlockDirtyBitmap', + 'data': { 'node': 'str', 'name': 'str' } } + +## +# @BlockDirtyBitmapAdd: +# +# @node: name of device/node which the bitmap is tracking +# +# @name: name of the dirty bitmap (must be less than 1024 bytes) +# +# @granularity: the bitmap granularity, default is 64k for +# block-dirty-bitmap-add +# +# @persistent: the bitmap is persistent, i.e. it will be saved to the +# corresponding block device image file on its close. For now only +# Qcow2 disks support persistent bitmaps. Default is false for +# block-dirty-bitmap-add. (Since: 2.10) +# +# @disabled: the bitmap is created in the disabled state, which means that +# it will not track drive changes. The bitmap may be enabled with +# block-dirty-bitmap-enable. Default is false. (Since: 4.0) +# +# Since: 2.4 +## +{ 'struct': 'BlockDirtyBitmapAdd', + 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32', + '*persistent': 'bool', '*disabled': 'bool' } } + +## +# @BlockDirtyBitmapMergeSource: +# +# @local: name of the bitmap, attached to the same node as target bitmap. +# +# @external: bitmap with specified node +# +# Since: 4.1 +## +{ 'alternate': 'BlockDirtyBitmapMergeSource', + 'data': { 'local': 'str', + 'external': 'BlockDirtyBitmap' } } + +## +# @BlockDirtyBitmapMerge: +# +# @node: name of device/node which the @target bitmap is tracking +# +# @target: name of the destination dirty bitmap +# +# @bitmaps: name(s) of the source dirty bitmap(s) at @node and/or fully +# specified BlockDirtyBitmap elements. The latter are supported +# since 4.1. +# +# Since: 4.0 +## +{ 'struct': 'BlockDirtyBitmapMerge', + 'data': { 'node': 'str', 'target': 'str', + 'bitmaps': ['BlockDirtyBitmapMergeSource'] } } + +## +# @block-dirty-bitmap-add: +# +# Create a dirty bitmap with a name on the node, and start tracking the writes. +# +# Returns: - nothing on success +# - If @node is not a valid block device or node, DeviceNotFound +# - If @name is already taken, GenericError with an explanation +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "block-dirty-bitmap-add", +# "arguments": { "node": "drive0", "name": "bitmap0" } } +# <- { "return": {} } +# +## +{ 'command': 'block-dirty-bitmap-add', + 'data': 'BlockDirtyBitmapAdd' } + +## +# @block-dirty-bitmap-remove: +# +# Stop write tracking and remove the dirty bitmap that was created +# with block-dirty-bitmap-add. If the bitmap is persistent, remove it from its +# storage too. +# +# Returns: - nothing on success +# - If @node is not a valid block device or node, DeviceNotFound +# - If @name is not found, GenericError with an explanation +# - if @name is frozen by an operation, GenericError +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "block-dirty-bitmap-remove", +# "arguments": { "node": "drive0", "name": "bitmap0" } } +# <- { "return": {} } +# +## +{ 'command': 'block-dirty-bitmap-remove', + 'data': 'BlockDirtyBitmap' } + +## +# @block-dirty-bitmap-clear: +# +# Clear (reset) a dirty bitmap on the device, so that an incremental +# backup from this point in time forward will only backup clusters +# modified after this clear operation. +# +# Returns: - nothing on success +# - If @node is not a valid block device, DeviceNotFound +# - If @name is not found, GenericError with an explanation +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "block-dirty-bitmap-clear", +# "arguments": { "node": "drive0", "name": "bitmap0" } } +# <- { "return": {} } +# +## +{ 'command': 'block-dirty-bitmap-clear', + 'data': 'BlockDirtyBitmap' } + +## +# @block-dirty-bitmap-enable: +# +# Enables a dirty bitmap so that it will begin tracking disk changes. +# +# Returns: - nothing on success +# - If @node is not a valid block device, DeviceNotFound +# - If @name is not found, GenericError with an explanation +# +# Since: 4.0 +# +# Example: +# +# -> { "execute": "block-dirty-bitmap-enable", +# "arguments": { "node": "drive0", "name": "bitmap0" } } +# <- { "return": {} } +# +## +{ 'command': 'block-dirty-bitmap-enable', + 'data': 'BlockDirtyBitmap' } + +## +# @block-dirty-bitmap-disable: +# +# Disables a dirty bitmap so that it will stop tracking disk changes. +# +# Returns: - nothing on success +# - If @node is not a valid block device, DeviceNotFound +# - If @name is not found, GenericError with an explanation +# +# Since: 4.0 +# +# Example: +# +# -> { "execute": "block-dirty-bitmap-disable", +# "arguments": { "node": "drive0", "name": "bitmap0" } } +# <- { "return": {} } +# +## +{ 'command': 'block-dirty-bitmap-disable', + 'data': 'BlockDirtyBitmap' } + +## +# @block-dirty-bitmap-merge: +# +# Merge dirty bitmaps listed in @bitmaps to the @target dirty bitmap. +# Dirty bitmaps in @bitmaps will be unchanged, except if it also appears +# as the @target bitmap. Any bits already set in @target will still be +# set after the merge, i.e., this operation does not clear the target. +# On error, @target is unchanged. +# +# The resulting bitmap will count as dirty any clusters that were dirty in any +# of the source bitmaps. This can be used to achieve backup checkpoints, or in +# simpler usages, to copy bitmaps. +# +# Returns: - nothing on success +# - If @node is not a valid block device, DeviceNotFound +# - If any bitmap in @bitmaps or @target is not found, GenericError +# - If any of the bitmaps have different sizes or granularities, +# GenericError +# +# Since: 4.0 +# +# Example: +# +# -> { "execute": "block-dirty-bitmap-merge", +# "arguments": { "node": "drive0", "target": "bitmap0", +# "bitmaps": ["bitmap1"] } } +# <- { "return": {} } +# +## +{ 'command': 'block-dirty-bitmap-merge', + 'data': 'BlockDirtyBitmapMerge' } + +## +# @BlockDirtyBitmapSha256: +# +# SHA256 hash of dirty bitmap data +# +# @sha256: ASCII representation of SHA256 bitmap hash +# +# Since: 2.10 +## +{ 'struct': 'BlockDirtyBitmapSha256', + 'data': {'sha256': 'str'} } + +## +# @x-debug-block-dirty-bitmap-sha256: +# +# Get bitmap SHA256. +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: - BlockDirtyBitmapSha256 on success +# - If @node is not a valid block device, DeviceNotFound +# - If @name is not found or if hashing has failed, GenericError with an +# explanation +# +# Since: 2.10 +## +{ 'command': 'x-debug-block-dirty-bitmap-sha256', + 'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256', + 'features': [ 'unstable' ] } + +## +# @blockdev-mirror: +# +# Start mirroring a block device's writes to a new destination. +# +# @job-id: identifier for the newly-created block job. If +# omitted, the device name will be used. (Since 2.7) +# +# @device: The device name or node-name of a root node whose writes should be +# mirrored. +# +# @target: the id or node-name of the block device to mirror to. This mustn't be +# attached to guest. +# +# @replaces: with sync=full graph node name to be replaced by the new +# image when a whole image copy is done. This can be used to repair +# broken Quorum files. By default, @device is replaced, although +# implicitly created filters on it are kept. +# +# @speed: the maximum speed, in bytes per second +# +# @sync: what parts of the disk image should be copied to the destination +# (all the disk, only the sectors allocated in the topmost image, or +# only new I/O). +# +# @granularity: granularity of the dirty bitmap, default is 64K +# if the image format doesn't have clusters, 4K if the clusters +# are smaller than that, else the cluster size. Must be a +# power of 2 between 512 and 64M +# +# @buf-size: maximum amount of data in flight from source to +# target +# +# @on-source-error: the action to take on an error on the source, +# default 'report'. 'stop' and 'enospc' can only be used +# if the block device supports io-status (see BlockInfo). +# +# @on-target-error: the action to take on an error on the target, +# default 'report' (no limitations, since this applies to +# a different block device than @device). +# +# @filter-node-name: the node name that should be assigned to the +# filter driver that the mirror job inserts into the graph +# above @device. If this option is not given, a node name is +# autogenerated. (Since: 2.9) +# +# @copy-mode: when to copy data to the destination; defaults to 'background' +# (Since: 3.0) +# +# @auto-finalize: When false, this job will wait in a PENDING state after it has +# finished its work, waiting for @block-job-finalize before +# making any block graph changes. +# When true, this job will automatically +# perform its abort or commit actions. +# Defaults to true. (Since 3.1) +# +# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it +# has completely ceased all work, and awaits @block-job-dismiss. +# When true, this job will automatically disappear from the query +# list without user intervention. +# Defaults to true. (Since 3.1) +# Returns: nothing on success. +# +# Since: 2.6 +# +# Example: +# +# -> { "execute": "blockdev-mirror", +# "arguments": { "device": "ide-hd0", +# "target": "target0", +# "sync": "full" } } +# <- { "return": {} } +# +## +{ 'command': 'blockdev-mirror', + 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', + '*replaces': 'str', + 'sync': 'MirrorSyncMode', + '*speed': 'int', '*granularity': 'uint32', + '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', + '*on-target-error': 'BlockdevOnError', + '*filter-node-name': 'str', + '*copy-mode': 'MirrorCopyMode', + '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } + +## +# @BlockIOThrottle: +# +# A set of parameters describing block throttling. +# +# @device: Block device name +# +# @id: The name or QOM path of the guest device (since: 2.8) +# +# @bps: total throughput limit in bytes per second +# +# @bps_rd: read throughput limit in bytes per second +# +# @bps_wr: write throughput limit in bytes per second +# +# @iops: total I/O operations per second +# +# @iops_rd: read I/O operations per second +# +# @iops_wr: write I/O operations per second +# +# @bps_max: total throughput limit during bursts, +# in bytes (Since 1.7) +# +# @bps_rd_max: read throughput limit during bursts, +# in bytes (Since 1.7) +# +# @bps_wr_max: write throughput limit during bursts, +# in bytes (Since 1.7) +# +# @iops_max: total I/O operations per second during bursts, +# in bytes (Since 1.7) +# +# @iops_rd_max: read I/O operations per second during bursts, +# in bytes (Since 1.7) +# +# @iops_wr_max: write I/O operations per second during bursts, +# in bytes (Since 1.7) +# +# @bps_max_length: maximum length of the @bps_max burst +# period, in seconds. It must only +# be set if @bps_max is set as well. +# Defaults to 1. (Since 2.6) +# +# @bps_rd_max_length: maximum length of the @bps_rd_max +# burst period, in seconds. It must only +# be set if @bps_rd_max is set as well. +# Defaults to 1. (Since 2.6) +# +# @bps_wr_max_length: maximum length of the @bps_wr_max +# burst period, in seconds. It must only +# be set if @bps_wr_max is set as well. +# Defaults to 1. (Since 2.6) +# +# @iops_max_length: maximum length of the @iops burst +# period, in seconds. It must only +# be set if @iops_max is set as well. +# Defaults to 1. (Since 2.6) +# +# @iops_rd_max_length: maximum length of the @iops_rd_max +# burst period, in seconds. It must only +# be set if @iops_rd_max is set as well. +# Defaults to 1. (Since 2.6) +# +# @iops_wr_max_length: maximum length of the @iops_wr_max +# burst period, in seconds. It must only +# be set if @iops_wr_max is set as well. +# Defaults to 1. (Since 2.6) +# +# @iops_size: an I/O size in bytes (Since 1.7) +# +# @group: throttle group name (Since 2.4) +# +# Features: +# @deprecated: Member @device is deprecated. Use @id instead. +# +# Since: 1.1 +## +{ 'struct': 'BlockIOThrottle', + 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, + '*id': 'str', 'bps': 'int', 'bps_rd': 'int', + 'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int', + '*bps_max': 'int', '*bps_rd_max': 'int', + '*bps_wr_max': 'int', '*iops_max': 'int', + '*iops_rd_max': 'int', '*iops_wr_max': 'int', + '*bps_max_length': 'int', '*bps_rd_max_length': 'int', + '*bps_wr_max_length': 'int', '*iops_max_length': 'int', + '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int', + '*iops_size': 'int', '*group': 'str' } } + +## +# @ThrottleLimits: +# +# Limit parameters for throttling. +# Since some limit combinations are illegal, limits should always be set in one +# transaction. All fields are optional. When setting limits, if a field is +# missing the current value is not changed. +# +# @iops-total: limit total I/O operations per second +# @iops-total-max: I/O operations burst +# @iops-total-max-length: length of the iops-total-max burst period, in seconds +# It must only be set if @iops-total-max is set as well. +# @iops-read: limit read operations per second +# @iops-read-max: I/O operations read burst +# @iops-read-max-length: length of the iops-read-max burst period, in seconds +# It must only be set if @iops-read-max is set as well. +# @iops-write: limit write operations per second +# @iops-write-max: I/O operations write burst +# @iops-write-max-length: length of the iops-write-max burst period, in seconds +# It must only be set if @iops-write-max is set as well. +# @bps-total: limit total bytes per second +# @bps-total-max: total bytes burst +# @bps-total-max-length: length of the bps-total-max burst period, in seconds. +# It must only be set if @bps-total-max is set as well. +# @bps-read: limit read bytes per second +# @bps-read-max: total bytes read burst +# @bps-read-max-length: length of the bps-read-max burst period, in seconds +# It must only be set if @bps-read-max is set as well. +# @bps-write: limit write bytes per second +# @bps-write-max: total bytes write burst +# @bps-write-max-length: length of the bps-write-max burst period, in seconds +# It must only be set if @bps-write-max is set as well. +# @iops-size: when limiting by iops max size of an I/O in bytes +# +# Since: 2.11 +## +{ 'struct': 'ThrottleLimits', + 'data': { '*iops-total' : 'int', '*iops-total-max' : 'int', + '*iops-total-max-length' : 'int', '*iops-read' : 'int', + '*iops-read-max' : 'int', '*iops-read-max-length' : 'int', + '*iops-write' : 'int', '*iops-write-max' : 'int', + '*iops-write-max-length' : 'int', '*bps-total' : 'int', + '*bps-total-max' : 'int', '*bps-total-max-length' : 'int', + '*bps-read' : 'int', '*bps-read-max' : 'int', + '*bps-read-max-length' : 'int', '*bps-write' : 'int', + '*bps-write-max' : 'int', '*bps-write-max-length' : 'int', + '*iops-size' : 'int' } } + +## +# @ThrottleGroupProperties: +# +# Properties for throttle-group objects. +# +# @limits: limits to apply for this throttle group +# +# Features: +# @unstable: All members starting with x- are aliases for the same key +# without x- in the @limits object. This is not a stable +# interface and may be removed or changed incompatibly in +# the future. Use @limits for a supported stable +# interface. +# +# Since: 2.11 +## +{ 'struct': 'ThrottleGroupProperties', + 'data': { '*limits': 'ThrottleLimits', + '*x-iops-total': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-total-max': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-total-max-length': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-read': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-read-max': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-read-max-length': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-write': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-write-max': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-write-max-length': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-total': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-total-max': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-total-max-length': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-read': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-read-max': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-read-max-length': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-write': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-write-max': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-bps-write-max-length': { 'type': 'int', + 'features': [ 'unstable' ] }, + '*x-iops-size': { 'type': 'int', + 'features': [ 'unstable' ] } } } + +## +# @block-stream: +# +# Copy data from a backing file into a block device. +# +# The block streaming operation is performed in the background until the entire +# backing file has been copied. This command returns immediately once streaming +# has started. The status of ongoing block streaming operations can be checked +# with query-block-jobs. The operation can be stopped before it has completed +# using the block-job-cancel command. +# +# The node that receives the data is called the top image, can be located in +# any part of the chain (but always above the base image; see below) and can be +# specified using its device or node name. Earlier qemu versions only allowed +# 'device' to name the top level node; presence of the 'base-node' parameter +# during introspection can be used as a witness of the enhanced semantics +# of 'device'. +# +# If a base file is specified then sectors are not copied from that base file and +# its backing chain. This can be used to stream a subset of the backing file +# chain instead of flattening the entire image. +# When streaming completes the image file will have the base file as its backing +# file, unless that node was changed while the job was running. In that case, +# base's parent's backing (or filtered, whichever exists) child (i.e., base at +# the beginning of the job) will be the new backing file. +# +# On successful completion the image file is updated to drop the backing file +# and the BLOCK_JOB_COMPLETED event is emitted. +# +# In case @device is a filter node, block-stream modifies the first non-filter +# overlay node below it to point to the new backing node instead of modifying +# @device itself. +# +# @job-id: identifier for the newly-created block job. If +# omitted, the device name will be used. (Since 2.7) +# +# @device: the device or node name of the top image +# +# @base: the common backing file name. +# It cannot be set if @base-node or @bottom is also set. +# +# @base-node: the node name of the backing file. +# It cannot be set if @base or @bottom is also set. (Since 2.8) +# +# @bottom: the last node in the chain that should be streamed into +# top. It cannot be set if @base or @base-node is also set. +# It cannot be filter node. (Since 6.0) +# +# @backing-file: The backing file string to write into the top +# image. This filename is not validated. +# +# If a pathname string is such that it cannot be +# resolved by QEMU, that means that subsequent QMP or +# HMP commands must use node-names for the image in +# question, as filename lookup methods will fail. +# +# If not specified, QEMU will automatically determine +# the backing file string to use, or error out if there +# is no obvious choice. Care should be taken when +# specifying the string, to specify a valid filename or +# protocol. +# (Since 2.1) +# +# @speed: the maximum speed, in bytes per second +# +# @on-error: the action to take on an error (default report). +# 'stop' and 'enospc' can only be used if the block device +# supports io-status (see BlockInfo). Since 1.3. +# +# @filter-node-name: the node name that should be assigned to the +# filter driver that the stream job inserts into the graph +# above @device. If this option is not given, a node name is +# autogenerated. (Since: 6.0) +# +# @auto-finalize: When false, this job will wait in a PENDING state after it has +# finished its work, waiting for @block-job-finalize before +# making any block graph changes. +# When true, this job will automatically +# perform its abort or commit actions. +# Defaults to true. (Since 3.1) +# +# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it +# has completely ceased all work, and awaits @block-job-dismiss. +# When true, this job will automatically disappear from the query +# list without user intervention. +# Defaults to true. (Since 3.1) +# +# Returns: - Nothing on success. +# - If @device does not exist, DeviceNotFound. +# +# Since: 1.1 +# +# Example: +# +# -> { "execute": "block-stream", +# "arguments": { "device": "virtio0", +# "base": "/tmp/master.qcow2" } } +# <- { "return": {} } +# +## +{ 'command': 'block-stream', + 'data': { '*job-id': 'str', 'device': 'str', '*base': 'str', + '*base-node': 'str', '*backing-file': 'str', '*bottom': 'str', + '*speed': 'int', '*on-error': 'BlockdevOnError', + '*filter-node-name': 'str', + '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } + +## +# @block-job-set-speed: +# +# Set maximum speed for a background block operation. +# +# This command can only be issued when there is an active block job. +# +# Throttling can be disabled by setting the speed to 0. +# +# @device: The job identifier. This used to be a device name (hence +# the name of the parameter), but since QEMU 2.7 it can have +# other values. +# +# @speed: the maximum speed, in bytes per second, or 0 for unlimited. +# Defaults to 0. +# +# Returns: - Nothing on success +# - If no background operation is active on this device, DeviceNotActive +# +# Since: 1.1 +## +{ 'command': 'block-job-set-speed', + 'data': { 'device': 'str', 'speed': 'int' } } + +## +# @block-job-cancel: +# +# Stop an active background block operation. +# +# This command returns immediately after marking the active background block +# operation for cancellation. It is an error to call this command if no +# operation is in progress. +# +# The operation will cancel as soon as possible and then emit the +# BLOCK_JOB_CANCELLED event. Before that happens the job is still visible when +# enumerated using query-block-jobs. +# +# Note that if you issue 'block-job-cancel' after 'drive-mirror' has indicated +# (via the event BLOCK_JOB_READY) that the source and destination are +# synchronized, then the event triggered by this command changes to +# BLOCK_JOB_COMPLETED, to indicate that the mirroring has ended and the +# destination now has a point-in-time copy tied to the time of the cancellation. +# +# For streaming, the image file retains its backing file unless the streaming +# operation happens to complete just as it is being cancelled. A new streaming +# operation can be started at a later time to finish copying all data from the +# backing file. +# +# @device: The job identifier. This used to be a device name (hence +# the name of the parameter), but since QEMU 2.7 it can have +# other values. +# +# @force: If true, and the job has already emitted the event BLOCK_JOB_READY, +# abandon the job immediately (even if it is paused) instead of waiting +# for the destination to complete its final synchronization (since 1.3) +# +# Returns: - Nothing on success +# - If no background operation is active on this device, DeviceNotActive +# +# Since: 1.1 +## +{ 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } } + +## +# @block-job-pause: +# +# Pause an active background block operation. +# +# This command returns immediately after marking the active background block +# operation for pausing. It is an error to call this command if no +# operation is in progress or if the job is already paused. +# +# The operation will pause as soon as possible. No event is emitted when +# the operation is actually paused. Cancelling a paused job automatically +# resumes it. +# +# @device: The job identifier. This used to be a device name (hence +# the name of the parameter), but since QEMU 2.7 it can have +# other values. +# +# Returns: - Nothing on success +# - If no background operation is active on this device, DeviceNotActive +# +# Since: 1.3 +## +{ 'command': 'block-job-pause', 'data': { 'device': 'str' } } + +## +# @block-job-resume: +# +# Resume an active background block operation. +# +# This command returns immediately after resuming a paused background block +# operation. It is an error to call this command if no operation is in +# progress or if the job is not paused. +# +# This command also clears the error status of the job. +# +# @device: The job identifier. This used to be a device name (hence +# the name of the parameter), but since QEMU 2.7 it can have +# other values. +# +# Returns: - Nothing on success +# - If no background operation is active on this device, DeviceNotActive +# +# Since: 1.3 +## +{ 'command': 'block-job-resume', 'data': { 'device': 'str' } } + +## +# @block-job-complete: +# +# Manually trigger completion of an active background block operation. This +# is supported for drive mirroring, where it also switches the device to +# write to the target path only. The ability to complete is signaled with +# a BLOCK_JOB_READY event. +# +# This command completes an active background block operation synchronously. +# The ordering of this command's return with the BLOCK_JOB_COMPLETED event +# is not defined. Note that if an I/O error occurs during the processing of +# this command: 1) the command itself will fail; 2) the error will be processed +# according to the rerror/werror arguments that were specified when starting +# the operation. +# +# A cancelled or paused job cannot be completed. +# +# @device: The job identifier. This used to be a device name (hence +# the name of the parameter), but since QEMU 2.7 it can have +# other values. +# +# Returns: - Nothing on success +# - If no background operation is active on this device, DeviceNotActive +# +# Since: 1.3 +## +{ 'command': 'block-job-complete', 'data': { 'device': 'str' } } + +## +# @block-job-dismiss: +# +# For jobs that have already concluded, remove them from the block-job-query +# list. This command only needs to be run for jobs which were started with +# QEMU 2.12+ job lifetime management semantics. +# +# This command will refuse to operate on any job that has not yet reached +# its terminal state, JOB_STATUS_CONCLUDED. For jobs that make use of the +# BLOCK_JOB_READY event, block-job-cancel or block-job-complete will still need +# to be used as appropriate. +# +# @id: The job identifier. +# +# Returns: Nothing on success +# +# Since: 2.12 +## +{ 'command': 'block-job-dismiss', 'data': { 'id': 'str' } } + +## +# @block-job-finalize: +# +# Once a job that has manual=true reaches the pending state, it can be +# instructed to finalize any graph changes and do any necessary cleanup +# via this command. +# For jobs in a transaction, instructing one job to finalize will force +# ALL jobs in the transaction to finalize, so it is only necessary to instruct +# a single member job to finalize. +# +# @id: The job identifier. +# +# Returns: Nothing on success +# +# Since: 2.12 +## +{ 'command': 'block-job-finalize', 'data': { 'id': 'str' } } + +## +# @BlockdevDiscardOptions: +# +# Determines how to handle discard requests. +# +# @ignore: Ignore the request +# @unmap: Forward as an unmap request +# +# Since: 2.9 +## +{ 'enum': 'BlockdevDiscardOptions', + 'data': [ 'ignore', 'unmap' ] } + +## +# @BlockdevDetectZeroesOptions: +# +# Describes the operation mode for the automatic conversion of plain +# zero writes by the OS to driver specific optimized zero write commands. +# +# @off: Disabled (default) +# @on: Enabled +# @unmap: Enabled and even try to unmap blocks if possible. This requires +# also that @BlockdevDiscardOptions is set to unmap for this device. +# +# Since: 2.1 +## +{ 'enum': 'BlockdevDetectZeroesOptions', + 'data': [ 'off', 'on', 'unmap' ] } + +## +# @BlockdevAioOptions: +# +# Selects the AIO backend to handle I/O requests +# +# @threads: Use qemu's thread pool +# @native: Use native AIO backend (only Linux and Windows) +# @io_uring: Use linux io_uring (since 5.0) +# +# Since: 2.9 +## +{ 'enum': 'BlockdevAioOptions', + 'data': [ 'threads', 'native', + { 'name': 'io_uring', 'if': 'CONFIG_LINUX_IO_URING' } ] } + +## +# @BlockdevCacheOptions: +# +# Includes cache-related options for block devices +# +# @direct: enables use of O_DIRECT (bypass the host page cache; +# default: false) +# @no-flush: ignore any flush requests for the device (default: +# false) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevCacheOptions', + 'data': { '*direct': 'bool', + '*no-flush': 'bool' } } + +## +# @BlockdevDriver: +# +# Drivers that are supported in block device operations. +# +# @throttle: Since 2.11 +# @nvme: Since 2.12 +# @copy-on-read: Since 3.0 +# @blklogwrites: Since 3.0 +# @blkreplay: Since 4.2 +# @compress: Since 5.0 +# @copy-before-write: Since 6.2 +# +# Since: 2.9 +## +{ 'enum': 'BlockdevDriver', + 'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs', + 'cloop', 'compress', 'copy-before-write', 'copy-on-read', 'dmg', + 'file', 'ftp', 'ftps', 'gluster', + {'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' }, + {'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' }, + 'http', 'https', 'iscsi', + 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', + 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd', + { 'name': 'replication', 'if': 'CONFIG_REPLICATION' }, + 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] } + +## +# @BlockdevOptionsFile: +# +# Driver specific block device options for the file backend. +# +# @filename: path to the image file +# @pr-manager: the id for the object that will handle persistent reservations +# for this device (default: none, forward the commands via SG_IO; +# since 2.11) +# @aio: AIO backend (default: threads) (since: 2.8) +# @aio-max-batch: maximum number of requests to batch together into a single +# submission in the AIO backend. The smallest value between +# this and the aio-max-batch value of the IOThread object is +# chosen. +# 0 means that the AIO backend will handle it automatically. +# (default: 0, since 6.2) +# @locking: whether to enable file locking. If set to 'auto', only enable +# when Open File Descriptor (OFD) locking API is available +# (default: auto, since 2.10) +# @drop-cache: invalidate page cache during live migration. This prevents +# stale data on the migration destination with cache.direct=off. +# Currently only supported on Linux hosts. +# (default: on, since: 4.0) +# @x-check-cache-dropped: whether to check that page cache was dropped on live +# migration. May cause noticeable delays if the image +# file is large, do not use in production. +# (default: off) (since: 3.0) +# +# Features: +# @dynamic-auto-read-only: If present, enabled auto-read-only means that the +# driver will open the image read-only at first, +# dynamically reopen the image file read-write when +# the first writer is attached to the node and reopen +# read-only when the last writer is detached. This +# allows giving QEMU write permissions only on demand +# when an operation actually needs write access. +# @unstable: Member x-check-cache-dropped is meant for debugging. +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsFile', + 'data': { 'filename': 'str', + '*pr-manager': 'str', + '*locking': 'OnOffAuto', + '*aio': 'BlockdevAioOptions', + '*aio-max-batch': 'int', + '*drop-cache': {'type': 'bool', + 'if': 'CONFIG_LINUX'}, + '*x-check-cache-dropped': { 'type': 'bool', + 'features': [ 'unstable' ] } }, + 'features': [ { 'name': 'dynamic-auto-read-only', + 'if': 'CONFIG_POSIX' } ] } + +## +# @BlockdevOptionsNull: +# +# Driver specific block device options for the null backend. +# +# @size: size of the device in bytes. +# @latency-ns: emulated latency (in nanoseconds) in processing +# requests. Default to zero which completes requests immediately. +# (Since 2.4) +# @read-zeroes: if true, reads from the device produce zeroes; if false, the +# buffer is left unchanged. (default: false; since: 4.1) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsNull', + 'data': { '*size': 'int', '*latency-ns': 'uint64', '*read-zeroes': 'bool' } } + +## +# @BlockdevOptionsNVMe: +# +# Driver specific block device options for the NVMe backend. +# +# @device: PCI controller address of the NVMe device in +# format hhhh:bb:ss.f (host:bus:slot.function) +# @namespace: namespace number of the device, starting from 1. +# +# Note that the PCI @device must have been unbound from any host +# kernel driver before instructing QEMU to add the blockdev. +# +# Since: 2.12 +## +{ 'struct': 'BlockdevOptionsNVMe', + 'data': { 'device': 'str', 'namespace': 'int' } } + +## +# @BlockdevOptionsVVFAT: +# +# Driver specific block device options for the vvfat protocol. +# +# @dir: directory to be exported as FAT image +# @fat-type: FAT type: 12, 16 or 32 +# @floppy: whether to export a floppy image (true) or +# partitioned hard disk (false; default) +# @label: set the volume label, limited to 11 bytes. FAT16 and +# FAT32 traditionally have some restrictions on labels, which are +# ignored by most operating systems. Defaults to "QEMU VVFAT". +# (since 2.4) +# @rw: whether to allow write operations (default: false) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsVVFAT', + 'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool', + '*label': 'str', '*rw': 'bool' } } + +## +# @BlockdevOptionsGenericFormat: +# +# Driver specific block device options for image format that have no option +# besides their data source. +# +# @file: reference to or definition of the data source block device +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsGenericFormat', + 'data': { 'file': 'BlockdevRef' } } + +## +# @BlockdevOptionsLUKS: +# +# Driver specific block device options for LUKS. +# +# @key-secret: the ID of a QCryptoSecret object providing +# the decryption key (since 2.6). Mandatory except when +# doing a metadata-only probe of the image. +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsLUKS', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { '*key-secret': 'str' } } + + +## +# @BlockdevOptionsGenericCOWFormat: +# +# Driver specific block device options for image format that have no option +# besides their data source and an optional backing file. +# +# @backing: reference to or definition of the backing file block +# device, null disables the backing file entirely. +# Defaults to the backing file stored the image file. +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsGenericCOWFormat', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { '*backing': 'BlockdevRefOrNull' } } + +## +# @Qcow2OverlapCheckMode: +# +# General overlap check modes. +# +# @none: Do not perform any checks +# +# @constant: Perform only checks which can be done in constant time and +# without reading anything from disk +# +# @cached: Perform only checks which can be done without reading anything +# from disk +# +# @all: Perform all available overlap checks +# +# Since: 2.9 +## +{ 'enum': 'Qcow2OverlapCheckMode', + 'data': [ 'none', 'constant', 'cached', 'all' ] } + +## +# @Qcow2OverlapCheckFlags: +# +# Structure of flags for each metadata structure. Setting a field to 'true' +# makes qemu guard that structure against unintended overwriting. The default +# value is chosen according to the template given. +# +# @template: Specifies a template mode which can be adjusted using the other +# flags, defaults to 'cached' +# +# @bitmap-directory: since 3.0 +# +# Since: 2.9 +## +{ 'struct': 'Qcow2OverlapCheckFlags', + 'data': { '*template': 'Qcow2OverlapCheckMode', + '*main-header': 'bool', + '*active-l1': 'bool', + '*active-l2': 'bool', + '*refcount-table': 'bool', + '*refcount-block': 'bool', + '*snapshot-table': 'bool', + '*inactive-l1': 'bool', + '*inactive-l2': 'bool', + '*bitmap-directory': 'bool' } } + +## +# @Qcow2OverlapChecks: +# +# Specifies which metadata structures should be guarded against unintended +# overwriting. +# +# @flags: set of flags for separate specification of each metadata structure +# type +# +# @mode: named mode which chooses a specific set of flags +# +# Since: 2.9 +## +{ 'alternate': 'Qcow2OverlapChecks', + 'data': { 'flags': 'Qcow2OverlapCheckFlags', + 'mode': 'Qcow2OverlapCheckMode' } } + +## +# @BlockdevQcowEncryptionFormat: +# +# @aes: AES-CBC with plain64 initialization vectors +# +# Since: 2.10 +## +{ 'enum': 'BlockdevQcowEncryptionFormat', + 'data': [ 'aes' ] } + +## +# @BlockdevQcowEncryption: +# +# Since: 2.10 +## +{ 'union': 'BlockdevQcowEncryption', + 'base': { 'format': 'BlockdevQcowEncryptionFormat' }, + 'discriminator': 'format', + 'data': { 'aes': 'QCryptoBlockOptionsQCow' } } + +## +# @BlockdevOptionsQcow: +# +# Driver specific block device options for qcow. +# +# @encrypt: Image decryption options. Mandatory for +# encrypted images, except when doing a metadata-only +# probe of the image. +# +# Since: 2.10 +## +{ 'struct': 'BlockdevOptionsQcow', + 'base': 'BlockdevOptionsGenericCOWFormat', + 'data': { '*encrypt': 'BlockdevQcowEncryption' } } + + + +## +# @BlockdevQcow2EncryptionFormat: +# +# @aes: AES-CBC with plain64 initialization vectors +# +# Since: 2.10 +## +{ 'enum': 'BlockdevQcow2EncryptionFormat', + 'data': [ 'aes', 'luks' ] } + +## +# @BlockdevQcow2Encryption: +# +# Since: 2.10 +## +{ 'union': 'BlockdevQcow2Encryption', + 'base': { 'format': 'BlockdevQcow2EncryptionFormat' }, + 'discriminator': 'format', + 'data': { 'aes': 'QCryptoBlockOptionsQCow', + 'luks': 'QCryptoBlockOptionsLUKS'} } + +## +# @BlockdevOptionsPreallocate: +# +# Filter driver intended to be inserted between format and protocol node +# and do preallocation in protocol node on write. +# +# @prealloc-align: on preallocation, align file length to this number, +# default 1048576 (1M) +# +# @prealloc-size: how much to preallocate, default 134217728 (128M) +# +# Since: 6.0 +## +{ 'struct': 'BlockdevOptionsPreallocate', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { '*prealloc-align': 'int', '*prealloc-size': 'int' } } + +## +# @BlockdevOptionsQcow2: +# +# Driver specific block device options for qcow2. +# +# @lazy-refcounts: whether to enable the lazy refcounts +# feature (default is taken from the image file) +# +# @pass-discard-request: whether discard requests to the qcow2 +# device should be forwarded to the data source +# +# @pass-discard-snapshot: whether discard requests for the data source +# should be issued when a snapshot operation (e.g. +# deleting a snapshot) frees clusters in the qcow2 file +# +# @pass-discard-other: whether discard requests for the data source +# should be issued on other occasions where a cluster +# gets freed +# +# @overlap-check: which overlap checks to perform for writes +# to the image, defaults to 'cached' (since 2.2) +# +# @cache-size: the maximum total size of the L2 table and +# refcount block caches in bytes (since 2.2) +# +# @l2-cache-size: the maximum size of the L2 table cache in +# bytes (since 2.2) +# +# @l2-cache-entry-size: the size of each entry in the L2 cache in +# bytes. It must be a power of two between 512 +# and the cluster size. The default value is +# the cluster size (since 2.12) +# +# @refcount-cache-size: the maximum size of the refcount block cache +# in bytes (since 2.2) +# +# @cache-clean-interval: clean unused entries in the L2 and refcount +# caches. The interval is in seconds. The default value +# is 600 on supporting platforms, and 0 on other +# platforms. 0 disables this feature. (since 2.5) +# +# @encrypt: Image decryption options. Mandatory for +# encrypted images, except when doing a metadata-only +# probe of the image. (since 2.10) +# +# @data-file: reference to or definition of the external data file. +# This may only be specified for images that require an +# external data file. If it is not specified for such +# an image, the data file name is loaded from the image +# file. (since 4.0) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsQcow2', + 'base': 'BlockdevOptionsGenericCOWFormat', + 'data': { '*lazy-refcounts': 'bool', + '*pass-discard-request': 'bool', + '*pass-discard-snapshot': 'bool', + '*pass-discard-other': 'bool', + '*overlap-check': 'Qcow2OverlapChecks', + '*cache-size': 'int', + '*l2-cache-size': 'int', + '*l2-cache-entry-size': 'int', + '*refcount-cache-size': 'int', + '*cache-clean-interval': 'int', + '*encrypt': 'BlockdevQcow2Encryption', + '*data-file': 'BlockdevRef' } } + +## +# @SshHostKeyCheckMode: +# +# @none: Don't check the host key at all +# @hash: Compare the host key with a given hash +# @known_hosts: Check the host key against the known_hosts file +# +# Since: 2.12 +## +{ 'enum': 'SshHostKeyCheckMode', + 'data': [ 'none', 'hash', 'known_hosts' ] } + +## +# @SshHostKeyCheckHashType: +# +# @md5: The given hash is an md5 hash +# @sha1: The given hash is an sha1 hash +# @sha256: The given hash is an sha256 hash +# +# Since: 2.12 +## +{ 'enum': 'SshHostKeyCheckHashType', + 'data': [ 'md5', 'sha1', 'sha256' ] } + +## +# @SshHostKeyHash: +# +# @type: The hash algorithm used for the hash +# @hash: The expected hash value +# +# Since: 2.12 +## +{ 'struct': 'SshHostKeyHash', + 'data': { 'type': 'SshHostKeyCheckHashType', + 'hash': 'str' }} + +## +# @SshHostKeyCheck: +# +# Since: 2.12 +## +{ 'union': 'SshHostKeyCheck', + 'base': { 'mode': 'SshHostKeyCheckMode' }, + 'discriminator': 'mode', + 'data': { 'hash': 'SshHostKeyHash' } } + +## +# @BlockdevOptionsSsh: +# +# @server: host address +# +# @path: path to the image on the host +# +# @user: user as which to connect, defaults to current +# local user name +# +# @host-key-check: Defines how and what to check the host key against +# (default: known_hosts) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsSsh', + 'data': { 'server': 'InetSocketAddress', + 'path': 'str', + '*user': 'str', + '*host-key-check': 'SshHostKeyCheck' } } + + +## +# @BlkdebugEvent: +# +# Trigger events supported by blkdebug. +# +# @l1_shrink_write_table: write zeros to the l1 table to shrink image. +# (since 2.11) +# +# @l1_shrink_free_l2_clusters: discard the l2 tables. (since 2.11) +# +# @cor_write: a write due to copy-on-read (since 2.11) +# +# @cluster_alloc_space: an allocation of file space for a cluster (since 4.1) +# +# @none: triggers once at creation of the blkdebug node (since 4.1) +# +# Since: 2.9 +## +{ 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG', + 'data': [ 'l1_update', 'l1_grow_alloc_table', 'l1_grow_write_table', + 'l1_grow_activate_table', 'l2_load', 'l2_update', + 'l2_update_compressed', 'l2_alloc_cow_read', 'l2_alloc_write', + 'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio', + 'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read', + 'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update', + 'refblock_load', 'refblock_update', 'refblock_update_part', + 'refblock_alloc', 'refblock_alloc_hookup', 'refblock_alloc_write', + 'refblock_alloc_write_blocks', 'refblock_alloc_write_table', + 'refblock_alloc_switch_table', 'cluster_alloc', + 'cluster_alloc_bytes', 'cluster_free', 'flush_to_os', + 'flush_to_disk', 'pwritev_rmw_head', 'pwritev_rmw_after_head', + 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev', + 'pwritev_zero', 'pwritev_done', 'empty_image_prepare', + 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters', + 'cor_write', 'cluster_alloc_space', 'none'] } + +## +# @BlkdebugIOType: +# +# Kinds of I/O that blkdebug can inject errors in. +# +# @read: .bdrv_co_preadv() +# +# @write: .bdrv_co_pwritev() +# +# @write-zeroes: .bdrv_co_pwrite_zeroes() +# +# @discard: .bdrv_co_pdiscard() +# +# @flush: .bdrv_co_flush_to_disk() +# +# @block-status: .bdrv_co_block_status() +# +# Since: 4.1 +## +{ 'enum': 'BlkdebugIOType', 'prefix': 'BLKDEBUG_IO_TYPE', + 'data': [ 'read', 'write', 'write-zeroes', 'discard', 'flush', + 'block-status' ] } + +## +# @BlkdebugInjectErrorOptions: +# +# Describes a single error injection for blkdebug. +# +# @event: trigger event +# +# @state: the state identifier blkdebug needs to be in to +# actually trigger the event; defaults to "any" +# +# @iotype: the type of I/O operations on which this error should +# be injected; defaults to "all read, write, +# write-zeroes, discard, and flush operations" +# (since: 4.1) +# +# @errno: error identifier (errno) to be returned; defaults to +# EIO +# +# @sector: specifies the sector index which has to be affected +# in order to actually trigger the event; defaults to "any +# sector" +# +# @once: disables further events after this one has been +# triggered; defaults to false +# +# @immediately: fail immediately; defaults to false +# +# Since: 2.9 +## +{ 'struct': 'BlkdebugInjectErrorOptions', + 'data': { 'event': 'BlkdebugEvent', + '*state': 'int', + '*iotype': 'BlkdebugIOType', + '*errno': 'int', + '*sector': 'int', + '*once': 'bool', + '*immediately': 'bool' } } + +## +# @BlkdebugSetStateOptions: +# +# Describes a single state-change event for blkdebug. +# +# @event: trigger event +# +# @state: the current state identifier blkdebug needs to be in; +# defaults to "any" +# +# @new_state: the state identifier blkdebug is supposed to assume if +# this event is triggered +# +# Since: 2.9 +## +{ 'struct': 'BlkdebugSetStateOptions', + 'data': { 'event': 'BlkdebugEvent', + '*state': 'int', + 'new_state': 'int' } } + +## +# @BlockdevOptionsBlkdebug: +# +# Driver specific block device options for blkdebug. +# +# @image: underlying raw block device (or image file) +# +# @config: filename of the configuration file +# +# @align: required alignment for requests in bytes, must be +# positive power of 2, or 0 for default +# +# @max-transfer: maximum size for I/O transfers in bytes, must be +# positive multiple of @align and of the underlying +# file's request alignment (but need not be a power of +# 2), or 0 for default (since 2.10) +# +# @opt-write-zero: preferred alignment for write zero requests in bytes, +# must be positive multiple of @align and of the +# underlying file's request alignment (but need not be a +# power of 2), or 0 for default (since 2.10) +# +# @max-write-zero: maximum size for write zero requests in bytes, must be +# positive multiple of @align, of @opt-write-zero, and of +# the underlying file's request alignment (but need not +# be a power of 2), or 0 for default (since 2.10) +# +# @opt-discard: preferred alignment for discard requests in bytes, must +# be positive multiple of @align and of the underlying +# file's request alignment (but need not be a power of +# 2), or 0 for default (since 2.10) +# +# @max-discard: maximum size for discard requests in bytes, must be +# positive multiple of @align, of @opt-discard, and of +# the underlying file's request alignment (but need not +# be a power of 2), or 0 for default (since 2.10) +# +# @inject-error: array of error injection descriptions +# +# @set-state: array of state-change descriptions +# +# @take-child-perms: Permissions to take on @image in addition to what +# is necessary anyway (which depends on how the +# blkdebug node is used). Defaults to none. +# (since 5.0) +# +# @unshare-child-perms: Permissions not to share on @image in addition +# to what cannot be shared anyway (which depends +# on how the blkdebug node is used). Defaults +# to none. (since 5.0) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsBlkdebug', + 'data': { 'image': 'BlockdevRef', + '*config': 'str', + '*align': 'int', '*max-transfer': 'int32', + '*opt-write-zero': 'int32', '*max-write-zero': 'int32', + '*opt-discard': 'int32', '*max-discard': 'int32', + '*inject-error': ['BlkdebugInjectErrorOptions'], + '*set-state': ['BlkdebugSetStateOptions'], + '*take-child-perms': ['BlockPermission'], + '*unshare-child-perms': ['BlockPermission'] } } + +## +# @BlockdevOptionsBlklogwrites: +# +# Driver specific block device options for blklogwrites. +# +# @file: block device +# +# @log: block device used to log writes to @file +# +# @log-sector-size: sector size used in logging writes to @file, determines +# granularity of offsets and sizes of writes (default: 512) +# +# @log-append: append to an existing log (default: false) +# +# @log-super-update-interval: interval of write requests after which the log +# super block is updated to disk (default: 4096) +# +# Since: 3.0 +## +{ 'struct': 'BlockdevOptionsBlklogwrites', + 'data': { 'file': 'BlockdevRef', + 'log': 'BlockdevRef', + '*log-sector-size': 'uint32', + '*log-append': 'bool', + '*log-super-update-interval': 'uint64' } } + +## +# @BlockdevOptionsBlkverify: +# +# Driver specific block device options for blkverify. +# +# @test: block device to be tested +# +# @raw: raw image used for verification +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsBlkverify', + 'data': { 'test': 'BlockdevRef', + 'raw': 'BlockdevRef' } } + +## +# @BlockdevOptionsBlkreplay: +# +# Driver specific block device options for blkreplay. +# +# @image: disk image which should be controlled with blkreplay +# +# Since: 4.2 +## +{ 'struct': 'BlockdevOptionsBlkreplay', + 'data': { 'image': 'BlockdevRef' } } + +## +# @QuorumReadPattern: +# +# An enumeration of quorum read patterns. +# +# @quorum: read all the children and do a quorum vote on reads +# +# @fifo: read only from the first child that has not failed +# +# Since: 2.9 +## +{ 'enum': 'QuorumReadPattern', 'data': [ 'quorum', 'fifo' ] } + +## +# @BlockdevOptionsQuorum: +# +# Driver specific block device options for Quorum +# +# @blkverify: true if the driver must print content mismatch +# set to false by default +# +# @children: the children block devices to use +# +# @vote-threshold: the vote limit under which a read will fail +# +# @rewrite-corrupted: rewrite corrupted data when quorum is reached +# (Since 2.1) +# +# @read-pattern: choose read pattern and set to quorum by default +# (Since 2.2) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsQuorum', + 'data': { '*blkverify': 'bool', + 'children': [ 'BlockdevRef' ], + 'vote-threshold': 'int', + '*rewrite-corrupted': 'bool', + '*read-pattern': 'QuorumReadPattern' } } + +## +# @BlockdevOptionsGluster: +# +# Driver specific block device options for Gluster +# +# @volume: name of gluster volume where VM image resides +# +# @path: absolute path to image file in gluster volume +# +# @server: gluster servers description +# +# @debug: libgfapi log level (default '4' which is Error) +# (Since 2.8) +# +# @logfile: libgfapi log file (default /dev/stderr) (Since 2.8) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsGluster', + 'data': { 'volume': 'str', + 'path': 'str', + 'server': ['SocketAddress'], + '*debug': 'int', + '*logfile': 'str' } } + +## +# @IscsiTransport: +# +# An enumeration of libiscsi transport types +# +# Since: 2.9 +## +{ 'enum': 'IscsiTransport', + 'data': [ 'tcp', 'iser' ] } + +## +# @IscsiHeaderDigest: +# +# An enumeration of header digests supported by libiscsi +# +# Since: 2.9 +## +{ 'enum': 'IscsiHeaderDigest', + 'prefix': 'QAPI_ISCSI_HEADER_DIGEST', + 'data': [ 'crc32c', 'none', 'crc32c-none', 'none-crc32c' ] } + +## +# @BlockdevOptionsIscsi: +# +# @transport: The iscsi transport type +# +# @portal: The address of the iscsi portal +# +# @target: The target iqn name +# +# @lun: LUN to connect to. Defaults to 0. +# +# @user: User name to log in with. If omitted, no CHAP +# authentication is performed. +# +# @password-secret: The ID of a QCryptoSecret object providing +# the password for the login. This option is required if +# @user is specified. +# +# @initiator-name: The iqn name we want to identify to the target +# as. If this option is not specified, an initiator name is +# generated automatically. +# +# @header-digest: The desired header digest. Defaults to +# none-crc32c. +# +# @timeout: Timeout in seconds after which a request will +# timeout. 0 means no timeout and is the default. +# +# Driver specific block device options for iscsi +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsIscsi', + 'data': { 'transport': 'IscsiTransport', + 'portal': 'str', + 'target': 'str', + '*lun': 'int', + '*user': 'str', + '*password-secret': 'str', + '*initiator-name': 'str', + '*header-digest': 'IscsiHeaderDigest', + '*timeout': 'int' } } + + +## +# @RbdAuthMode: +# +# Since: 3.0 +## +{ 'enum': 'RbdAuthMode', + 'data': [ 'cephx', 'none' ] } + +## +# @RbdImageEncryptionFormat: +# +# Since: 6.1 +## +{ 'enum': 'RbdImageEncryptionFormat', + 'data': [ 'luks', 'luks2' ] } + +## +# @RbdEncryptionOptionsLUKSBase: +# +# @key-secret: ID of a QCryptoSecret object providing a passphrase +# for unlocking the encryption +# +# Since: 6.1 +## +{ 'struct': 'RbdEncryptionOptionsLUKSBase', + 'data': { 'key-secret': 'str' } } + +## +# @RbdEncryptionCreateOptionsLUKSBase: +# +# @cipher-alg: The encryption algorithm +# +# Since: 6.1 +## +{ 'struct': 'RbdEncryptionCreateOptionsLUKSBase', + 'base': 'RbdEncryptionOptionsLUKSBase', + 'data': { '*cipher-alg': 'QCryptoCipherAlgorithm' } } + +## +# @RbdEncryptionOptionsLUKS: +# +# Since: 6.1 +## +{ 'struct': 'RbdEncryptionOptionsLUKS', + 'base': 'RbdEncryptionOptionsLUKSBase', + 'data': { } } + +## +# @RbdEncryptionOptionsLUKS2: +# +# Since: 6.1 +## +{ 'struct': 'RbdEncryptionOptionsLUKS2', + 'base': 'RbdEncryptionOptionsLUKSBase', + 'data': { } } + +## +# @RbdEncryptionCreateOptionsLUKS: +# +# Since: 6.1 +## +{ 'struct': 'RbdEncryptionCreateOptionsLUKS', + 'base': 'RbdEncryptionCreateOptionsLUKSBase', + 'data': { } } + +## +# @RbdEncryptionCreateOptionsLUKS2: +# +# Since: 6.1 +## +{ 'struct': 'RbdEncryptionCreateOptionsLUKS2', + 'base': 'RbdEncryptionCreateOptionsLUKSBase', + 'data': { } } + +## +# @RbdEncryptionOptions: +# +# Since: 6.1 +## +{ 'union': 'RbdEncryptionOptions', + 'base': { 'format': 'RbdImageEncryptionFormat' }, + 'discriminator': 'format', + 'data': { 'luks': 'RbdEncryptionOptionsLUKS', + 'luks2': 'RbdEncryptionOptionsLUKS2' } } + +## +# @RbdEncryptionCreateOptions: +# +# Since: 6.1 +## +{ 'union': 'RbdEncryptionCreateOptions', + 'base': { 'format': 'RbdImageEncryptionFormat' }, + 'discriminator': 'format', + 'data': { 'luks': 'RbdEncryptionCreateOptionsLUKS', + 'luks2': 'RbdEncryptionCreateOptionsLUKS2' } } + +## +# @BlockdevOptionsRbd: +# +# @pool: Ceph pool name. +# +# @namespace: Rados namespace name in the Ceph pool. (Since 5.0) +# +# @image: Image name in the Ceph pool. +# +# @conf: path to Ceph configuration file. Values +# in the configuration file will be overridden by +# options specified via QAPI. +# +# @snapshot: Ceph snapshot name. +# +# @encrypt: Image encryption options. (Since 6.1) +# +# @user: Ceph id name. +# +# @auth-client-required: Acceptable authentication modes. +# This maps to Ceph configuration option +# "auth_client_required". (Since 3.0) +# +# @key-secret: ID of a QCryptoSecret object providing a key +# for cephx authentication. +# This maps to Ceph configuration option +# "key". (Since 3.0) +# +# @server: Monitor host address and port. This maps +# to the "mon_host" Ceph option. +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsRbd', + 'data': { 'pool': 'str', + '*namespace': 'str', + 'image': 'str', + '*conf': 'str', + '*snapshot': 'str', + '*encrypt': 'RbdEncryptionOptions', + '*user': 'str', + '*auth-client-required': ['RbdAuthMode'], + '*key-secret': 'str', + '*server': ['InetSocketAddressBase'] } } + +## +# @ReplicationMode: +# +# An enumeration of replication modes. +# +# @primary: Primary mode, the vm's state will be sent to secondary QEMU. +# +# @secondary: Secondary mode, receive the vm's state from primary QEMU. +# +# Since: 2.9 +## +{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ], + 'if': 'CONFIG_REPLICATION' } + +## +# @BlockdevOptionsReplication: +# +# Driver specific block device options for replication +# +# @mode: the replication mode +# +# @top-id: In secondary mode, node name or device ID of the root +# node who owns the replication node chain. Must not be given in +# primary mode. +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsReplication', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { 'mode': 'ReplicationMode', + '*top-id': 'str' }, + 'if': 'CONFIG_REPLICATION' } + +## +# @NFSTransport: +# +# An enumeration of NFS transport types +# +# @inet: TCP transport +# +# Since: 2.9 +## +{ 'enum': 'NFSTransport', + 'data': [ 'inet' ] } + +## +# @NFSServer: +# +# Captures the address of the socket +# +# @type: transport type used for NFS (only TCP supported) +# +# @host: host address for NFS server +# +# Since: 2.9 +## +{ 'struct': 'NFSServer', + 'data': { 'type': 'NFSTransport', + 'host': 'str' } } + +## +# @BlockdevOptionsNfs: +# +# Driver specific block device option for NFS +# +# @server: host address +# +# @path: path of the image on the host +# +# @user: UID value to use when talking to the +# server (defaults to 65534 on Windows and getuid() +# on unix) +# +# @group: GID value to use when talking to the +# server (defaults to 65534 on Windows and getgid() +# in unix) +# +# @tcp-syn-count: number of SYNs during the session +# establishment (defaults to libnfs default) +# +# @readahead-size: set the readahead size in bytes (defaults +# to libnfs default) +# +# @page-cache-size: set the pagecache size in bytes (defaults +# to libnfs default) +# +# @debug: set the NFS debug level (max 2) (defaults +# to libnfs default) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsNfs', + 'data': { 'server': 'NFSServer', + 'path': 'str', + '*user': 'int', + '*group': 'int', + '*tcp-syn-count': 'int', + '*readahead-size': 'int', + '*page-cache-size': 'int', + '*debug': 'int' } } + +## +# @BlockdevOptionsCurlBase: +# +# Driver specific block device options shared by all protocols supported by the +# curl backend. +# +# @url: URL of the image file +# +# @readahead: Size of the read-ahead cache; must be a multiple of +# 512 (defaults to 256 kB) +# +# @timeout: Timeout for connections, in seconds (defaults to 5) +# +# @username: Username for authentication (defaults to none) +# +# @password-secret: ID of a QCryptoSecret object providing a password +# for authentication (defaults to no password) +# +# @proxy-username: Username for proxy authentication (defaults to none) +# +# @proxy-password-secret: ID of a QCryptoSecret object providing a password +# for proxy authentication (defaults to no password) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsCurlBase', + 'data': { 'url': 'str', + '*readahead': 'int', + '*timeout': 'int', + '*username': 'str', + '*password-secret': 'str', + '*proxy-username': 'str', + '*proxy-password-secret': 'str' } } + +## +# @BlockdevOptionsCurlHttp: +# +# Driver specific block device options for HTTP connections over the curl +# backend. URLs must start with "http://". +# +# @cookie: List of cookies to set; format is +# "name1=content1; name2=content2;" as explained by +# CURLOPT_COOKIE(3). Defaults to no cookies. +# +# @cookie-secret: ID of a QCryptoSecret object providing the cookie data in a +# secure way. See @cookie for the format. (since 2.10) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsCurlHttp', + 'base': 'BlockdevOptionsCurlBase', + 'data': { '*cookie': 'str', + '*cookie-secret': 'str'} } + +## +# @BlockdevOptionsCurlHttps: +# +# Driver specific block device options for HTTPS connections over the curl +# backend. URLs must start with "https://". +# +# @cookie: List of cookies to set; format is +# "name1=content1; name2=content2;" as explained by +# CURLOPT_COOKIE(3). Defaults to no cookies. +# +# @sslverify: Whether to verify the SSL certificate's validity (defaults to +# true) +# +# @cookie-secret: ID of a QCryptoSecret object providing the cookie data in a +# secure way. See @cookie for the format. (since 2.10) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsCurlHttps', + 'base': 'BlockdevOptionsCurlBase', + 'data': { '*cookie': 'str', + '*sslverify': 'bool', + '*cookie-secret': 'str'} } + +## +# @BlockdevOptionsCurlFtp: +# +# Driver specific block device options for FTP connections over the curl +# backend. URLs must start with "ftp://". +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsCurlFtp', + 'base': 'BlockdevOptionsCurlBase', + 'data': { } } + +## +# @BlockdevOptionsCurlFtps: +# +# Driver specific block device options for FTPS connections over the curl +# backend. URLs must start with "ftps://". +# +# @sslverify: Whether to verify the SSL certificate's validity (defaults to +# true) +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsCurlFtps', + 'base': 'BlockdevOptionsCurlBase', + 'data': { '*sslverify': 'bool' } } + +## +# @BlockdevOptionsNbd: +# +# Driver specific block device options for NBD. +# +# @server: NBD server address +# +# @export: export name +# +# @tls-creds: TLS credentials ID +# +# @x-dirty-bitmap: A metadata context name such as "qemu:dirty-bitmap:NAME" +# or "qemu:allocation-depth" to query in place of the +# traditional "base:allocation" block status (see +# NBD_OPT_LIST_META_CONTEXT in the NBD protocol; and +# yes, naming this option x-context would have made +# more sense) (since 3.0) +# +# @reconnect-delay: On an unexpected disconnect, the nbd client tries to +# connect again until succeeding or encountering a serious +# error. During the first @reconnect-delay seconds, all +# requests are paused and will be rerun on a successful +# reconnect. After that time, any delayed requests and all +# future requests before a successful reconnect will +# immediately fail. Default 0 (Since 4.2) +# +# Features: +# @unstable: Member @x-dirty-bitmap is experimental. +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsNbd', + 'data': { 'server': 'SocketAddress', + '*export': 'str', + '*tls-creds': 'str', + '*x-dirty-bitmap': { 'type': 'str', 'features': [ 'unstable' ] }, + '*reconnect-delay': 'uint32' } } + +## +# @BlockdevOptionsRaw: +# +# Driver specific block device options for the raw driver. +# +# @offset: position where the block device starts +# @size: the assumed size of the device +# +# Since: 2.9 +## +{ 'struct': 'BlockdevOptionsRaw', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { '*offset': 'int', '*size': 'int' } } + +## +# @BlockdevOptionsThrottle: +# +# Driver specific block device options for the throttle driver +# +# @throttle-group: the name of the throttle-group object to use. It +# must already exist. +# @file: reference to or definition of the data source block device +# Since: 2.11 +## +{ 'struct': 'BlockdevOptionsThrottle', + 'data': { 'throttle-group': 'str', + 'file' : 'BlockdevRef' + } } + +## +# @BlockdevOptionsCor: +# +# Driver specific block device options for the copy-on-read driver. +# +# @bottom: The name of a non-filter node (allocation-bearing layer) that +# limits the COR operations in the backing chain (inclusive), so +# that no data below this node will be copied by this filter. +# If option is absent, the limit is not applied, so that data +# from all backing layers may be copied. +# +# Since: 6.0 +## +{ 'struct': 'BlockdevOptionsCor', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { '*bottom': 'str' } } + +## +# @BlockdevOptionsCbw: +# +# Driver specific block device options for the copy-before-write driver, +# which does so called copy-before-write operations: when data is +# written to the filter, the filter first reads corresponding blocks +# from its file child and copies them to @target child. After successfully +# copying, the write request is propagated to file child. If copying +# fails, the original write request is failed too and no data is written +# to file child. +# +# @target: The target for copy-before-write operations. +# +# Since: 6.2 +## +{ 'struct': 'BlockdevOptionsCbw', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { 'target': 'BlockdevRef' } } + +## +# @BlockdevOptions: +# +# Options for creating a block device. Many options are available for all +# block devices, independent of the block driver: +# +# @driver: block driver name +# @node-name: the node name of the new node (Since 2.0). +# This option is required on the top level of blockdev-add. +# Valid node names start with an alphabetic character and may +# contain only alphanumeric characters, '-', '.' and '_'. Their +# maximum length is 31 characters. +# @discard: discard-related options (default: ignore) +# @cache: cache-related options +# @read-only: whether the block device should be read-only (default: false). +# Note that some block drivers support only read-only access, +# either generally or in certain configurations. In this case, +# the default value does not work and the option must be +# specified explicitly. +# @auto-read-only: if true and @read-only is false, QEMU may automatically +# decide not to open the image read-write as requested, but +# fall back to read-only instead (and switch between the modes +# later), e.g. depending on whether the image file is writable +# or whether a writing user is attached to the node +# (default: false, since 3.1) +# @detect-zeroes: detect and optimize zero writes (Since 2.1) +# (default: off) +# @force-share: force share all permission on added nodes. +# Requires read-only=true. (Since 2.10) +# +# Remaining options are determined by the block driver. +# +# Since: 2.9 +## +{ 'union': 'BlockdevOptions', + 'base': { 'driver': 'BlockdevDriver', + '*node-name': 'str', + '*discard': 'BlockdevDiscardOptions', + '*cache': 'BlockdevCacheOptions', + '*read-only': 'bool', + '*auto-read-only': 'bool', + '*force-share': 'bool', + '*detect-zeroes': 'BlockdevDetectZeroesOptions' }, + 'discriminator': 'driver', + 'data': { + 'blkdebug': 'BlockdevOptionsBlkdebug', + 'blklogwrites':'BlockdevOptionsBlklogwrites', + 'blkverify': 'BlockdevOptionsBlkverify', + 'blkreplay': 'BlockdevOptionsBlkreplay', + 'bochs': 'BlockdevOptionsGenericFormat', + 'cloop': 'BlockdevOptionsGenericFormat', + 'compress': 'BlockdevOptionsGenericFormat', + 'copy-before-write':'BlockdevOptionsCbw', + 'copy-on-read':'BlockdevOptionsCor', + 'dmg': 'BlockdevOptionsGenericFormat', + 'file': 'BlockdevOptionsFile', + 'ftp': 'BlockdevOptionsCurlFtp', + 'ftps': 'BlockdevOptionsCurlFtps', + 'gluster': 'BlockdevOptionsGluster', + 'host_cdrom': { 'type': 'BlockdevOptionsFile', + 'if': 'HAVE_HOST_BLOCK_DEVICE' }, + 'host_device': { 'type': 'BlockdevOptionsFile', + 'if': 'HAVE_HOST_BLOCK_DEVICE' }, + 'http': 'BlockdevOptionsCurlHttp', + 'https': 'BlockdevOptionsCurlHttps', + 'iscsi': 'BlockdevOptionsIscsi', + 'luks': 'BlockdevOptionsLUKS', + 'nbd': 'BlockdevOptionsNbd', + 'nfs': 'BlockdevOptionsNfs', + 'null-aio': 'BlockdevOptionsNull', + 'null-co': 'BlockdevOptionsNull', + 'nvme': 'BlockdevOptionsNVMe', + 'parallels': 'BlockdevOptionsGenericFormat', + 'preallocate':'BlockdevOptionsPreallocate', + 'qcow2': 'BlockdevOptionsQcow2', + 'qcow': 'BlockdevOptionsQcow', + 'qed': 'BlockdevOptionsGenericCOWFormat', + 'quorum': 'BlockdevOptionsQuorum', + 'raw': 'BlockdevOptionsRaw', + 'rbd': 'BlockdevOptionsRbd', + 'replication': { 'type': 'BlockdevOptionsReplication', + 'if': 'CONFIG_REPLICATION' }, + 'ssh': 'BlockdevOptionsSsh', + 'throttle': 'BlockdevOptionsThrottle', + 'vdi': 'BlockdevOptionsGenericFormat', + 'vhdx': 'BlockdevOptionsGenericFormat', + 'vmdk': 'BlockdevOptionsGenericCOWFormat', + 'vpc': 'BlockdevOptionsGenericFormat', + 'vvfat': 'BlockdevOptionsVVFAT' + } } + +## +# @BlockdevRef: +# +# Reference to a block device. +# +# @definition: defines a new block device inline +# @reference: references the ID of an existing block device +# +# Since: 2.9 +## +{ 'alternate': 'BlockdevRef', + 'data': { 'definition': 'BlockdevOptions', + 'reference': 'str' } } + +## +# @BlockdevRefOrNull: +# +# Reference to a block device. +# +# @definition: defines a new block device inline +# @reference: references the ID of an existing block device. +# An empty string means that no block device should +# be referenced. Deprecated; use null instead. +# @null: No block device should be referenced (since 2.10) +# +# Since: 2.9 +## +{ 'alternate': 'BlockdevRefOrNull', + 'data': { 'definition': 'BlockdevOptions', + 'reference': 'str', + 'null': 'null' } } + +## +# @blockdev-add: +# +# Creates a new block device. +# +# Since: 2.9 +# +# Example: +# +# 1. +# -> { "execute": "blockdev-add", +# "arguments": { +# "driver": "qcow2", +# "node-name": "test1", +# "file": { +# "driver": "file", +# "filename": "test.qcow2" +# } +# } +# } +# <- { "return": {} } +# +# 2. +# -> { "execute": "blockdev-add", +# "arguments": { +# "driver": "qcow2", +# "node-name": "node0", +# "discard": "unmap", +# "cache": { +# "direct": true +# }, +# "file": { +# "driver": "file", +# "filename": "/tmp/test.qcow2" +# }, +# "backing": { +# "driver": "raw", +# "file": { +# "driver": "file", +# "filename": "/dev/fdset/4" +# } +# } +# } +# } +# +# <- { "return": {} } +# +## +{ 'command': 'blockdev-add', 'data': 'BlockdevOptions', 'boxed': true } + +## +# @blockdev-reopen: +# +# Reopens one or more block devices using the given set of options. +# Any option not specified will be reset to its default value regardless +# of its previous status. If an option cannot be changed or a particular +# driver does not support reopening then the command will return an +# error. All devices in the list are reopened in one transaction, so +# if one of them fails then the whole transaction is cancelled. +# +# The command receives a list of block devices to reopen. For each one +# of them, the top-level @node-name option (from BlockdevOptions) must be +# specified and is used to select the block device to be reopened. +# Other @node-name options must be either omitted or set to the +# current name of the appropriate node. This command won't change any +# node name and any attempt to do it will result in an error. +# +# In the case of options that refer to child nodes, the behavior of +# this command depends on the value: +# +# 1) A set of options (BlockdevOptions): the child is reopened with +# the specified set of options. +# +# 2) A reference to the current child: the child is reopened using +# its existing set of options. +# +# 3) A reference to a different node: the current child is replaced +# with the specified one. +# +# 4) NULL: the current child (if any) is detached. +# +# Options (1) and (2) are supported in all cases. Option (3) is +# supported for @file and @backing, and option (4) for @backing only. +# +# Unlike with blockdev-add, the @backing option must always be present +# unless the node being reopened does not have a backing file and its +# image does not have a default backing file name as part of its +# metadata. +# +# Since: 6.1 +## +{ 'command': 'blockdev-reopen', + 'data': { 'options': ['BlockdevOptions'] } } + +## +# @blockdev-del: +# +# Deletes a block device that has been added using blockdev-add. +# The command will fail if the node is attached to a device or is +# otherwise being used. +# +# @node-name: Name of the graph node to delete. +# +# Since: 2.9 +# +# Example: +# +# -> { "execute": "blockdev-add", +# "arguments": { +# "driver": "qcow2", +# "node-name": "node0", +# "file": { +# "driver": "file", +# "filename": "test.qcow2" +# } +# } +# } +# <- { "return": {} } +# +# -> { "execute": "blockdev-del", +# "arguments": { "node-name": "node0" } +# } +# <- { "return": {} } +# +## +{ 'command': 'blockdev-del', 'data': { 'node-name': 'str' } } + +## +# @BlockdevCreateOptionsFile: +# +# Driver specific image creation options for file. +# +# @filename: Filename for the new image file +# @size: Size of the virtual disk in bytes +# @preallocation: Preallocation mode for the new image (default: off; +# allowed values: off, +# falloc (if CONFIG_POSIX_FALLOCATE), +# full (if CONFIG_POSIX)) +# @nocow: Turn off copy-on-write (valid only on btrfs; default: off) +# @extent-size-hint: Extent size hint to add to the image file; 0 for not +# adding an extent size hint (default: 1 MB, since 5.1) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsFile', + 'data': { 'filename': 'str', + 'size': 'size', + '*preallocation': 'PreallocMode', + '*nocow': 'bool', + '*extent-size-hint': 'size'} } + +## +# @BlockdevCreateOptionsGluster: +# +# Driver specific image creation options for gluster. +# +# @location: Where to store the new image file +# @size: Size of the virtual disk in bytes +# @preallocation: Preallocation mode for the new image (default: off; +# allowed values: off, +# falloc (if CONFIG_GLUSTERFS_FALLOCATE), +# full (if CONFIG_GLUSTERFS_ZEROFILL)) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsGluster', + 'data': { 'location': 'BlockdevOptionsGluster', + 'size': 'size', + '*preallocation': 'PreallocMode' } } + +## +# @BlockdevCreateOptionsLUKS: +# +# Driver specific image creation options for LUKS. +# +# @file: Node to create the image format on +# @size: Size of the virtual disk in bytes +# @preallocation: Preallocation mode for the new image +# (since: 4.2) +# (default: off; allowed values: off, metadata, falloc, full) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsLUKS', + 'base': 'QCryptoBlockCreateOptionsLUKS', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*preallocation': 'PreallocMode' } } + +## +# @BlockdevCreateOptionsNfs: +# +# Driver specific image creation options for NFS. +# +# @location: Where to store the new image file +# @size: Size of the virtual disk in bytes +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsNfs', + 'data': { 'location': 'BlockdevOptionsNfs', + 'size': 'size' } } + +## +# @BlockdevCreateOptionsParallels: +# +# Driver specific image creation options for parallels. +# +# @file: Node to create the image format on +# @size: Size of the virtual disk in bytes +# @cluster-size: Cluster size in bytes (default: 1 MB) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsParallels', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*cluster-size': 'size' } } + +## +# @BlockdevCreateOptionsQcow: +# +# Driver specific image creation options for qcow. +# +# @file: Node to create the image format on +# @size: Size of the virtual disk in bytes +# @backing-file: File name of the backing file if a backing file +# should be used +# @encrypt: Encryption options if the image should be encrypted +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsQcow', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*backing-file': 'str', + '*encrypt': 'QCryptoBlockCreateOptions' } } + +## +# @BlockdevQcow2Version: +# +# @v2: The original QCOW2 format as introduced in qemu 0.10 (version 2) +# @v3: The extended QCOW2 format as introduced in qemu 1.1 (version 3) +# +# Since: 2.12 +## +{ 'enum': 'BlockdevQcow2Version', + 'data': [ 'v2', 'v3' ] } + + +## +# @Qcow2CompressionType: +# +# Compression type used in qcow2 image file +# +# @zlib: zlib compression, see <http://zlib.net/> +# @zstd: zstd compression, see <http://github.com/facebook/zstd> +# +# Since: 5.1 +## +{ 'enum': 'Qcow2CompressionType', + 'data': [ 'zlib', { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] } + +## +# @BlockdevCreateOptionsQcow2: +# +# Driver specific image creation options for qcow2. +# +# @file: Node to create the image format on +# @data-file: Node to use as an external data file in which all guest +# data is stored so that only metadata remains in the qcow2 +# file (since: 4.0) +# @data-file-raw: True if the external data file must stay valid as a +# standalone (read-only) raw image without looking at qcow2 +# metadata (default: false; since: 4.0) +# @extended-l2: True to make the image have extended L2 entries +# (default: false; since 5.2) +# @size: Size of the virtual disk in bytes +# @version: Compatibility level (default: v3) +# @backing-file: File name of the backing file if a backing file +# should be used +# @backing-fmt: Name of the block driver to use for the backing file +# @encrypt: Encryption options if the image should be encrypted +# @cluster-size: qcow2 cluster size in bytes (default: 65536) +# @preallocation: Preallocation mode for the new image (default: off; +# allowed values: off, falloc, full, metadata) +# @lazy-refcounts: True if refcounts may be updated lazily (default: off) +# @refcount-bits: Width of reference counts in bits (default: 16) +# @compression-type: The image cluster compression method +# (default: zlib, since 5.1) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsQcow2', + 'data': { 'file': 'BlockdevRef', + '*data-file': 'BlockdevRef', + '*data-file-raw': 'bool', + '*extended-l2': 'bool', + 'size': 'size', + '*version': 'BlockdevQcow2Version', + '*backing-file': 'str', + '*backing-fmt': 'BlockdevDriver', + '*encrypt': 'QCryptoBlockCreateOptions', + '*cluster-size': 'size', + '*preallocation': 'PreallocMode', + '*lazy-refcounts': 'bool', + '*refcount-bits': 'int', + '*compression-type':'Qcow2CompressionType' } } + +## +# @BlockdevCreateOptionsQed: +# +# Driver specific image creation options for qed. +# +# @file: Node to create the image format on +# @size: Size of the virtual disk in bytes +# @backing-file: File name of the backing file if a backing file +# should be used +# @backing-fmt: Name of the block driver to use for the backing file +# @cluster-size: Cluster size in bytes (default: 65536) +# @table-size: L1/L2 table size (in clusters) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsQed', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*backing-file': 'str', + '*backing-fmt': 'BlockdevDriver', + '*cluster-size': 'size', + '*table-size': 'int' } } + +## +# @BlockdevCreateOptionsRbd: +# +# Driver specific image creation options for rbd/Ceph. +# +# @location: Where to store the new image file. This location cannot +# point to a snapshot. +# @size: Size of the virtual disk in bytes +# @cluster-size: RBD object size +# @encrypt: Image encryption options. (Since 6.1) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsRbd', + 'data': { 'location': 'BlockdevOptionsRbd', + 'size': 'size', + '*cluster-size' : 'size', + '*encrypt' : 'RbdEncryptionCreateOptions' } } + +## +# @BlockdevVmdkSubformat: +# +# Subformat options for VMDK images +# +# @monolithicSparse: Single file image with sparse cluster allocation +# +# @monolithicFlat: Single flat data image and a descriptor file +# +# @twoGbMaxExtentSparse: Data is split into 2GB (per virtual LBA) sparse extent +# files, in addition to a descriptor file +# +# @twoGbMaxExtentFlat: Data is split into 2GB (per virtual LBA) flat extent +# files, in addition to a descriptor file +# +# @streamOptimized: Single file image sparse cluster allocation, optimized +# for streaming over network. +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkSubformat', + 'data': [ 'monolithicSparse', 'monolithicFlat', 'twoGbMaxExtentSparse', + 'twoGbMaxExtentFlat', 'streamOptimized'] } + +## +# @BlockdevVmdkAdapterType: +# +# Adapter type info for VMDK images +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkAdapterType', + 'data': [ 'ide', 'buslogic', 'lsilogic', 'legacyESX'] } + +## +# @BlockdevCreateOptionsVmdk: +# +# Driver specific image creation options for VMDK. +# +# @file: Where to store the new image file. This refers to the image +# file for monolithcSparse and streamOptimized format, or the +# descriptor file for other formats. +# @size: Size of the virtual disk in bytes +# @extents: Where to store the data extents. Required for monolithcFlat, +# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For +# monolithicFlat, only one entry is required; for +# twoGbMaxExtent* formats, the number of entries required is +# calculated as extent_number = virtual_size / 2GB. Providing +# more extents than will be used is an error. +# @subformat: The subformat of the VMDK image. Default: "monolithicSparse". +# @backing-file: The path of backing file. Default: no backing file is used. +# @adapter-type: The adapter type used to fill in the descriptor. Default: ide. +# @hwversion: Hardware version. The meaningful options are "4" or "6". +# Default: "4". +# @toolsversion: VMware guest tools version. +# Default: "2147483647" (Since 6.2) +# @zeroed-grain: Whether to enable zeroed-grain feature for sparse subformats. +# Default: false. +# +# Since: 4.0 +## +{ 'struct': 'BlockdevCreateOptionsVmdk', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*extents': ['BlockdevRef'], + '*subformat': 'BlockdevVmdkSubformat', + '*backing-file': 'str', + '*adapter-type': 'BlockdevVmdkAdapterType', + '*hwversion': 'str', + '*toolsversion': 'str', + '*zeroed-grain': 'bool' } } + + +## +# @BlockdevCreateOptionsSsh: +# +# Driver specific image creation options for SSH. +# +# @location: Where to store the new image file +# @size: Size of the virtual disk in bytes +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsSsh', + 'data': { 'location': 'BlockdevOptionsSsh', + 'size': 'size' } } + +## +# @BlockdevCreateOptionsVdi: +# +# Driver specific image creation options for VDI. +# +# @file: Node to create the image format on +# @size: Size of the virtual disk in bytes +# @preallocation: Preallocation mode for the new image (default: off; +# allowed values: off, metadata) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsVdi', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*preallocation': 'PreallocMode' } } + +## +# @BlockdevVhdxSubformat: +# +# @dynamic: Growing image file +# @fixed: Preallocated fixed-size image file +# +# Since: 2.12 +## +{ 'enum': 'BlockdevVhdxSubformat', + 'data': [ 'dynamic', 'fixed' ] } + +## +# @BlockdevCreateOptionsVhdx: +# +# Driver specific image creation options for vhdx. +# +# @file: Node to create the image format on +# @size: Size of the virtual disk in bytes +# @log-size: Log size in bytes, must be a multiple of 1 MB +# (default: 1 MB) +# @block-size: Block size in bytes, must be a multiple of 1 MB and not +# larger than 256 MB (default: automatically choose a block +# size depending on the image size) +# @subformat: vhdx subformat (default: dynamic) +# @block-state-zero: Force use of payload blocks of type 'ZERO'. Non-standard, +# but default. Do not set to 'off' when using 'qemu-img +# convert' with subformat=dynamic. +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsVhdx', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*log-size': 'size', + '*block-size': 'size', + '*subformat': 'BlockdevVhdxSubformat', + '*block-state-zero': 'bool' } } + +## +# @BlockdevVpcSubformat: +# +# @dynamic: Growing image file +# @fixed: Preallocated fixed-size image file +# +# Since: 2.12 +## +{ 'enum': 'BlockdevVpcSubformat', + 'data': [ 'dynamic', 'fixed' ] } + +## +# @BlockdevCreateOptionsVpc: +# +# Driver specific image creation options for vpc (VHD). +# +# @file: Node to create the image format on +# @size: Size of the virtual disk in bytes +# @subformat: vhdx subformat (default: dynamic) +# @force-size: Force use of the exact byte size instead of rounding to the +# next size that can be represented in CHS geometry +# (default: false) +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsVpc', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*subformat': 'BlockdevVpcSubformat', + '*force-size': 'bool' } } + +## +# @BlockdevCreateOptions: +# +# Options for creating an image format on a given node. +# +# @driver: block driver to create the image format +# +# Since: 2.12 +## +{ 'union': 'BlockdevCreateOptions', + 'base': { + 'driver': 'BlockdevDriver' }, + 'discriminator': 'driver', + 'data': { + 'file': 'BlockdevCreateOptionsFile', + 'gluster': 'BlockdevCreateOptionsGluster', + 'luks': 'BlockdevCreateOptionsLUKS', + 'nfs': 'BlockdevCreateOptionsNfs', + 'parallels': 'BlockdevCreateOptionsParallels', + 'qcow': 'BlockdevCreateOptionsQcow', + 'qcow2': 'BlockdevCreateOptionsQcow2', + 'qed': 'BlockdevCreateOptionsQed', + 'rbd': 'BlockdevCreateOptionsRbd', + 'ssh': 'BlockdevCreateOptionsSsh', + 'vdi': 'BlockdevCreateOptionsVdi', + 'vhdx': 'BlockdevCreateOptionsVhdx', + 'vmdk': 'BlockdevCreateOptionsVmdk', + 'vpc': 'BlockdevCreateOptionsVpc' + } } + +## +# @blockdev-create: +# +# Starts a job to create an image format on a given node. The job is +# automatically finalized, but a manual job-dismiss is required. +# +# @job-id: Identifier for the newly created job. +# +# @options: Options for the image creation. +# +# Since: 3.0 +## +{ 'command': 'blockdev-create', + 'data': { 'job-id': 'str', + 'options': 'BlockdevCreateOptions' } } + +## +# @BlockdevAmendOptionsLUKS: +# +# Driver specific image amend options for LUKS. +# +# Since: 5.1 +## +{ 'struct': 'BlockdevAmendOptionsLUKS', + 'base': 'QCryptoBlockAmendOptionsLUKS', + 'data': { } +} + +## +# @BlockdevAmendOptionsQcow2: +# +# Driver specific image amend options for qcow2. +# For now, only encryption options can be amended +# +# @encrypt Encryption options to be amended +# +# Since: 5.1 +## +{ 'struct': 'BlockdevAmendOptionsQcow2', + 'data': { '*encrypt': 'QCryptoBlockAmendOptions' } } + +## +# @BlockdevAmendOptions: +# +# Options for amending an image format +# +# @driver: Block driver of the node to amend. +# +# Since: 5.1 +## +{ 'union': 'BlockdevAmendOptions', + 'base': { + 'driver': 'BlockdevDriver' }, + 'discriminator': 'driver', + 'data': { + 'luks': 'BlockdevAmendOptionsLUKS', + 'qcow2': 'BlockdevAmendOptionsQcow2' } } + +## +# @x-blockdev-amend: +# +# Starts a job to amend format specific options of an existing open block device +# The job is automatically finalized, but a manual job-dismiss is required. +# +# @job-id: Identifier for the newly created job. +# +# @node-name: Name of the block node to work on +# +# @options: Options (driver specific) +# +# @force: Allow unsafe operations, format specific +# For luks that allows erase of the last active keyslot +# (permanent loss of data), +# and replacement of an active keyslot +# (possible loss of data if IO error happens) +# +# Features: +# @unstable: This command is experimental. +# +# Since: 5.1 +## +{ 'command': 'x-blockdev-amend', + 'data': { 'job-id': 'str', + 'node-name': 'str', + 'options': 'BlockdevAmendOptions', + '*force': 'bool' }, + 'features': [ 'unstable' ] } + +## +# @BlockErrorAction: +# +# An enumeration of action that has been taken when a DISK I/O occurs +# +# @ignore: error has been ignored +# +# @report: error has been reported to the device +# +# @stop: error caused VM to be stopped +# +# Since: 2.1 +## +{ 'enum': 'BlockErrorAction', + 'data': [ 'ignore', 'report', 'stop' ] } + + +## +# @BLOCK_IMAGE_CORRUPTED: +# +# Emitted when a disk image is being marked corrupt. The image can be +# identified by its device or node name. The 'device' field is always +# present for compatibility reasons, but it can be empty ("") if the +# image does not have a device name associated. +# +# @device: device name. This is always present for compatibility +# reasons, but it can be empty ("") if the image does not +# have a device name associated. +# +# @node-name: node name (Since: 2.4) +# +# @msg: informative message for human consumption, such as the kind of +# corruption being detected. It should not be parsed by machine as it is +# not guaranteed to be stable +# +# @offset: if the corruption resulted from an image access, this is +# the host's access offset into the image +# +# @size: if the corruption resulted from an image access, this is +# the access size +# +# @fatal: if set, the image is marked corrupt and therefore unusable after this +# event and must be repaired (Since 2.2; before, every +# BLOCK_IMAGE_CORRUPTED event was fatal) +# +# Note: If action is "stop", a STOP event will eventually follow the +# BLOCK_IO_ERROR event. +# +# Example: +# +# <- { "event": "BLOCK_IMAGE_CORRUPTED", +# "data": { "device": "ide0-hd0", "node-name": "node0", +# "msg": "Prevented active L1 table overwrite", "offset": 196608, +# "size": 65536 }, +# "timestamp": { "seconds": 1378126126, "microseconds": 966463 } } +# +# Since: 1.7 +## +{ 'event': 'BLOCK_IMAGE_CORRUPTED', + 'data': { 'device' : 'str', + '*node-name' : 'str', + 'msg' : 'str', + '*offset' : 'int', + '*size' : 'int', + 'fatal' : 'bool' } } + +## +# @BLOCK_IO_ERROR: +# +# Emitted when a disk I/O error occurs +# +# @device: device name. This is always present for compatibility +# reasons, but it can be empty ("") if the image does not +# have a device name associated. +# +# @node-name: node name. Note that errors may be reported for the root node +# that is directly attached to a guest device rather than for the +# node where the error occurred. The node name is not present if +# the drive is empty. (Since: 2.8) +# +# @operation: I/O operation +# +# @action: action that has been taken +# +# @nospace: true if I/O error was caused due to a no-space +# condition. This key is only present if query-block's +# io-status is present, please see query-block documentation +# for more information (since: 2.2) +# +# @reason: human readable string describing the error cause. +# (This field is a debugging aid for humans, it should not +# be parsed by applications) (since: 2.2) +# +# Note: If action is "stop", a STOP event will eventually follow the +# BLOCK_IO_ERROR event +# +# Since: 0.13 +# +# Example: +# +# <- { "event": "BLOCK_IO_ERROR", +# "data": { "device": "ide0-hd1", +# "node-name": "#block212", +# "operation": "write", +# "action": "stop" }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'BLOCK_IO_ERROR', + 'data': { 'device': 'str', '*node-name': 'str', + 'operation': 'IoOperationType', + 'action': 'BlockErrorAction', '*nospace': 'bool', + 'reason': 'str' } } + +## +# @BLOCK_JOB_COMPLETED: +# +# Emitted when a block job has completed +# +# @type: job type +# +# @device: The job identifier. Originally the device name but other +# values are allowed since QEMU 2.7 +# +# @len: maximum progress value +# +# @offset: current progress value. On success this is equal to len. +# On failure this is less than len +# +# @speed: rate limit, bytes per second +# +# @error: error message. 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 +# +# Since: 1.1 +# +# Example: +# +# <- { "event": "BLOCK_JOB_COMPLETED", +# "data": { "type": "stream", "device": "virtio-disk0", +# "len": 10737418240, "offset": 10737418240, +# "speed": 0 }, +# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +# +## +{ 'event': 'BLOCK_JOB_COMPLETED', + 'data': { 'type' : 'JobType', + 'device': 'str', + 'len' : 'int', + 'offset': 'int', + 'speed' : 'int', + '*error': 'str' } } + +## +# @BLOCK_JOB_CANCELLED: +# +# Emitted when a block job has been cancelled +# +# @type: job type +# +# @device: The job identifier. Originally the device name but other +# values are allowed since QEMU 2.7 +# +# @len: maximum progress value +# +# @offset: current progress value. On success this is equal to len. +# On failure this is less than len +# +# @speed: rate limit, bytes per second +# +# Since: 1.1 +# +# Example: +# +# <- { "event": "BLOCK_JOB_CANCELLED", +# "data": { "type": "stream", "device": "virtio-disk0", +# "len": 10737418240, "offset": 134217728, +# "speed": 0 }, +# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +# +## +{ 'event': 'BLOCK_JOB_CANCELLED', + 'data': { 'type' : 'JobType', + 'device': 'str', + 'len' : 'int', + 'offset': 'int', + 'speed' : 'int' } } + +## +# @BLOCK_JOB_ERROR: +# +# Emitted when a block job encounters an error +# +# @device: The job identifier. Originally the device name but other +# values are allowed since QEMU 2.7 +# +# @operation: I/O operation +# +# @action: action that has been taken +# +# Since: 1.3 +# +# Example: +# +# <- { "event": "BLOCK_JOB_ERROR", +# "data": { "device": "ide0-hd1", +# "operation": "write", +# "action": "stop" }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'BLOCK_JOB_ERROR', + 'data': { 'device' : 'str', + 'operation': 'IoOperationType', + 'action' : 'BlockErrorAction' } } + +## +# @BLOCK_JOB_READY: +# +# Emitted when a block job is ready to complete +# +# @type: job type +# +# @device: The job identifier. Originally the device name but other +# values are allowed since QEMU 2.7 +# +# @len: maximum progress value +# +# @offset: current progress value. On success this is equal to len. +# On failure this is less than len +# +# @speed: rate limit, bytes per second +# +# Note: The "ready to complete" status is always reset by a @BLOCK_JOB_ERROR +# event +# +# Since: 1.3 +# +# Example: +# +# <- { "event": "BLOCK_JOB_READY", +# "data": { "device": "drive0", "type": "mirror", "speed": 0, +# "len": 2097152, "offset": 2097152 } +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'BLOCK_JOB_READY', + 'data': { 'type' : 'JobType', + 'device': 'str', + 'len' : 'int', + 'offset': 'int', + 'speed' : 'int' } } + +## +# @BLOCK_JOB_PENDING: +# +# Emitted when a block job is awaiting explicit authorization to finalize graph +# changes via @block-job-finalize. If this job is part of a transaction, it will +# not emit this event until the transaction has converged first. +# +# @type: job type +# +# @id: The job identifier. +# +# Since: 2.12 +# +# Example: +# +# <- { "event": "BLOCK_JOB_WAITING", +# "data": { "device": "drive0", "type": "mirror" }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'BLOCK_JOB_PENDING', + 'data': { 'type' : 'JobType', + 'id' : 'str' } } + +## +# @PreallocMode: +# +# Preallocation mode of QEMU image file +# +# @off: no preallocation +# @metadata: preallocate only for metadata +# @falloc: like @full preallocation but allocate disk space by +# posix_fallocate() rather than writing data. +# @full: preallocate all data by writing it to the device to ensure +# disk space is really available. This data may or may not be +# zero, depending on the image format and storage. +# @full preallocation also sets up metadata correctly. +# +# Since: 2.2 +## +{ 'enum': 'PreallocMode', + 'data': [ 'off', 'metadata', 'falloc', 'full' ] } + +## +# @BLOCK_WRITE_THRESHOLD: +# +# Emitted when writes on block device reaches or exceeds the +# configured write threshold. For thin-provisioned devices, this +# means the device should be extended to avoid pausing for +# disk exhaustion. +# The event is one shot. Once triggered, it needs to be +# re-registered with another block-set-write-threshold command. +# +# @node-name: graph node name on which the threshold was exceeded. +# +# @amount-exceeded: amount of data which exceeded the threshold, in bytes. +# +# @write-threshold: last configured threshold, in bytes. +# +# Since: 2.3 +## +{ 'event': 'BLOCK_WRITE_THRESHOLD', + 'data': { 'node-name': 'str', + 'amount-exceeded': 'uint64', + 'write-threshold': 'uint64' } } + +## +# @block-set-write-threshold: +# +# Change the write threshold for a block drive. An event will be +# delivered if a write to this block drive crosses the configured +# threshold. The threshold is an offset, thus must be +# non-negative. Default is no write threshold. Setting the threshold +# to zero disables it. +# +# This is useful to transparently resize thin-provisioned drives without +# the guest OS noticing. +# +# @node-name: graph node name on which the threshold must be set. +# +# @write-threshold: configured threshold for the block device, bytes. +# Use 0 to disable the threshold. +# +# Since: 2.3 +# +# Example: +# +# -> { "execute": "block-set-write-threshold", +# "arguments": { "node-name": "mydev", +# "write-threshold": 17179869184 } } +# <- { "return": {} } +# +## +{ 'command': 'block-set-write-threshold', + 'data': { 'node-name': 'str', 'write-threshold': 'uint64' } } + +## +# @x-blockdev-change: +# +# Dynamically reconfigure the block driver state graph. It can be used +# to add, remove, insert or replace a graph node. Currently only the +# Quorum driver implements this feature to add or remove its child. This +# is useful to fix a broken quorum child. +# +# If @node is specified, it will be inserted under @parent. @child +# may not be specified in this case. If both @parent and @child are +# specified but @node is not, @child will be detached from @parent. +# +# @parent: the id or name of the parent node. +# +# @child: the name of a child under the given parent node. +# +# @node: the name of the node that will be added. +# +# Features: +# @unstable: This command is experimental, and its API is not stable. It +# does not support all kinds of operations, all kinds of +# children, nor all block drivers. +# +# FIXME Removing children from a quorum node means introducing +# gaps in the child indices. This cannot be represented in the +# 'children' list of BlockdevOptionsQuorum, as returned by +# .bdrv_refresh_filename(). +# +# Warning: The data in a new quorum child MUST be consistent +# with that of the rest of the array. +# +# Since: 2.7 +# +# Example: +# +# 1. Add a new node to a quorum +# -> { "execute": "blockdev-add", +# "arguments": { +# "driver": "raw", +# "node-name": "new_node", +# "file": { "driver": "file", +# "filename": "test.raw" } } } +# <- { "return": {} } +# -> { "execute": "x-blockdev-change", +# "arguments": { "parent": "disk1", +# "node": "new_node" } } +# <- { "return": {} } +# +# 2. Delete a quorum's node +# -> { "execute": "x-blockdev-change", +# "arguments": { "parent": "disk1", +# "child": "children.1" } } +# <- { "return": {} } +# +## +{ 'command': 'x-blockdev-change', + 'data' : { 'parent': 'str', + '*child': 'str', + '*node': 'str' }, + 'features': [ 'unstable' ] } + +## +# @x-blockdev-set-iothread: +# +# Move @node and its children into the @iothread. If @iothread is null then +# move @node and its children into the main loop. +# +# The node must not be attached to a BlockBackend. +# +# @node-name: the name of the block driver node +# +# @iothread: the name of the IOThread object or null for the main loop +# +# @force: true if the node and its children should be moved when a BlockBackend +# is already attached +# +# Features: +# @unstable: This command is experimental and intended for test cases that +# need control over IOThreads only. +# +# Since: 2.12 +# +# Example: +# +# 1. Move a node into an IOThread +# -> { "execute": "x-blockdev-set-iothread", +# "arguments": { "node-name": "disk1", +# "iothread": "iothread0" } } +# <- { "return": {} } +# +# 2. Move a node into the main loop +# -> { "execute": "x-blockdev-set-iothread", +# "arguments": { "node-name": "disk1", +# "iothread": null } } +# <- { "return": {} } +# +## +{ 'command': 'x-blockdev-set-iothread', + 'data' : { 'node-name': 'str', + 'iothread': 'StrOrNull', + '*force': 'bool' }, + 'features': [ 'unstable' ] } + +## +# @QuorumOpType: +# +# An enumeration of the quorum operation types +# +# @read: read operation +# +# @write: write operation +# +# @flush: flush operation +# +# Since: 2.6 +## +{ 'enum': 'QuorumOpType', + 'data': [ 'read', 'write', 'flush' ] } + +## +# @QUORUM_FAILURE: +# +# Emitted by the Quorum block driver if it fails to establish a quorum +# +# @reference: device name if defined else node name +# +# @sector-num: number of the first sector of the failed read operation +# +# @sectors-count: failed read operation sector count +# +# Note: This event is rate-limited. +# +# Since: 2.0 +# +# Example: +# +# <- { "event": "QUORUM_FAILURE", +# "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 }, +# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } +# +## +{ 'event': 'QUORUM_FAILURE', + 'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } } + +## +# @QUORUM_REPORT_BAD: +# +# Emitted to report a corruption of a Quorum file +# +# @type: quorum operation type (Since 2.6) +# +# @error: error message. Only present on failure. This field +# contains a human-readable error message. There are no semantics other +# than that the block layer reported an error and clients should not +# try to interpret the error string. +# +# @node-name: the graph node name of the block driver state +# +# @sector-num: number of the first sector of the failed read operation +# +# @sectors-count: failed read operation sector count +# +# Note: This event is rate-limited. +# +# Since: 2.0 +# +# Example: +# +# 1. Read operation +# +# { "event": "QUORUM_REPORT_BAD", +# "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5, +# "type": "read" }, +# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } +# +# 2. Flush operation +# +# { "event": "QUORUM_REPORT_BAD", +# "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120, +# "type": "flush", "error": "Broken pipe" }, +# "timestamp": { "seconds": 1456406829, "microseconds": 291763 } } +# +## +{ 'event': 'QUORUM_REPORT_BAD', + 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str', + 'sector-num': 'int', 'sectors-count': 'int' } } + +## +# @BlockdevSnapshotInternal: +# +# @device: the device name or node-name of a root node to generate the snapshot +# from +# +# @name: the name of the internal snapshot to be created +# +# Notes: In transaction, if @name is empty, or any snapshot matching @name +# exists, the operation will fail. Only some image formats support it, +# for example, qcow2, and rbd. +# +# Since: 1.7 +## +{ 'struct': 'BlockdevSnapshotInternal', + 'data': { 'device': 'str', 'name': 'str' } } + +## +# @blockdev-snapshot-internal-sync: +# +# Synchronously take an internal snapshot of a block device, when the +# format of the image used supports it. If the name is an empty +# string, or a snapshot with name already exists, the operation will +# fail. +# +# For the arguments, see the documentation of BlockdevSnapshotInternal. +# +# Returns: - nothing on success +# - If @device is not a valid block device, GenericError +# - If any snapshot matching @name exists, or @name is empty, +# GenericError +# - If the format of the image used does not support it, +# BlockFormatFeatureNotSupported +# +# Since: 1.7 +# +# Example: +# +# -> { "execute": "blockdev-snapshot-internal-sync", +# "arguments": { "device": "ide-hd0", +# "name": "snapshot0" } +# } +# <- { "return": {} } +# +## +{ 'command': 'blockdev-snapshot-internal-sync', + 'data': 'BlockdevSnapshotInternal' } + +## +# @blockdev-snapshot-delete-internal-sync: +# +# Synchronously delete an internal snapshot of a block device, when the format +# of the image used support it. The snapshot is identified by name or id or +# both. One of the name or id is required. Return SnapshotInfo for the +# successfully deleted snapshot. +# +# @device: the device name or node-name of a root node to delete the snapshot +# from +# +# @id: optional the snapshot's ID to be deleted +# +# @name: optional the snapshot's name to be deleted +# +# Returns: - SnapshotInfo on success +# - If @device is not a valid block device, GenericError +# - If snapshot not found, GenericError +# - If the format of the image used does not support it, +# BlockFormatFeatureNotSupported +# - If @id and @name are both not specified, GenericError +# +# Since: 1.7 +# +# Example: +# +# -> { "execute": "blockdev-snapshot-delete-internal-sync", +# "arguments": { "device": "ide-hd0", +# "name": "snapshot0" } +# } +# <- { "return": { +# "id": "1", +# "name": "snapshot0", +# "vm-state-size": 0, +# "date-sec": 1000012, +# "date-nsec": 10, +# "vm-clock-sec": 100, +# "vm-clock-nsec": 20, +# "icount": 220414 +# } +# } +# +## +{ 'command': 'blockdev-snapshot-delete-internal-sync', + 'data': { 'device': 'str', '*id': 'str', '*name': 'str'}, + 'returns': 'SnapshotInfo' } diff --git a/qapi/block-export.json b/qapi/block-export.json new file mode 100644 index 000000000..c1b92ce1c --- /dev/null +++ b/qapi/block-export.json @@ -0,0 +1,399 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# == Block device exports +## + +{ 'include': 'sockets.json' } + +## +# @NbdServerOptions: +# +# Keep this type consistent with the nbd-server-start arguments. The only +# intended difference is using SocketAddress instead of SocketAddressLegacy. +# +# @addr: Address on which to listen. +# @tls-creds: ID of the TLS credentials object (since 2.6). +# @tls-authz: ID of the QAuthZ authorization object used to validate +# the client's x509 distinguished name. This object is +# is only resolved at time of use, so can be deleted and +# recreated on the fly while the NBD server is active. +# If missing, it will default to denying access (since 4.0). +# @max-connections: The maximum number of connections to allow at the same +# time, 0 for unlimited. (since 5.2; default: 0) +# +# Since: 4.2 +## +{ 'struct': 'NbdServerOptions', + 'data': { 'addr': 'SocketAddress', + '*tls-creds': 'str', + '*tls-authz': 'str', + '*max-connections': 'uint32' } } + +## +# @nbd-server-start: +# +# Start an NBD server listening on the given host and port. Block +# devices can then be exported using @nbd-server-add. The NBD +# server will present them as named exports; for example, another +# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME". +# +# Keep this type consistent with the NbdServerOptions type. The only intended +# difference is using SocketAddressLegacy instead of SocketAddress. +# +# @addr: Address on which to listen. +# @tls-creds: ID of the TLS credentials object (since 2.6). +# @tls-authz: ID of the QAuthZ authorization object used to validate +# the client's x509 distinguished name. This object is +# is only resolved at time of use, so can be deleted and +# recreated on the fly while the NBD server is active. +# If missing, it will default to denying access (since 4.0). +# @max-connections: The maximum number of connections to allow at the same +# time, 0 for unlimited. (since 5.2; default: 0) +# +# Returns: error if the server is already running. +# +# Since: 1.3 +## +{ 'command': 'nbd-server-start', + 'data': { 'addr': 'SocketAddressLegacy', + '*tls-creds': 'str', + '*tls-authz': 'str', + '*max-connections': 'uint32' } } + +## +# @BlockExportOptionsNbdBase: +# +# An NBD block export (common options shared between nbd-server-add and +# the NBD branch of block-export-add). +# +# @name: Export name. If unspecified, the @device parameter is used as the +# export name. (Since 2.12) +# +# @description: Free-form description of the export, up to 4096 bytes. +# (Since 5.0) +# +# Since: 5.0 +## +{ 'struct': 'BlockExportOptionsNbdBase', + 'data': { '*name': 'str', '*description': 'str' } } + +## +# @BlockExportOptionsNbd: +# +# An NBD block export (distinct options used in the NBD branch of +# block-export-add). +# +# @bitmaps: Also export each of the named dirty bitmaps reachable from +# @device, so the NBD client can use NBD_OPT_SET_META_CONTEXT with +# the metadata context name "qemu:dirty-bitmap:BITMAP" to inspect +# each bitmap. +# +# @allocation-depth: Also export the allocation depth map for @device, so +# the NBD client can use NBD_OPT_SET_META_CONTEXT with +# the metadata context name "qemu:allocation-depth" to +# inspect allocation details. (since 5.2) +# +# Since: 5.2 +## +{ 'struct': 'BlockExportOptionsNbd', + 'base': 'BlockExportOptionsNbdBase', + 'data': { '*bitmaps': ['str'], '*allocation-depth': 'bool' } } + +## +# @BlockExportOptionsVhostUserBlk: +# +# A vhost-user-blk block export. +# +# @addr: The vhost-user socket on which to listen. Both 'unix' and 'fd' +# SocketAddress types are supported. Passed fds must be UNIX domain +# sockets. +# @logical-block-size: Logical block size in bytes. Defaults to 512 bytes. +# @num-queues: Number of request virtqueues. Must be greater than 0. Defaults +# to 1. +# +# Since: 5.2 +## +{ 'struct': 'BlockExportOptionsVhostUserBlk', + 'data': { 'addr': 'SocketAddress', + '*logical-block-size': 'size', + '*num-queues': 'uint16'} } + +## +# @FuseExportAllowOther: +# +# Possible allow_other modes for FUSE exports. +# +# @off: Do not pass allow_other as a mount option. +# +# @on: Pass allow_other as a mount option. +# +# @auto: Try mounting with allow_other first, and if that fails, retry +# without allow_other. +# +# Since: 6.1 +## +{ 'enum': 'FuseExportAllowOther', + 'data': ['off', 'on', 'auto'] } + +## +# @BlockExportOptionsFuse: +# +# Options for exporting a block graph node on some (file) mountpoint +# as a raw image. +# +# @mountpoint: Path on which to export the block device via FUSE. +# This must point to an existing regular file. +# +# @growable: Whether writes beyond the EOF should grow the block node +# accordingly. (default: false) +# +# @allow-other: If this is off, only qemu's user is allowed access to +# this export. That cannot be changed even with chmod or +# chown. +# Enabling this option will allow other users access to +# the export with the FUSE mount option "allow_other". +# Note that using allow_other as a non-root user requires +# user_allow_other to be enabled in the global fuse.conf +# configuration file. +# In auto mode (the default), the FUSE export driver will +# first attempt to mount the export with allow_other, and +# if that fails, try again without. +# (since 6.1; default: auto) +# +# Since: 6.0 +## +{ 'struct': 'BlockExportOptionsFuse', + 'data': { 'mountpoint': 'str', + '*growable': 'bool', + '*allow-other': 'FuseExportAllowOther' }, + 'if': 'CONFIG_FUSE' } + +## +# @NbdServerAddOptions: +# +# An NBD block export, per legacy nbd-server-add command. +# +# @device: The device name or node name of the node to be exported +# +# @writable: Whether clients should be able to write to the device via the +# NBD connection (default false). +# +# @bitmap: Also export a single dirty bitmap reachable from @device, so the +# NBD client can use NBD_OPT_SET_META_CONTEXT with the metadata +# context name "qemu:dirty-bitmap:BITMAP" to inspect the bitmap +# (since 4.0). +# +# Since: 5.0 +## +{ 'struct': 'NbdServerAddOptions', + 'base': 'BlockExportOptionsNbdBase', + 'data': { 'device': 'str', + '*writable': 'bool', '*bitmap': 'str' } } + +## +# @nbd-server-add: +# +# Export a block node to QEMU's embedded NBD server. +# +# The export name will be used as the id for the resulting block export. +# +# Features: +# @deprecated: This command is deprecated. Use @block-export-add instead. +# +# Returns: error if the server is not running, or export with the same name +# already exists. +# +# Since: 1.3 +## +{ 'command': 'nbd-server-add', + 'data': 'NbdServerAddOptions', 'boxed': true, 'features': ['deprecated'] } + +## +# @BlockExportRemoveMode: +# +# Mode for removing a block export. +# +# @safe: Remove export if there are no existing connections, fail otherwise. +# +# @hard: Drop all connections immediately and remove export. +# +# Potential additional modes to be added in the future: +# +# hide: Just hide export from new clients, leave existing connections as is. +# Remove export after all clients are disconnected. +# +# soft: Hide export from new clients, answer with ESHUTDOWN for all further +# requests from existing clients. +# +# Since: 2.12 +## +{'enum': 'BlockExportRemoveMode', 'data': ['safe', 'hard']} + +## +# @nbd-server-remove: +# +# Remove NBD export by name. +# +# @name: Block export id. +# +# @mode: Mode of command operation. See @BlockExportRemoveMode description. +# Default is 'safe'. +# +# Features: +# @deprecated: This command is deprecated. Use @block-export-del instead. +# +# Returns: error if +# - the server is not running +# - export is not found +# - mode is 'safe' and there are existing connections +# +# Since: 2.12 +## +{ 'command': 'nbd-server-remove', + 'data': {'name': 'str', '*mode': 'BlockExportRemoveMode'}, + 'features': ['deprecated'] } + +## +# @nbd-server-stop: +# +# Stop QEMU's embedded NBD server, and unregister all devices previously +# added via @nbd-server-add. +# +# Since: 1.3 +## +{ 'command': 'nbd-server-stop' } + +## +# @BlockExportType: +# +# An enumeration of block export types +# +# @nbd: NBD export +# @vhost-user-blk: vhost-user-blk export (since 5.2) +# @fuse: FUSE export (since: 6.0) +# +# Since: 4.2 +## +{ 'enum': 'BlockExportType', + 'data': [ 'nbd', 'vhost-user-blk', + { 'name': 'fuse', 'if': 'CONFIG_FUSE' } ] } + +## +# @BlockExportOptions: +# +# Describes a block export, i.e. how single node should be exported on an +# external interface. +# +# @id: A unique identifier for the block export (across all export types) +# +# @node-name: The node name of the block node to be exported (since: 5.2) +# +# @writable: True if clients should be able to write to the export +# (default false) +# +# @writethrough: If true, caches are flushed after every write request to the +# export before completion is signalled. (since: 5.2; +# default: false) +# +# @iothread: The name of the iothread object where the export will run. The +# default is to use the thread currently associated with the +# block node. (since: 5.2) +# +# @fixed-iothread: True prevents the block node from being moved to another +# thread while the export is active. If true and @iothread is +# given, export creation fails if the block node cannot be +# moved to the iothread. The default is false. (since: 5.2) +# +# Since: 4.2 +## +{ 'union': 'BlockExportOptions', + 'base': { 'type': 'BlockExportType', + 'id': 'str', + '*fixed-iothread': 'bool', + '*iothread': 'str', + 'node-name': 'str', + '*writable': 'bool', + '*writethrough': 'bool' }, + 'discriminator': 'type', + 'data': { + 'nbd': 'BlockExportOptionsNbd', + 'vhost-user-blk': 'BlockExportOptionsVhostUserBlk', + 'fuse': { 'type': 'BlockExportOptionsFuse', + 'if': 'CONFIG_FUSE' } + } } + +## +# @block-export-add: +# +# Creates a new block export. +# +# Since: 5.2 +## +{ 'command': 'block-export-add', + 'data': 'BlockExportOptions', 'boxed': true } + +## +# @block-export-del: +# +# Request to remove a block export. This drops the user's reference to the +# export, but the export may still stay around after this command returns until +# the shutdown of the export has completed. +# +# @id: Block export id. +# +# @mode: Mode of command operation. See @BlockExportRemoveMode description. +# Default is 'safe'. +# +# Returns: Error if the export is not found or @mode is 'safe' and the export +# is still in use (e.g. by existing client connections) +# +# Since: 5.2 +## +{ 'command': 'block-export-del', + 'data': { 'id': 'str', '*mode': 'BlockExportRemoveMode' } } + +## +# @BLOCK_EXPORT_DELETED: +# +# Emitted when a block export is removed and its id can be reused. +# +# @id: Block export id. +# +# Since: 5.2 +## +{ 'event': 'BLOCK_EXPORT_DELETED', + 'data': { 'id': 'str' } } + +## +# @BlockExportInfo: +# +# Information about a single block export. +# +# @id: The unique identifier for the block export +# +# @type: The block export type +# +# @node-name: The node name of the block node that is exported +# +# @shutting-down: True if the export is shutting down (e.g. after a +# block-export-del command, but before the shutdown has +# completed) +# +# Since: 5.2 +## +{ 'struct': 'BlockExportInfo', + 'data': { 'id': 'str', + 'type': 'BlockExportType', + 'node-name': 'str', + 'shutting-down': 'bool' } } + +## +# @query-block-exports: +# +# Returns: A list of BlockExportInfo describing all block exports +# +# Since: 5.2 +## +{ 'command': 'query-block-exports', 'returns': ['BlockExportInfo'] } diff --git a/qapi/block.json b/qapi/block.json new file mode 100644 index 000000000..82fcf2c91 --- /dev/null +++ b/qapi/block.json @@ -0,0 +1,572 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# = Block devices +## + +{ 'include': 'block-core.json' } + +## +# == Additional block stuff (VM related) +## + +## +# @BiosAtaTranslation: +# +# Policy that BIOS should use to interpret cylinder/head/sector +# addresses. Note that Bochs BIOS and SeaBIOS will not actually +# translate logical CHS to physical; instead, they will use logical +# block addressing. +# +# @auto: If cylinder/heads/sizes are passed, choose between none and LBA +# depending on the size of the disk. If they are not passed, +# choose none if QEMU can guess that the disk had 16 or fewer +# heads, large if QEMU can guess that the disk had 131072 or +# fewer tracks across all heads (i.e. cylinders*heads<131072), +# otherwise LBA. +# +# @none: The physical disk geometry is equal to the logical geometry. +# +# @lba: Assume 63 sectors per track and one of 16, 32, 64, 128 or 255 +# heads (if fewer than 255 are enough to cover the whole disk +# with 1024 cylinders/head). The number of cylinders/head is +# then computed based on the number of sectors and heads. +# +# @large: The number of cylinders per head is scaled down to 1024 +# by correspondingly scaling up the number of heads. +# +# @rechs: Same as @large, but first convert a 16-head geometry to +# 15-head, by proportionally scaling up the number of +# cylinders/head. +# +# Since: 2.0 +## +{ 'enum': 'BiosAtaTranslation', + 'data': ['auto', 'none', 'lba', 'large', 'rechs']} + +## +# @FloppyDriveType: +# +# Type of Floppy drive to be emulated by the Floppy Disk Controller. +# +# @144: 1.44MB 3.5" drive +# @288: 2.88MB 3.5" drive +# @120: 1.2MB 5.25" drive +# @none: No drive connected +# @auto: Automatically determined by inserted media at boot +# +# Since: 2.6 +## +{ 'enum': 'FloppyDriveType', + 'data': ['144', '288', '120', 'none', 'auto']} + +## +# @PRManagerInfo: +# +# Information about a persistent reservation manager +# +# @id: the identifier of the persistent reservation manager +# +# @connected: true if the persistent reservation manager is connected to +# the underlying storage or helper +# +# Since: 3.0 +## +{ 'struct': 'PRManagerInfo', + 'data': {'id': 'str', 'connected': 'bool'} } + +## +# @query-pr-managers: +# +# Returns a list of information about each persistent reservation manager. +# +# Returns: a list of @PRManagerInfo for each persistent reservation manager +# +# Since: 3.0 +## +{ 'command': 'query-pr-managers', 'returns': ['PRManagerInfo'], + 'allow-preconfig': true } + +## +# @eject: +# +# Ejects the medium from a removable drive. +# +# @device: Block device name +# +# @id: The name or QOM path of the guest device (since: 2.8) +# +# @force: If true, eject regardless of whether the drive is locked. +# If not specified, the default value is false. +# +# Features: +# @deprecated: Member @device is deprecated. Use @id instead. +# +# Returns: - Nothing on success +# - If @device is not a valid block device, DeviceNotFound +# Notes: Ejecting a device with no media results in success +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "eject", "arguments": { "id": "ide1-0-1" } } +# <- { "return": {} } +## +{ 'command': 'eject', + 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, + '*id': 'str', + '*force': 'bool' } } + +## +# @blockdev-open-tray: +# +# Opens a block device's tray. If there is a block driver state tree inserted as +# a medium, it will become inaccessible to the guest (but it will remain +# associated to the block device, so closing the tray will make it accessible +# again). +# +# If the tray was already open before, this will be a no-op. +# +# Once the tray opens, a DEVICE_TRAY_MOVED event is emitted. There are cases in +# which no such event will be generated, these include: +# +# - if the guest has locked the tray, @force is false and the guest does not +# respond to the eject request +# - if the BlockBackend denoted by @device does not have a guest device attached +# to it +# - if the guest device does not have an actual tray +# +# @device: Block device name +# +# @id: The name or QOM path of the guest device (since: 2.8) +# +# @force: if false (the default), an eject request will be sent to +# the guest if it has locked the tray (and the tray will not be opened +# immediately); if true, the tray will be opened regardless of whether +# it is locked +# +# Features: +# @deprecated: Member @device is deprecated. Use @id instead. +# +# Since: 2.5 +# +# Example: +# +# -> { "execute": "blockdev-open-tray", +# "arguments": { "id": "ide0-1-0" } } +# +# <- { "timestamp": { "seconds": 1418751016, +# "microseconds": 716996 }, +# "event": "DEVICE_TRAY_MOVED", +# "data": { "device": "ide1-cd0", +# "id": "ide0-1-0", +# "tray-open": true } } +# +# <- { "return": {} } +# +## +{ 'command': 'blockdev-open-tray', + 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, + '*id': 'str', + '*force': 'bool' } } + +## +# @blockdev-close-tray: +# +# Closes a block device's tray. If there is a block driver state tree associated +# with the block device (which is currently ejected), that tree will be loaded +# as the medium. +# +# If the tray was already closed before, this will be a no-op. +# +# @device: Block device name +# +# @id: The name or QOM path of the guest device (since: 2.8) +# +# Features: +# @deprecated: Member @device is deprecated. Use @id instead. +# +# Since: 2.5 +# +# Example: +# +# -> { "execute": "blockdev-close-tray", +# "arguments": { "id": "ide0-1-0" } } +# +# <- { "timestamp": { "seconds": 1418751345, +# "microseconds": 272147 }, +# "event": "DEVICE_TRAY_MOVED", +# "data": { "device": "ide1-cd0", +# "id": "ide0-1-0", +# "tray-open": false } } +# +# <- { "return": {} } +# +## +{ 'command': 'blockdev-close-tray', + 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, + '*id': 'str' } } + +## +# @blockdev-remove-medium: +# +# Removes a medium (a block driver state tree) from a block device. That block +# device's tray must currently be open (unless there is no attached guest +# device). +# +# If the tray is open and there is no medium inserted, this will be a no-op. +# +# @id: The name or QOM path of the guest device +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "blockdev-remove-medium", +# "arguments": { "id": "ide0-1-0" } } +# +# <- { "error": { "class": "GenericError", +# "desc": "Tray of device 'ide0-1-0' is not open" } } +# +# -> { "execute": "blockdev-open-tray", +# "arguments": { "id": "ide0-1-0" } } +# +# <- { "timestamp": { "seconds": 1418751627, +# "microseconds": 549958 }, +# "event": "DEVICE_TRAY_MOVED", +# "data": { "device": "ide1-cd0", +# "id": "ide0-1-0", +# "tray-open": true } } +# +# <- { "return": {} } +# +# -> { "execute": "blockdev-remove-medium", +# "arguments": { "id": "ide0-1-0" } } +# +# <- { "return": {} } +# +## +{ 'command': 'blockdev-remove-medium', + 'data': { 'id': 'str' } } + +## +# @blockdev-insert-medium: +# +# Inserts a medium (a block driver state tree) into a block device. That block +# device's tray must currently be open (unless there is no attached guest +# device) and there must be no medium inserted already. +# +# @id: The name or QOM path of the guest device +# +# @node-name: name of a node in the block driver state graph +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "blockdev-add", +# "arguments": { +# "node-name": "node0", +# "driver": "raw", +# "file": { "driver": "file", +# "filename": "fedora.iso" } } } +# <- { "return": {} } +# +# -> { "execute": "blockdev-insert-medium", +# "arguments": { "id": "ide0-1-0", +# "node-name": "node0" } } +# +# <- { "return": {} } +# +## +{ 'command': 'blockdev-insert-medium', + 'data': { 'id': 'str', + 'node-name': 'str'} } + + +## +# @BlockdevChangeReadOnlyMode: +# +# Specifies the new read-only mode of a block device subject to the +# @blockdev-change-medium command. +# +# @retain: Retains the current read-only mode +# +# @read-only: Makes the device read-only +# +# @read-write: Makes the device writable +# +# Since: 2.3 +# +## +{ 'enum': 'BlockdevChangeReadOnlyMode', + 'data': ['retain', 'read-only', 'read-write'] } + + +## +# @blockdev-change-medium: +# +# Changes the medium inserted into a block device by ejecting the current medium +# and loading a new image file which is inserted as the new medium (this command +# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium +# and blockdev-close-tray). +# +# @device: Block device name +# +# @id: The name or QOM path of the guest device +# (since: 2.8) +# +# @filename: filename of the new image to be loaded +# +# @format: format to open the new image with (defaults to +# the probed format) +# +# @read-only-mode: change the read-only mode of the device; defaults +# to 'retain' +# +# Features: +# @deprecated: Member @device is deprecated. Use @id instead. +# +# Since: 2.5 +# +# Examples: +# +# 1. Change a removable medium +# +# -> { "execute": "blockdev-change-medium", +# "arguments": { "id": "ide0-1-0", +# "filename": "/srv/images/Fedora-12-x86_64-DVD.iso", +# "format": "raw" } } +# <- { "return": {} } +# +# 2. Load a read-only medium into a writable drive +# +# -> { "execute": "blockdev-change-medium", +# "arguments": { "id": "floppyA", +# "filename": "/srv/images/ro.img", +# "format": "raw", +# "read-only-mode": "retain" } } +# +# <- { "error": +# { "class": "GenericError", +# "desc": "Could not open '/srv/images/ro.img': Permission denied" } } +# +# -> { "execute": "blockdev-change-medium", +# "arguments": { "id": "floppyA", +# "filename": "/srv/images/ro.img", +# "format": "raw", +# "read-only-mode": "read-only" } } +# +# <- { "return": {} } +# +## +{ 'command': 'blockdev-change-medium', + 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] }, + '*id': 'str', + 'filename': 'str', + '*format': 'str', + '*read-only-mode': 'BlockdevChangeReadOnlyMode' } } + + +## +# @DEVICE_TRAY_MOVED: +# +# Emitted whenever the tray of a removable device is moved by the guest or by +# HMP/QMP commands +# +# @device: Block device name. This is always present for compatibility +# reasons, but it can be empty ("") if the image does not +# have a device name associated. +# +# @id: The name or QOM path of the guest device (since 2.8) +# +# @tray-open: true if the tray has been opened or false if it has been closed +# +# Since: 1.1 +# +# Example: +# +# <- { "event": "DEVICE_TRAY_MOVED", +# "data": { "device": "ide1-cd0", +# "id": "/machine/unattached/device[22]", +# "tray-open": true +# }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'DEVICE_TRAY_MOVED', + 'data': { 'device': 'str', 'id': 'str', 'tray-open': 'bool' } } + +## +# @PR_MANAGER_STATUS_CHANGED: +# +# Emitted whenever the connected status of a persistent reservation +# manager changes. +# +# @id: The id of the PR manager object +# +# @connected: true if the PR manager is connected to a backend +# +# Since: 3.0 +# +# Example: +# +# <- { "event": "PR_MANAGER_STATUS_CHANGED", +# "data": { "id": "pr-helper0", +# "connected": true +# }, +# "timestamp": { "seconds": 1519840375, "microseconds": 450486 } } +# +## +{ 'event': 'PR_MANAGER_STATUS_CHANGED', + 'data': { 'id': 'str', 'connected': 'bool' } } + +## +# @block_set_io_throttle: +# +# Change I/O throttle limits for a block drive. +# +# Since QEMU 2.4, each device with I/O limits is member of a throttle +# group. +# +# If two or more devices are members of the same group, the limits +# will apply to the combined I/O of the whole group in a round-robin +# fashion. Therefore, setting new I/O limits to a device will affect +# the whole group. +# +# The name of the group can be specified using the 'group' parameter. +# If the parameter is unset, it is assumed to be the current group of +# that device. If it's not in any group yet, the name of the device +# will be used as the name for its group. +# +# The 'group' parameter can also be used to move a device to a +# different group. In this case the limits specified in the parameters +# will be applied to the new group only. +# +# I/O limits can be disabled by setting all of them to 0. In this case +# the device will be removed from its group and the rest of its +# members will not be affected. The 'group' parameter is ignored. +# +# Returns: - Nothing on success +# - If @device is not a valid block device, DeviceNotFound +# +# Since: 1.1 +# +# Example: +# +# -> { "execute": "block_set_io_throttle", +# "arguments": { "id": "virtio-blk-pci0/virtio-backend", +# "bps": 0, +# "bps_rd": 0, +# "bps_wr": 0, +# "iops": 512, +# "iops_rd": 0, +# "iops_wr": 0, +# "bps_max": 0, +# "bps_rd_max": 0, +# "bps_wr_max": 0, +# "iops_max": 0, +# "iops_rd_max": 0, +# "iops_wr_max": 0, +# "bps_max_length": 0, +# "iops_size": 0 } } +# <- { "return": {} } +# +# -> { "execute": "block_set_io_throttle", +# "arguments": { "id": "ide0-1-0", +# "bps": 1000000, +# "bps_rd": 0, +# "bps_wr": 0, +# "iops": 0, +# "iops_rd": 0, +# "iops_wr": 0, +# "bps_max": 8000000, +# "bps_rd_max": 0, +# "bps_wr_max": 0, +# "iops_max": 0, +# "iops_rd_max": 0, +# "iops_wr_max": 0, +# "bps_max_length": 60, +# "iops_size": 0 } } +# <- { "return": {} } +## +{ 'command': 'block_set_io_throttle', 'boxed': true, + 'data': 'BlockIOThrottle' } + +## +# @block-latency-histogram-set: +# +# Manage read, write and flush latency histograms for the device. +# +# If only @id parameter is specified, remove all present latency histograms +# for the device. Otherwise, add/reset some of (or all) latency histograms. +# +# @id: The name or QOM path of the guest device. +# +# @boundaries: list of interval boundary values (see description in +# BlockLatencyHistogramInfo definition). If specified, all +# latency histograms are removed, and empty ones created for all +# io types with intervals corresponding to @boundaries (except for +# io types, for which specific boundaries are set through the +# following parameters). +# +# @boundaries-read: list of interval boundary values for read latency +# histogram. If specified, old read latency histogram is +# removed, and empty one created with intervals +# corresponding to @boundaries-read. The parameter has higher +# priority then @boundaries. +# +# @boundaries-write: list of interval boundary values for write latency +# histogram. +# +# @boundaries-flush: list of interval boundary values for flush latency +# histogram. +# +# Returns: error if device is not found or any boundary arrays are invalid. +# +# Since: 4.0 +# +# Example: +# set new histograms for all io types with intervals +# [0, 10), [10, 50), [50, 100), [100, +inf): +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "id": "drive0", +# "boundaries": [10, 50, 100] } } +# <- { "return": {} } +# +# Example: +# set new histogram only for write, other histograms will remain +# not changed (or not created): +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "id": "drive0", +# "boundaries-write": [10, 50, 100] } } +# <- { "return": {} } +# +# Example: +# set new histograms with the following intervals: +# read, flush: [0, 10), [10, 50), [50, 100), [100, +inf) +# write: [0, 1000), [1000, 5000), [5000, +inf) +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "id": "drive0", +# "boundaries": [10, 50, 100], +# "boundaries-write": [1000, 5000] } } +# <- { "return": {} } +# +# Example: +# remove all latency histograms: +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "id": "drive0" } } +# <- { "return": {} } +## +{ 'command': 'block-latency-histogram-set', + 'data': {'id': 'str', + '*boundaries': ['uint64'], + '*boundaries-read': ['uint64'], + '*boundaries-write': ['uint64'], + '*boundaries-flush': ['uint64'] } } diff --git a/qapi/char.json b/qapi/char.json new file mode 100644 index 000000000..f5133a5ee --- /dev/null +++ b/qapi/char.json @@ -0,0 +1,742 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Character devices +## + +{ 'include': 'sockets.json' } + +## +# @ChardevInfo: +# +# Information about a character device. +# +# @label: the label of the character device +# +# @filename: the filename of the character device +# +# @frontend-open: shows whether the frontend device attached to this backend +# (eg. with the chardev=... option) is in open or closed state +# (since 2.1) +# +# Notes: @filename is encoded using the QEMU command line character device +# encoding. See the QEMU man page for details. +# +# Since: 0.14 +## +{ 'struct': 'ChardevInfo', + 'data': { 'label': 'str', + 'filename': 'str', + 'frontend-open': 'bool' } } + +## +# @query-chardev: +# +# Returns information about current character devices. +# +# Returns: a list of @ChardevInfo +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-chardev" } +# <- { +# "return": [ +# { +# "label": "charchannel0", +# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.agent,server=on", +# "frontend-open": false +# }, +# { +# "label": "charmonitor", +# "filename": "unix:/var/lib/libvirt/qemu/seabios.rhel6.monitor,server=on", +# "frontend-open": true +# }, +# { +# "label": "charserial0", +# "filename": "pty:/dev/pts/2", +# "frontend-open": true +# } +# ] +# } +# +## +{ 'command': 'query-chardev', 'returns': ['ChardevInfo'], + 'allow-preconfig': true } + +## +# @ChardevBackendInfo: +# +# Information about a character device backend +# +# @name: The backend name +# +# Since: 2.0 +## +{ 'struct': 'ChardevBackendInfo', 'data': {'name': 'str'} } + +## +# @query-chardev-backends: +# +# Returns information about character device backends. +# +# Returns: a list of @ChardevBackendInfo +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "query-chardev-backends" } +# <- { +# "return":[ +# { +# "name":"udp" +# }, +# { +# "name":"tcp" +# }, +# { +# "name":"unix" +# }, +# { +# "name":"spiceport" +# } +# ] +# } +# +## +{ 'command': 'query-chardev-backends', 'returns': ['ChardevBackendInfo'] } + +## +# @DataFormat: +# +# An enumeration of data format. +# +# @utf8: Data is a UTF-8 string (RFC 3629) +# +# @base64: Data is Base64 encoded binary (RFC 3548) +# +# Since: 1.4 +## +{ 'enum': 'DataFormat', + 'data': [ 'utf8', 'base64' ] } + +## +# @ringbuf-write: +# +# Write to a ring buffer character device. +# +# @device: the ring buffer character device name +# +# @data: data to write +# +# @format: data encoding (default 'utf8'). +# +# - base64: data must be base64 encoded text. Its binary +# decoding gets written. +# - utf8: data's UTF-8 encoding is written +# - data itself is always Unicode regardless of format, like +# any other string. +# +# Returns: Nothing on success +# +# Since: 1.4 +# +# Example: +# +# -> { "execute": "ringbuf-write", +# "arguments": { "device": "foo", +# "data": "abcdefgh", +# "format": "utf8" } } +# <- { "return": {} } +# +## +{ 'command': 'ringbuf-write', + 'data': { 'device': 'str', + 'data': 'str', + '*format': 'DataFormat'} } + +## +# @ringbuf-read: +# +# Read from a ring buffer character device. +# +# @device: the ring buffer character device name +# +# @size: how many bytes to read at most +# +# @format: data encoding (default 'utf8'). +# +# - base64: the data read is returned in base64 encoding. +# - utf8: the data read is interpreted as UTF-8. +# Bug: can screw up when the buffer contains invalid UTF-8 +# sequences, NUL characters, after the ring buffer lost +# data, and when reading stops because the size limit is +# reached. +# - The return value is always Unicode regardless of format, +# like any other string. +# +# Returns: data read from the device +# +# Since: 1.4 +# +# Example: +# +# -> { "execute": "ringbuf-read", +# "arguments": { "device": "foo", +# "size": 1000, +# "format": "utf8" } } +# <- { "return": "abcdefgh" } +# +## +{ 'command': 'ringbuf-read', + 'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'}, + 'returns': 'str' } + +## +# @ChardevCommon: +# +# Configuration shared across all chardev backends +# +# @logfile: The name of a logfile to save output +# @logappend: true to append instead of truncate +# (default to false to truncate) +# +# Since: 2.6 +## +{ 'struct': 'ChardevCommon', + 'data': { '*logfile': 'str', + '*logappend': 'bool' } } + +## +# @ChardevFile: +# +# Configuration info for file chardevs. +# +# @in: The name of the input file +# @out: The name of the output file +# @append: Open the file in append mode (default false to +# truncate) (Since 2.6) +# +# Since: 1.4 +## +{ 'struct': 'ChardevFile', + 'data': { '*in': 'str', + 'out': 'str', + '*append': 'bool' }, + 'base': 'ChardevCommon' } + +## +# @ChardevHostdev: +# +# Configuration info for device and pipe chardevs. +# +# @device: The name of the special file for the device, +# i.e. /dev/ttyS0 on Unix or COM1: on Windows +# +# Since: 1.4 +## +{ 'struct': 'ChardevHostdev', + 'data': { 'device': 'str' }, + 'base': 'ChardevCommon' } + +## +# @ChardevSocket: +# +# Configuration info for (stream) socket chardevs. +# +# @addr: socket address to listen on (server=true) +# or connect to (server=false) +# @tls-creds: the ID of the TLS credentials object (since 2.6) +# @tls-authz: the ID of the QAuthZ authorization object against which +# the client's x509 distinguished name will be validated. This +# object is only resolved at time of use, so can be deleted +# and recreated on the fly while the chardev server is active. +# If missing, it will default to denying access (since 4.0) +# @server: create server socket (default: true) +# @wait: wait for incoming connection on server +# sockets (default: false). +# Silently ignored with server: false. This use is deprecated. +# @nodelay: set TCP_NODELAY socket option (default: false) +# @telnet: enable telnet protocol on server +# sockets (default: false) +# @tn3270: enable tn3270 protocol on server +# sockets (default: false) (Since: 2.10) +# @websocket: enable websocket protocol on server +# sockets (default: false) (Since: 3.1) +# @reconnect: For a client socket, if a socket is disconnected, +# then attempt a reconnect after the given number of seconds. +# Setting this to zero disables this function. (default: 0) +# (Since: 2.2) +# +# Since: 1.4 +## +{ 'struct': 'ChardevSocket', + 'data': { 'addr': 'SocketAddressLegacy', + '*tls-creds': 'str', + '*tls-authz' : 'str', + '*server': 'bool', + '*wait': 'bool', + '*nodelay': 'bool', + '*telnet': 'bool', + '*tn3270': 'bool', + '*websocket': 'bool', + '*reconnect': 'int' }, + 'base': 'ChardevCommon' } + +## +# @ChardevUdp: +# +# Configuration info for datagram socket chardevs. +# +# @remote: remote address +# @local: local address +# +# Since: 1.5 +## +{ 'struct': 'ChardevUdp', + 'data': { 'remote': 'SocketAddressLegacy', + '*local': 'SocketAddressLegacy' }, + 'base': 'ChardevCommon' } + +## +# @ChardevMux: +# +# Configuration info for mux chardevs. +# +# @chardev: name of the base chardev. +# +# Since: 1.5 +## +{ 'struct': 'ChardevMux', + 'data': { 'chardev': 'str' }, + 'base': 'ChardevCommon' } + +## +# @ChardevStdio: +# +# Configuration info for stdio chardevs. +# +# @signal: Allow signals (such as SIGINT triggered by ^C) +# be delivered to qemu. Default: true. +# +# Since: 1.5 +## +{ 'struct': 'ChardevStdio', + 'data': { '*signal': 'bool' }, + 'base': 'ChardevCommon' } + + +## +# @ChardevSpiceChannel: +# +# Configuration info for spice vm channel chardevs. +# +# @type: kind of channel (for example vdagent). +# +# Since: 1.5 +## +{ 'struct': 'ChardevSpiceChannel', + 'data': { 'type': 'str' }, + 'base': 'ChardevCommon', + 'if': 'CONFIG_SPICE' } + +## +# @ChardevSpicePort: +# +# Configuration info for spice port chardevs. +# +# @fqdn: name of the channel (see docs/spice-port-fqdn.txt) +# +# Since: 1.5 +## +{ 'struct': 'ChardevSpicePort', + 'data': { 'fqdn': 'str' }, + 'base': 'ChardevCommon', + 'if': 'CONFIG_SPICE' } + +## +# @ChardevVC: +# +# Configuration info for virtual console chardevs. +# +# @width: console width, in pixels +# @height: console height, in pixels +# @cols: console width, in chars +# @rows: console height, in chars +# +# Since: 1.5 +## +{ 'struct': 'ChardevVC', + 'data': { '*width': 'int', + '*height': 'int', + '*cols': 'int', + '*rows': 'int' }, + 'base': 'ChardevCommon' } + +## +# @ChardevRingbuf: +# +# Configuration info for ring buffer chardevs. +# +# @size: ring buffer size, must be power of two, default is 65536 +# +# Since: 1.5 +## +{ 'struct': 'ChardevRingbuf', + 'data': { '*size': 'int' }, + 'base': 'ChardevCommon' } + +## +# @ChardevQemuVDAgent: +# +# Configuration info for qemu vdagent implementation. +# +# @mouse: enable/disable mouse, default is enabled. +# @clipboard: enable/disable clipboard, default is disabled. +# +# Since: 6.1 +# +## +{ 'struct': 'ChardevQemuVDAgent', + 'data': { '*mouse': 'bool', + '*clipboard': 'bool' }, + 'base': 'ChardevCommon', + 'if': 'CONFIG_SPICE_PROTOCOL' } + +## +# @ChardevBackendKind: +# +# @pipe: Since 1.5 +# @udp: Since 1.5 +# @mux: Since 1.5 +# @msmouse: Since 1.5 +# @wctablet: Since 2.9 +# @braille: Since 1.5 +# @testdev: Since 2.2 +# @stdio: Since 1.5 +# @console: Since 1.5 +# @spicevmc: Since 1.5 +# @spiceport: Since 1.5 +# @qemu-vdagent: Since 6.1 +# @vc: v1.5 +# @ringbuf: Since 1.6 +# @memory: Since 1.5 +# +# Since: 1.4 +## +{ 'enum': 'ChardevBackendKind', + 'data': [ 'file', + 'serial', + 'parallel', + 'pipe', + 'socket', + 'udp', + 'pty', + 'null', + 'mux', + 'msmouse', + 'wctablet', + 'braille', + 'testdev', + 'stdio', + 'console', + { 'name': 'spicevmc', 'if': 'CONFIG_SPICE' }, + { 'name': 'spiceport', 'if': 'CONFIG_SPICE' }, + { 'name': 'qemu-vdagent', 'if': 'CONFIG_SPICE_PROTOCOL' }, + 'vc', + 'ringbuf', + # next one is just for compatibility + 'memory' ] } + +## +# @ChardevFileWrapper: +# +# Since: 1.4 +## +{ 'struct': 'ChardevFileWrapper', + 'data': { 'data': 'ChardevFile' } } + +## +# @ChardevHostdevWrapper: +# +# Since: 1.4 +## +{ 'struct': 'ChardevHostdevWrapper', + 'data': { 'data': 'ChardevHostdev' } } + +## +# @ChardevSocketWrapper: +# +# Since: 1.4 +## +{ 'struct': 'ChardevSocketWrapper', + 'data': { 'data': 'ChardevSocket' } } + +## +# @ChardevUdpWrapper: +# +# Since: 1.5 +## +{ 'struct': 'ChardevUdpWrapper', + 'data': { 'data': 'ChardevUdp' } } + +## +# @ChardevCommonWrapper: +# +# Since: 2.6 +## +{ 'struct': 'ChardevCommonWrapper', + 'data': { 'data': 'ChardevCommon' } } + +## +# @ChardevMuxWrapper: +# +# Since: 1.5 +## +{ 'struct': 'ChardevMuxWrapper', + 'data': { 'data': 'ChardevMux' } } + +## +# @ChardevStdioWrapper: +# +# Since: 1.5 +## +{ 'struct': 'ChardevStdioWrapper', + 'data': { 'data': 'ChardevStdio' } } + +## +# @ChardevSpiceChannelWrapper: +# +# Since: 1.5 +## +{ 'struct': 'ChardevSpiceChannelWrapper', + 'data': { 'data': 'ChardevSpiceChannel' }, + 'if': 'CONFIG_SPICE' } + +## +# @ChardevSpicePortWrapper: +# +# Since: 1.5 +## +{ 'struct': 'ChardevSpicePortWrapper', + 'data': { 'data': 'ChardevSpicePort' }, + 'if': 'CONFIG_SPICE' } + +## +# @ChardevQemuVDAgentWrapper: +# +# Since: 6.1 +## +{ 'struct': 'ChardevQemuVDAgentWrapper', + 'data': { 'data': 'ChardevQemuVDAgent' }, + 'if': 'CONFIG_SPICE_PROTOCOL' } + +## +# @ChardevVCWrapper: +# +# Since: 1.5 +## +{ 'struct': 'ChardevVCWrapper', + 'data': { 'data': 'ChardevVC' } } + +## +# @ChardevRingbufWrapper: +# +# Since: 1.5 +## +{ 'struct': 'ChardevRingbufWrapper', + 'data': { 'data': 'ChardevRingbuf' } } + +## +# @ChardevBackend: +# +# Configuration info for the new chardev backend. +# +# Since: 1.4 +## +{ 'union': 'ChardevBackend', + 'base': { 'type': 'ChardevBackendKind' }, + 'discriminator': 'type', + 'data': { 'file': 'ChardevFileWrapper', + 'serial': 'ChardevHostdevWrapper', + 'parallel': 'ChardevHostdevWrapper', + 'pipe': 'ChardevHostdevWrapper', + 'socket': 'ChardevSocketWrapper', + 'udp': 'ChardevUdpWrapper', + 'pty': 'ChardevCommonWrapper', + 'null': 'ChardevCommonWrapper', + 'mux': 'ChardevMuxWrapper', + 'msmouse': 'ChardevCommonWrapper', + 'wctablet': 'ChardevCommonWrapper', + 'braille': 'ChardevCommonWrapper', + 'testdev': 'ChardevCommonWrapper', + 'stdio': 'ChardevStdioWrapper', + 'console': 'ChardevCommonWrapper', + 'spicevmc': { 'type': 'ChardevSpiceChannelWrapper', + 'if': 'CONFIG_SPICE' }, + 'spiceport': { 'type': 'ChardevSpicePortWrapper', + 'if': 'CONFIG_SPICE' }, + 'qemu-vdagent': { 'type': 'ChardevQemuVDAgentWrapper', + 'if': 'CONFIG_SPICE_PROTOCOL' }, + 'vc': 'ChardevVCWrapper', + 'ringbuf': 'ChardevRingbufWrapper', + # next one is just for compatibility + 'memory': 'ChardevRingbufWrapper' } } + +## +# @ChardevReturn: +# +# Return info about the chardev backend just created. +# +# @pty: name of the slave pseudoterminal device, present if +# and only if a chardev of type 'pty' was created +# +# Since: 1.4 +## +{ 'struct' : 'ChardevReturn', + 'data': { '*pty': 'str' } } + +## +# @chardev-add: +# +# Add a character device backend +# +# @id: the chardev's ID, must be unique +# @backend: backend type and parameters +# +# Returns: ChardevReturn. +# +# Since: 1.4 +# +# Example: +# +# -> { "execute" : "chardev-add", +# "arguments" : { "id" : "foo", +# "backend" : { "type" : "null", "data" : {} } } } +# <- { "return": {} } +# +# -> { "execute" : "chardev-add", +# "arguments" : { "id" : "bar", +# "backend" : { "type" : "file", +# "data" : { "out" : "/tmp/bar.log" } } } } +# <- { "return": {} } +# +# -> { "execute" : "chardev-add", +# "arguments" : { "id" : "baz", +# "backend" : { "type" : "pty", "data" : {} } } } +# <- { "return": { "pty" : "/dev/pty/42" } } +# +## +{ 'command': 'chardev-add', + 'data': { 'id': 'str', + 'backend': 'ChardevBackend' }, + 'returns': 'ChardevReturn' } + +## +# @chardev-change: +# +# Change a character device backend +# +# @id: the chardev's ID, must exist +# @backend: new backend type and parameters +# +# Returns: ChardevReturn. +# +# Since: 2.10 +# +# Example: +# +# -> { "execute" : "chardev-change", +# "arguments" : { "id" : "baz", +# "backend" : { "type" : "pty", "data" : {} } } } +# <- { "return": { "pty" : "/dev/pty/42" } } +# +# -> {"execute" : "chardev-change", +# "arguments" : { +# "id" : "charchannel2", +# "backend" : { +# "type" : "socket", +# "data" : { +# "addr" : { +# "type" : "unix" , +# "data" : { +# "path" : "/tmp/charchannel2.socket" +# } +# }, +# "server" : true, +# "wait" : false }}}} +# <- {"return": {}} +# +## +{ 'command': 'chardev-change', + 'data': { 'id': 'str', + 'backend': 'ChardevBackend' }, + 'returns': 'ChardevReturn' } + +## +# @chardev-remove: +# +# Remove a character device backend +# +# @id: the chardev's ID, must exist and not be in use +# +# Returns: Nothing on success +# +# Since: 1.4 +# +# Example: +# +# -> { "execute": "chardev-remove", "arguments": { "id" : "foo" } } +# <- { "return": {} } +# +## +{ 'command': 'chardev-remove', + 'data': { 'id': 'str' } } + +## +# @chardev-send-break: +# +# Send a break to a character device +# +# @id: the chardev's ID, must exist +# +# Returns: Nothing on success +# +# Since: 2.10 +# +# Example: +# +# -> { "execute": "chardev-send-break", "arguments": { "id" : "foo" } } +# <- { "return": {} } +# +## +{ 'command': 'chardev-send-break', + 'data': { 'id': 'str' } } + +## +# @VSERPORT_CHANGE: +# +# Emitted when the guest opens or closes a virtio-serial port. +# +# @id: device identifier of the virtio-serial port +# +# @open: true if the guest has opened the virtio-serial port +# +# Note: This event is rate-limited. +# +# Since: 2.1 +# +# Example: +# +# <- { "event": "VSERPORT_CHANGE", +# "data": { "id": "channel0", "open": true }, +# "timestamp": { "seconds": 1401385907, "microseconds": 422329 } } +# +## +{ 'event': 'VSERPORT_CHANGE', + 'data': { 'id': 'str', + 'open': 'bool' } } diff --git a/qapi/common.json b/qapi/common.json new file mode 100644 index 000000000..412cc4f5a --- /dev/null +++ b/qapi/common.json @@ -0,0 +1,210 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# = Common data types +## + +## +# @IoOperationType: +# +# An enumeration of the I/O operation types +# +# @read: read operation +# +# @write: write operation +# +# Since: 2.1 +## +{ 'enum': 'IoOperationType', + 'data': [ 'read', 'write' ] } + +## +# @OnOffAuto: +# +# An enumeration of three options: on, off, and auto +# +# @auto: QEMU selects the value between on and off +# +# @on: Enabled +# +# @off: Disabled +# +# Since: 2.2 +## +{ 'enum': 'OnOffAuto', + 'data': [ 'auto', 'on', 'off' ] } + +## +# @OnOffSplit: +# +# An enumeration of three values: on, off, and split +# +# @on: Enabled +# +# @off: Disabled +# +# @split: Mixed +# +# Since: 2.6 +## +{ 'enum': 'OnOffSplit', + 'data': [ 'on', 'off', 'split' ] } + +## +# @String: +# +# A fat type wrapping 'str', to be embedded in lists. +# +# Since: 1.2 +## +{ 'struct': 'String', + 'data': { + 'str': 'str' } } + +## +# @StrOrNull: +# +# This is a string value or the explicit lack of a string (null +# pointer in C). Intended for cases when 'optional absent' already +# has a different meaning. +# +# @s: the string value +# @n: no string value +# +# Since: 2.10 +## +{ 'alternate': 'StrOrNull', + 'data': { 's': 'str', + 'n': 'null' } } + +## +# @OffAutoPCIBAR: +# +# An enumeration of options for specifying a PCI BAR +# +# @off: The specified feature is disabled +# +# @auto: The PCI BAR for the feature is automatically selected +# +# @bar0: PCI BAR0 is used for the feature +# +# @bar1: PCI BAR1 is used for the feature +# +# @bar2: PCI BAR2 is used for the feature +# +# @bar3: PCI BAR3 is used for the feature +# +# @bar4: PCI BAR4 is used for the feature +# +# @bar5: PCI BAR5 is used for the feature +# +# Since: 2.12 +## +{ 'enum': 'OffAutoPCIBAR', + 'data': [ 'off', 'auto', 'bar0', 'bar1', 'bar2', 'bar3', 'bar4', 'bar5' ] } + +## +# @PCIELinkSpeed: +# +# An enumeration of PCIe link speeds in units of GT/s +# +# @2_5: 2.5GT/s +# +# @5: 5.0GT/s +# +# @8: 8.0GT/s +# +# @16: 16.0GT/s +# +# Since: 4.0 +## +{ 'enum': 'PCIELinkSpeed', + 'data': [ '2_5', '5', '8', '16' ] } + +## +# @PCIELinkWidth: +# +# An enumeration of PCIe link width +# +# @1: x1 +# +# @2: x2 +# +# @4: x4 +# +# @8: x8 +# +# @12: x12 +# +# @16: x16 +# +# @32: x32 +# +# Since: 4.0 +## +{ 'enum': 'PCIELinkWidth', + 'data': [ '1', '2', '4', '8', '12', '16', '32' ] } + +## +# @HostMemPolicy: +# +# Host memory policy types +# +# @default: restore default policy, remove any nondefault policy +# +# @preferred: set the preferred host nodes for allocation +# +# @bind: a strict policy that restricts memory allocation to the +# host nodes specified +# +# @interleave: memory allocations are interleaved across the set +# of host nodes specified +# +# Since: 2.1 +## +{ 'enum': 'HostMemPolicy', + 'data': [ 'default', 'preferred', 'bind', 'interleave' ] } + +## +# @NetFilterDirection: +# +# Indicates whether a netfilter is attached to a netdev's transmit queue or +# receive queue or both. +# +# @all: the filter is attached both to the receive and the transmit +# queue of the netdev (default). +# +# @rx: the filter is attached to the receive queue of the netdev, +# where it will receive packets sent to the netdev. +# +# @tx: the filter is attached to the transmit queue of the netdev, +# where it will receive packets sent by the netdev. +# +# Since: 2.5 +## +{ 'enum': 'NetFilterDirection', + 'data': [ 'all', 'rx', 'tx' ] } + +## +# @GrabToggleKeys: +# +# Keys to toggle input-linux between host and guest. +# +# Since: 4.0 +# +## +{ 'enum': 'GrabToggleKeys', + 'data': [ 'ctrl-ctrl', 'alt-alt', 'shift-shift','meta-meta', 'scrolllock', + 'ctrl-scrolllock' ] } + +## +# @HumanReadableText: +# +# @human-readable-text: Formatted output intended for humans. +# +# Since: 6.2 +# +## +{ 'struct': 'HumanReadableText', + 'data': { 'human-readable-text': 'str' } } diff --git a/qapi/compat.json b/qapi/compat.json new file mode 100644 index 000000000..dd7261ae2 --- /dev/null +++ b/qapi/compat.json @@ -0,0 +1,61 @@ +# -*- Mode: Python -*- + +## +# = Compatibility policy +## + +## +# @CompatPolicyInput: +# +# Policy for handling "funny" input. +# +# @accept: Accept silently +# @reject: Reject with an error +# @crash: abort() the process +# +# Since: 6.0 +## +{ 'enum': 'CompatPolicyInput', + 'data': [ 'accept', 'reject', 'crash' ] } + +## +# @CompatPolicyOutput: +# +# Policy for handling "funny" output. +# +# @accept: Pass on unchanged +# @hide: Filter out +# +# Since: 6.0 +## +{ 'enum': 'CompatPolicyOutput', + 'data': [ 'accept', 'hide' ] } + +## +# @CompatPolicy: +# +# Policy for handling deprecated management interfaces. +# +# This is intended for testing users of the management interfaces. +# +# Limitation: covers only syntactic aspects of QMP, i.e. stuff tagged +# with feature 'deprecated'. We may want to extend it to cover +# semantic aspects, CLI, and experimental features. +# +# Limitation: deprecated-output policy @hide is not implemented for +# enumeration values. They behave the same as with policy @accept. +# +# @deprecated-input: how to handle deprecated input (default 'accept') +# @deprecated-output: how to handle deprecated output (default 'accept') +# @unstable-input: how to handle unstable input (default 'accept') +# (since 6.2) +# @unstable-output: how to handle unstable output (default 'accept') +# (since 6.2) +# +# Since: 6.0 +## +{ 'struct': 'CompatPolicy', + 'data': { '*deprecated-input': 'CompatPolicyInput', + '*deprecated-output': 'CompatPolicyOutput', + '*unstable-input': 'CompatPolicyInput', + '*unstable-output': 'CompatPolicyOutput' } } diff --git a/qapi/control.json b/qapi/control.json new file mode 100644 index 000000000..71a838d49 --- /dev/null +++ b/qapi/control.json @@ -0,0 +1,215 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = QMP monitor control +## + +## +# @qmp_capabilities: +# +# Enable QMP capabilities. +# +# Arguments: +# +# @enable: An optional list of QMPCapability values to enable. The +# client must not enable any capability that is not +# mentioned in the QMP greeting message. If the field is not +# provided, it means no QMP capabilities will be enabled. +# (since 2.12) +# +# Example: +# +# -> { "execute": "qmp_capabilities", +# "arguments": { "enable": [ "oob" ] } } +# <- { "return": {} } +# +# Notes: This command is valid exactly when first connecting: it must be +# issued before any other command will be accepted, and will fail once the +# monitor is accepting other commands. (see qemu docs/interop/qmp-spec.txt) +# +# The QMP client needs to explicitly enable QMP capabilities, otherwise +# all the QMP capabilities will be turned off by default. +# +# Since: 0.13 +# +## +{ 'command': 'qmp_capabilities', + 'data': { '*enable': [ 'QMPCapability' ] }, + 'allow-preconfig': true } + +## +# @QMPCapability: +# +# Enumeration of capabilities to be advertised during initial client +# connection, used for agreeing on particular QMP extension behaviors. +# +# @oob: QMP ability to support out-of-band requests. +# (Please refer to qmp-spec.txt for more information on OOB) +# +# Since: 2.12 +# +## +{ 'enum': 'QMPCapability', + 'data': [ 'oob' ] } + +## +# @VersionTriple: +# +# A three-part version number. +# +# @major: The major version number. +# +# @minor: The minor version number. +# +# @micro: The micro version number. +# +# Since: 2.4 +## +{ 'struct': 'VersionTriple', + 'data': {'major': 'int', 'minor': 'int', 'micro': 'int'} } + + +## +# @VersionInfo: +# +# A description of QEMU's version. +# +# @qemu: The version of QEMU. By current convention, a micro +# version of 50 signifies a development branch. A micro version +# greater than or equal to 90 signifies a release candidate for +# the next minor version. A micro version of less than 50 +# signifies a stable release. +# +# @package: QEMU will always set this field to an empty string. Downstream +# versions of QEMU should set this to a non-empty string. The +# exact format depends on the downstream however it highly +# recommended that a unique name is used. +# +# Since: 0.14 +## +{ 'struct': 'VersionInfo', + 'data': {'qemu': 'VersionTriple', 'package': 'str'} } + +## +# @query-version: +# +# Returns the current version of QEMU. +# +# Returns: A @VersionInfo object describing the current version of QEMU. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-version" } +# <- { +# "return":{ +# "qemu":{ +# "major":0, +# "minor":11, +# "micro":5 +# }, +# "package":"" +# } +# } +# +## +{ 'command': 'query-version', 'returns': 'VersionInfo', + 'allow-preconfig': true } + +## +# @CommandInfo: +# +# Information about a QMP command +# +# @name: The command name +# +# Since: 0.14 +## +{ 'struct': 'CommandInfo', 'data': {'name': 'str'} } + +## +# @query-commands: +# +# Return a list of supported QMP commands by this server +# +# Returns: A list of @CommandInfo for all supported commands +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-commands" } +# <- { +# "return":[ +# { +# "name":"query-balloon" +# }, +# { +# "name":"system_powerdown" +# } +# ] +# } +# +# Note: This example has been shortened as the real response is too long. +# +## +{ 'command': 'query-commands', 'returns': ['CommandInfo'], + 'allow-preconfig': true } + +## +# @quit: +# +# This command will cause the QEMU process to exit gracefully. While every +# attempt is made to send the QMP response before terminating, this is not +# guaranteed. When using this interface, a premature EOF would not be +# unexpected. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "quit" } +# <- { "return": {} } +## +{ 'command': 'quit', + 'allow-preconfig': true } + +## +# @MonitorMode: +# +# An enumeration of monitor modes. +# +# @readline: HMP monitor (human-oriented command line interface) +# +# @control: QMP monitor (JSON-based machine interface) +# +# Since: 5.0 +## +{ 'enum': 'MonitorMode', 'data': [ 'readline', 'control' ] } + +## +# @MonitorOptions: +# +# Options to be used for adding a new monitor. +# +# @id: Name of the monitor +# +# @mode: Selects the monitor mode (default: readline in the system +# emulator, control in qemu-storage-daemon) +# +# @pretty: Enables pretty printing (QMP only) +# +# @chardev: Name of a character device to expose the monitor on +# +# Since: 5.0 +## +{ 'struct': 'MonitorOptions', + 'data': { + '*id': 'str', + '*mode': 'MonitorMode', + '*pretty': 'bool', + 'chardev': 'str' + } } diff --git a/qapi/crypto.json b/qapi/crypto.json new file mode 100644 index 000000000..1ec54c15c --- /dev/null +++ b/qapi/crypto.json @@ -0,0 +1,542 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Cryptography +## + +## +# @QCryptoTLSCredsEndpoint: +# +# The type of network endpoint that will be using the credentials. +# Most types of credential require different setup / structures +# depending on whether they will be used in a server versus a +# client. +# +# @client: the network endpoint is acting as the client +# +# @server: the network endpoint is acting as the server +# +# Since: 2.5 +## +{ 'enum': 'QCryptoTLSCredsEndpoint', + 'prefix': 'QCRYPTO_TLS_CREDS_ENDPOINT', + 'data': ['client', 'server']} + + +## +# @QCryptoSecretFormat: +# +# The data format that the secret is provided in +# +# @raw: raw bytes. When encoded in JSON only valid UTF-8 sequences can be used +# @base64: arbitrary base64 encoded binary data +# Since: 2.6 +## +{ 'enum': 'QCryptoSecretFormat', + 'prefix': 'QCRYPTO_SECRET_FORMAT', + 'data': ['raw', 'base64']} + + +## +# @QCryptoHashAlgorithm: +# +# The supported algorithms for computing content digests +# +# @md5: MD5. Should not be used in any new code, legacy compat only +# @sha1: SHA-1. Should not be used in any new code, legacy compat only +# @sha224: SHA-224. (since 2.7) +# @sha256: SHA-256. Current recommended strong hash. +# @sha384: SHA-384. (since 2.7) +# @sha512: SHA-512. (since 2.7) +# @ripemd160: RIPEMD-160. (since 2.7) +# Since: 2.6 +## +{ 'enum': 'QCryptoHashAlgorithm', + 'prefix': 'QCRYPTO_HASH_ALG', + 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160']} + + +## +# @QCryptoCipherAlgorithm: +# +# The supported algorithms for content encryption ciphers +# +# @aes-128: AES with 128 bit / 16 byte keys +# @aes-192: AES with 192 bit / 24 byte keys +# @aes-256: AES with 256 bit / 32 byte keys +# @des: DES with 56 bit / 8 byte keys. Do not use except in VNC. (since 6.1) +# @3des: 3DES(EDE) with 192 bit / 24 byte keys (since 2.9) +# @cast5-128: Cast5 with 128 bit / 16 byte keys +# @serpent-128: Serpent with 128 bit / 16 byte keys +# @serpent-192: Serpent with 192 bit / 24 byte keys +# @serpent-256: Serpent with 256 bit / 32 byte keys +# @twofish-128: Twofish with 128 bit / 16 byte keys +# @twofish-192: Twofish with 192 bit / 24 byte keys +# @twofish-256: Twofish with 256 bit / 32 byte keys +# Since: 2.6 +## +{ 'enum': 'QCryptoCipherAlgorithm', + 'prefix': 'QCRYPTO_CIPHER_ALG', + 'data': ['aes-128', 'aes-192', 'aes-256', + 'des', '3des', + 'cast5-128', + 'serpent-128', 'serpent-192', 'serpent-256', + 'twofish-128', 'twofish-192', 'twofish-256']} + + +## +# @QCryptoCipherMode: +# +# The supported modes for content encryption ciphers +# +# @ecb: Electronic Code Book +# @cbc: Cipher Block Chaining +# @xts: XEX with tweaked code book and ciphertext stealing +# @ctr: Counter (Since 2.8) +# Since: 2.6 +## +{ 'enum': 'QCryptoCipherMode', + 'prefix': 'QCRYPTO_CIPHER_MODE', + 'data': ['ecb', 'cbc', 'xts', 'ctr']} + + +## +# @QCryptoIVGenAlgorithm: +# +# The supported algorithms for generating initialization +# vectors for full disk encryption. The 'plain' generator +# should not be used for disks with sector numbers larger +# than 2^32, except where compatibility with pre-existing +# Linux dm-crypt volumes is required. +# +# @plain: 64-bit sector number truncated to 32-bits +# @plain64: 64-bit sector number +# @essiv: 64-bit sector number encrypted with a hash of the encryption key +# Since: 2.6 +## +{ 'enum': 'QCryptoIVGenAlgorithm', + 'prefix': 'QCRYPTO_IVGEN_ALG', + 'data': ['plain', 'plain64', 'essiv']} + +## +# @QCryptoBlockFormat: +# +# The supported full disk encryption formats +# +# @qcow: QCow/QCow2 built-in AES-CBC encryption. Use only +# for liberating data from old images. +# @luks: LUKS encryption format. Recommended for new images +# +# Since: 2.6 +## +{ 'enum': 'QCryptoBlockFormat', +# 'prefix': 'QCRYPTO_BLOCK_FORMAT', + 'data': ['qcow', 'luks']} + +## +# @QCryptoBlockOptionsBase: +# +# The common options that apply to all full disk +# encryption formats +# +# @format: the encryption format +# +# Since: 2.6 +## +{ 'struct': 'QCryptoBlockOptionsBase', + 'data': { 'format': 'QCryptoBlockFormat' }} + +## +# @QCryptoBlockOptionsQCow: +# +# The options that apply to QCow/QCow2 AES-CBC encryption format +# +# @key-secret: the ID of a QCryptoSecret object providing the +# decryption key. Mandatory except when probing image for +# metadata only. +# +# Since: 2.6 +## +{ 'struct': 'QCryptoBlockOptionsQCow', + 'data': { '*key-secret': 'str' }} + +## +# @QCryptoBlockOptionsLUKS: +# +# The options that apply to LUKS encryption format +# +# @key-secret: the ID of a QCryptoSecret object providing the +# decryption key. Mandatory except when probing image for +# metadata only. +# Since: 2.6 +## +{ 'struct': 'QCryptoBlockOptionsLUKS', + 'data': { '*key-secret': 'str' }} + + +## +# @QCryptoBlockCreateOptionsLUKS: +# +# The options that apply to LUKS encryption format initialization +# +# @cipher-alg: the cipher algorithm for data encryption +# Currently defaults to 'aes-256'. +# @cipher-mode: the cipher mode for data encryption +# Currently defaults to 'xts' +# @ivgen-alg: the initialization vector generator +# Currently defaults to 'plain64' +# @ivgen-hash-alg: the initialization vector generator hash +# Currently defaults to 'sha256' +# @hash-alg: the master key hash algorithm +# Currently defaults to 'sha256' +# @iter-time: number of milliseconds to spend in +# PBKDF passphrase processing. Currently defaults +# to 2000. (since 2.8) +# Since: 2.6 +## +{ 'struct': 'QCryptoBlockCreateOptionsLUKS', + 'base': 'QCryptoBlockOptionsLUKS', + 'data': { '*cipher-alg': 'QCryptoCipherAlgorithm', + '*cipher-mode': 'QCryptoCipherMode', + '*ivgen-alg': 'QCryptoIVGenAlgorithm', + '*ivgen-hash-alg': 'QCryptoHashAlgorithm', + '*hash-alg': 'QCryptoHashAlgorithm', + '*iter-time': 'int'}} + + +## +# @QCryptoBlockOpenOptions: +# +# The options that are available for all encryption formats +# when opening an existing volume +# +# Since: 2.6 +## +{ 'union': 'QCryptoBlockOpenOptions', + 'base': 'QCryptoBlockOptionsBase', + 'discriminator': 'format', + 'data': { 'qcow': 'QCryptoBlockOptionsQCow', + 'luks': 'QCryptoBlockOptionsLUKS' } } + + +## +# @QCryptoBlockCreateOptions: +# +# The options that are available for all encryption formats +# when initializing a new volume +# +# Since: 2.6 +## +{ 'union': 'QCryptoBlockCreateOptions', + 'base': 'QCryptoBlockOptionsBase', + 'discriminator': 'format', + 'data': { 'qcow': 'QCryptoBlockOptionsQCow', + 'luks': 'QCryptoBlockCreateOptionsLUKS' } } + + +## +# @QCryptoBlockInfoBase: +# +# The common information that applies to all full disk +# encryption formats +# +# @format: the encryption format +# +# Since: 2.7 +## +{ 'struct': 'QCryptoBlockInfoBase', + 'data': { 'format': 'QCryptoBlockFormat' }} + + +## +# @QCryptoBlockInfoLUKSSlot: +# +# Information about the LUKS block encryption key +# slot options +# +# @active: whether the key slot is currently in use +# @key-offset: offset to the key material in bytes +# @iters: number of PBKDF2 iterations for key material +# @stripes: number of stripes for splitting key material +# +# Since: 2.7 +## +{ 'struct': 'QCryptoBlockInfoLUKSSlot', + 'data': {'active': 'bool', + '*iters': 'int', + '*stripes': 'int', + 'key-offset': 'int' } } + + +## +# @QCryptoBlockInfoLUKS: +# +# Information about the LUKS block encryption options +# +# @cipher-alg: the cipher algorithm for data encryption +# @cipher-mode: the cipher mode for data encryption +# @ivgen-alg: the initialization vector generator +# @ivgen-hash-alg: the initialization vector generator hash +# @hash-alg: the master key hash algorithm +# @payload-offset: offset to the payload data in bytes +# @master-key-iters: number of PBKDF2 iterations for key material +# @uuid: unique identifier for the volume +# @slots: information about each key slot +# +# Since: 2.7 +## +{ 'struct': 'QCryptoBlockInfoLUKS', + 'data': {'cipher-alg': 'QCryptoCipherAlgorithm', + 'cipher-mode': 'QCryptoCipherMode', + 'ivgen-alg': 'QCryptoIVGenAlgorithm', + '*ivgen-hash-alg': 'QCryptoHashAlgorithm', + 'hash-alg': 'QCryptoHashAlgorithm', + 'payload-offset': 'int', + 'master-key-iters': 'int', + 'uuid': 'str', + 'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }} + +## +# @QCryptoBlockInfo: +# +# Information about the block encryption options +# +# Since: 2.7 +## +{ 'union': 'QCryptoBlockInfo', + 'base': 'QCryptoBlockInfoBase', + 'discriminator': 'format', + 'data': { 'luks': 'QCryptoBlockInfoLUKS' } } + +## +# @QCryptoBlockLUKSKeyslotState: +# +# Defines state of keyslots that are affected by the update +# +# @active: The slots contain the given password and marked as active +# @inactive: The slots are erased (contain garbage) and marked as inactive +# +# Since: 5.1 +## +{ 'enum': 'QCryptoBlockLUKSKeyslotState', + 'data': [ 'active', 'inactive' ] } + + +## +# @QCryptoBlockAmendOptionsLUKS: +# +# This struct defines the update parameters that activate/de-activate set +# of keyslots +# +# @state: the desired state of the keyslots +# +# @new-secret: The ID of a QCryptoSecret object providing the password to be +# written into added active keyslots +# +# @old-secret: Optional (for deactivation only) +# If given will deactivate all keyslots that +# match password located in QCryptoSecret with this ID +# +# @iter-time: Optional (for activation only) +# Number of milliseconds to spend in +# PBKDF passphrase processing for the newly activated keyslot. +# Currently defaults to 2000. +# +# @keyslot: Optional. ID of the keyslot to activate/deactivate. +# For keyslot activation, keyslot should not be active already +# (this is unsafe to update an active keyslot), +# but possible if 'force' parameter is given. +# If keyslot is not given, first free keyslot will be written. +# +# For keyslot deactivation, this parameter specifies the exact +# keyslot to deactivate +# +# @secret: Optional. The ID of a QCryptoSecret object providing the +# password to use to retrieve current master key. +# Defaults to the same secret that was used to open the image +# +# +# Since 5.1 +## +{ 'struct': 'QCryptoBlockAmendOptionsLUKS', + 'data': { 'state': 'QCryptoBlockLUKSKeyslotState', + '*new-secret': 'str', + '*old-secret': 'str', + '*keyslot': 'int', + '*iter-time': 'int', + '*secret': 'str' } } + +## +# @QCryptoBlockAmendOptions: +# +# The options that are available for all encryption formats +# when amending encryption settings +# +# Since: 5.1 +## +{ 'union': 'QCryptoBlockAmendOptions', + 'base': 'QCryptoBlockOptionsBase', + 'discriminator': 'format', + 'data': { + 'luks': 'QCryptoBlockAmendOptionsLUKS' } } + +## +# @SecretCommonProperties: +# +# Properties for objects of classes derived from secret-common. +# +# @loaded: if true, the secret is loaded immediately when applying this option +# and will probably fail when processing the next option. Don't use; +# only provided for compatibility. (default: false) +# +# @format: the data format that the secret is provided in (default: raw) +# +# @keyid: the name of another secret that should be used to decrypt the +# provided data. If not present, the data is assumed to be unencrypted. +# +# @iv: the random initialization vector used for encryption of this particular +# secret. Should be a base64 encrypted string of the 16-byte IV. Mandatory +# if @keyid is given. Ignored if @keyid is absent. +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 2.6 +## +{ 'struct': 'SecretCommonProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] }, + '*format': 'QCryptoSecretFormat', + '*keyid': 'str', + '*iv': 'str' } } + +## +# @SecretProperties: +# +# Properties for secret objects. +# +# Either @data or @file must be provided, but not both. +# +# @data: the associated with the secret from +# +# @file: the filename to load the data associated with the secret from +# +# Since: 2.6 +## +{ 'struct': 'SecretProperties', + 'base': 'SecretCommonProperties', + 'data': { '*data': 'str', + '*file': 'str' } } + +## +# @SecretKeyringProperties: +# +# Properties for secret_keyring objects. +# +# @serial: serial number that identifies a key to get from the kernel +# +# Since: 5.1 +## +{ 'struct': 'SecretKeyringProperties', + 'base': 'SecretCommonProperties', + 'data': { 'serial': 'int32' } } + +## +# @TlsCredsProperties: +# +# Properties for objects of classes derived from tls-creds. +# +# @verify-peer: if true the peer credentials will be verified once the +# handshake is completed. This is a no-op for anonymous +# credentials. (default: true) +# +# @dir: the path of the directory that contains the credential files +# +# @endpoint: whether the QEMU network backend that uses the credentials will be +# acting as a client or as a server (default: client) +# +# @priority: a gnutls priority string as described at +# https://gnutls.org/manual/html_node/Priority-Strings.html +# +# Since: 2.5 +## +{ 'struct': 'TlsCredsProperties', + 'data': { '*verify-peer': 'bool', + '*dir': 'str', + '*endpoint': 'QCryptoTLSCredsEndpoint', + '*priority': 'str' } } + +## +# @TlsCredsAnonProperties: +# +# Properties for tls-creds-anon objects. +# +# @loaded: if true, the credentials are loaded immediately when applying this +# option and will ignore options that are processed later. Don't use; +# only provided for compatibility. (default: false) +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 2.5 +## +{ 'struct': 'TlsCredsAnonProperties', + 'base': 'TlsCredsProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] } } } + +## +# @TlsCredsPskProperties: +# +# Properties for tls-creds-psk objects. +# +# @loaded: if true, the credentials are loaded immediately when applying this +# option and will ignore options that are processed later. Don't use; +# only provided for compatibility. (default: false) +# +# @username: the username which will be sent to the server. For clients only. +# If absent, "qemu" is sent and the property will read back as an +# empty string. +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 3.0 +## +{ 'struct': 'TlsCredsPskProperties', + 'base': 'TlsCredsProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] }, + '*username': 'str' } } + +## +# @TlsCredsX509Properties: +# +# Properties for tls-creds-x509 objects. +# +# @loaded: if true, the credentials are loaded immediately when applying this +# option and will ignore options that are processed later. Don't use; +# only provided for compatibility. (default: false) +# +# @sanity-check: if true, perform some sanity checks before using the +# credentials (default: true) +# +# @passwordid: For the server-key.pem and client-key.pem files which contain +# sensitive private keys, it is possible to use an encrypted +# version by providing the @passwordid parameter. This provides +# the ID of a previously created secret object containing the +# password for decryption. +# +# Features: +# @deprecated: Member @loaded is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 2.5 +## +{ 'struct': 'TlsCredsX509Properties', + 'base': 'TlsCredsProperties', + 'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] }, + '*sanity-check': 'bool', + '*passwordid': 'str' } } diff --git a/qapi/dump.json b/qapi/dump.json new file mode 100644 index 000000000..f7c4267e3 --- /dev/null +++ b/qapi/dump.json @@ -0,0 +1,201 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Dump guest memory +## + +## +# @DumpGuestMemoryFormat: +# +# An enumeration of guest-memory-dump's format. +# +# @elf: elf format +# +# @kdump-zlib: kdump-compressed format with zlib-compressed +# +# @kdump-lzo: kdump-compressed format with lzo-compressed +# +# @kdump-snappy: kdump-compressed format with snappy-compressed +# +# @win-dmp: Windows full crashdump format, +# can be used instead of ELF converting (since 2.13) +# +# Since: 2.0 +## +{ 'enum': 'DumpGuestMemoryFormat', + 'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy', 'win-dmp' ] } + +## +# @dump-guest-memory: +# +# Dump guest's memory to vmcore. It is a synchronous operation that can take +# very long depending on the amount of guest memory. +# +# @paging: if true, do paging to get guest's memory mapping. This allows +# using gdb to process the core file. +# +# IMPORTANT: this option can make QEMU allocate several gigabytes +# of RAM. This can happen for a large guest, or a +# malicious guest pretending to be large. +# +# Also, paging=true has the following limitations: +# +# 1. The guest may be in a catastrophic state or can have corrupted +# memory, which cannot be trusted +# 2. The guest can be in real-mode even if paging is enabled. For +# example, the guest uses ACPI to sleep, and ACPI sleep state +# goes in real-mode +# 3. Currently only supported on i386 and x86_64. +# +# @protocol: the filename or file descriptor of the vmcore. The supported +# protocols are: +# +# 1. file: the protocol starts with "file:", and the following +# string is the file's path. +# 2. fd: the protocol starts with "fd:", and the following string +# is the fd's name. +# +# @detach: if true, QMP will return immediately rather than +# waiting for the dump to finish. The user can track progress +# using "query-dump". (since 2.6). +# +# @begin: if specified, the starting physical address. +# +# @length: if specified, the memory size, in bytes. If you don't +# want to dump all guest's memory, please specify the start @begin +# and @length +# +# @format: if specified, the format of guest memory dump. But non-elf +# format is conflict with paging and filter, ie. @paging, @begin and +# @length is not allowed to be specified with non-elf @format at the +# same time (since 2.0) +# +# Note: All boolean arguments default to false +# +# Returns: nothing on success +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "dump-guest-memory", +# "arguments": { "protocol": "fd:dump" } } +# <- { "return": {} } +# +## +{ 'command': 'dump-guest-memory', + 'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool', + '*begin': 'int', '*length': 'int', + '*format': 'DumpGuestMemoryFormat'} } + +## +# @DumpStatus: +# +# Describe the status of a long-running background guest memory dump. +# +# @none: no dump-guest-memory has started yet. +# +# @active: there is one dump running in background. +# +# @completed: the last dump has finished successfully. +# +# @failed: the last dump has failed. +# +# Since: 2.6 +## +{ 'enum': 'DumpStatus', + 'data': [ 'none', 'active', 'completed', 'failed' ] } + +## +# @DumpQueryResult: +# +# The result format for 'query-dump'. +# +# @status: enum of @DumpStatus, which shows current dump status +# +# @completed: bytes written in latest dump (uncompressed) +# +# @total: total bytes to be written in latest dump (uncompressed) +# +# Since: 2.6 +## +{ 'struct': 'DumpQueryResult', + 'data': { 'status': 'DumpStatus', + 'completed': 'int', + 'total': 'int' } } + +## +# @query-dump: +# +# Query latest dump status. +# +# Returns: A @DumpStatus object showing the dump status. +# +# Since: 2.6 +# +# Example: +# +# -> { "execute": "query-dump" } +# <- { "return": { "status": "active", "completed": 1024000, +# "total": 2048000 } } +# +## +{ 'command': 'query-dump', 'returns': 'DumpQueryResult' } + +## +# @DUMP_COMPLETED: +# +# Emitted when background dump has completed +# +# @result: final dump status +# +# @error: human-readable error string that provides +# hint on why dump failed. Only presents on failure. The +# user should not try to interpret the error string. +# +# Since: 2.6 +# +# Example: +# +# { "event": "DUMP_COMPLETED", +# "data": {"result": {"total": 1090650112, "status": "completed", +# "completed": 1090650112} } } +# +## +{ 'event': 'DUMP_COMPLETED' , + 'data': { 'result': 'DumpQueryResult', '*error': 'str' } } + +## +# @DumpGuestMemoryCapability: +# +# A list of the available formats for dump-guest-memory +# +# Since: 2.0 +## +{ 'struct': 'DumpGuestMemoryCapability', + 'data': { + 'formats': ['DumpGuestMemoryFormat'] } } + +## +# @query-dump-guest-memory-capability: +# +# Returns the available formats for dump-guest-memory +# +# Returns: A @DumpGuestMemoryCapability object listing available formats for +# dump-guest-memory +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "query-dump-guest-memory-capability" } +# <- { "return": { "formats": +# ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] } +# +## +{ 'command': 'query-dump-guest-memory-capability', + 'returns': 'DumpGuestMemoryCapability' } diff --git a/qapi/error.json b/qapi/error.json new file mode 100644 index 000000000..94a6502de --- /dev/null +++ b/qapi/error.json @@ -0,0 +1,30 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# = QMP errors +## + +## +# @QapiErrorClass: +# +# 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 +# +# @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 +# +# Since: 1.2 +## +{ 'enum': 'QapiErrorClass', + # Keep this in sync with ErrorClass in error.h + 'data': [ 'GenericError', 'CommandNotFound', + 'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] } diff --git a/qapi/introspect.json b/qapi/introspect.json new file mode 100644 index 000000000..183148b2e --- /dev/null +++ b/qapi/introspect.json @@ -0,0 +1,319 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# Copyright (C) 2015 Red Hat, Inc. +# +# Authors: +# Markus Armbruster <armbru@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = QMP introspection +## + +## +# @query-qmp-schema: +# +# Command query-qmp-schema exposes the QMP wire ABI as an array of +# SchemaInfo. This lets QMP clients figure out what commands and +# events are available in this QEMU, and their parameters and results. +# +# However, the SchemaInfo can't reflect all the rules and restrictions +# that apply to QMP. It's interface introspection (figuring out +# what's there), not interface specification. The specification is in +# the QAPI schema. +# +# Furthermore, while we strive to keep the QMP wire format +# backwards-compatible across qemu versions, the introspection output +# is not guaranteed to have the same stability. For example, one +# version of qemu may list an object member as an optional +# non-variant, while another lists the same member only through the +# object's variants; or the type of a member may change from a generic +# string into a specific enum or from one specific type into an +# alternate that includes the original type alongside something else. +# +# Returns: array of @SchemaInfo, where each element describes an +# entity in the ABI: command, event, type, ... +# +# The order of the various SchemaInfo is unspecified; however, all +# names are guaranteed to be unique (no name will be duplicated with +# different meta-types). +# +# Note: the QAPI schema is also used to help define *internal* +# interfaces, by defining QAPI types. These are not part of the QMP +# wire ABI, and therefore not returned by this command. +# +# Since: 2.5 +## +{ 'command': 'query-qmp-schema', + 'returns': [ 'SchemaInfo' ], + 'allow-preconfig': true } + +## +# @SchemaMetaType: +# +# This is a @SchemaInfo's meta type, i.e. the kind of entity it +# describes. +# +# @builtin: a predefined type such as 'int' or 'bool'. +# +# @enum: an enumeration type +# +# @array: an array type +# +# @object: an object type (struct or union) +# +# @alternate: an alternate type +# +# @command: a QMP command +# +# @event: a QMP event +# +# Since: 2.5 +## +{ 'enum': 'SchemaMetaType', + 'data': [ 'builtin', 'enum', 'array', 'object', 'alternate', + 'command', 'event' ] } + +## +# @SchemaInfo: +# +# @name: the entity's name, inherited from @base. +# The SchemaInfo is always referenced by this name. +# Commands and events have the name defined in the QAPI schema. +# Unlike command and event names, type names are not part of +# the wire ABI. Consequently, type names are meaningless +# strings here, although they are still guaranteed unique +# regardless of @meta-type. +# +# @meta-type: the entity's meta type, inherited from @base. +# +# @features: names of features associated with the entity, in no +# particular order. +# (since 4.1 for object types, 4.2 for commands, 5.0 for +# the rest) +# +# Additional members depend on the value of @meta-type. +# +# Since: 2.5 +## +{ 'union': 'SchemaInfo', + 'base': { 'name': 'str', 'meta-type': 'SchemaMetaType', + '*features': [ 'str' ] }, + 'discriminator': 'meta-type', + 'data': { + 'builtin': 'SchemaInfoBuiltin', + 'enum': 'SchemaInfoEnum', + 'array': 'SchemaInfoArray', + 'object': 'SchemaInfoObject', + 'alternate': 'SchemaInfoAlternate', + 'command': 'SchemaInfoCommand', + 'event': 'SchemaInfoEvent' } } + +## +# @SchemaInfoBuiltin: +# +# Additional SchemaInfo members for meta-type 'builtin'. +# +# @json-type: the JSON type used for this type on the wire. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoBuiltin', + 'data': { 'json-type': 'JSONType' } } + +## +# @JSONType: +# +# The four primitive and two structured types according to RFC 8259 +# section 1, plus 'int' (split off 'number'), plus the obvious top +# type 'value'. +# +# Since: 2.5 +## +{ 'enum': 'JSONType', + 'data': [ 'string', 'number', 'int', 'boolean', 'null', + 'object', 'array', 'value' ] } + +## +# @SchemaInfoEnum: +# +# Additional SchemaInfo members for meta-type 'enum'. +# +# @members: the enum type's members, in no particular order +# (since 6.2). +# +# @values: the enumeration type's member names, in no particular order. +# Redundant with @members. Just for backward compatibility. +# +# Features: +# @deprecated: Member @values is deprecated. Use @members instead. +# +# Values of this type are JSON string on the wire. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoEnum', + 'data': { 'members': [ 'SchemaInfoEnumMember' ], + 'values': { 'type': [ 'str' ], + 'features': [ 'deprecated' ] } } } + +## +# @SchemaInfoEnumMember: +# +# An object member. +# +# @name: the member's name, as defined in the QAPI schema. +# +# @features: names of features associated with the member, in no +# particular order. +# +# Since: 6.2 +## +{ 'struct': 'SchemaInfoEnumMember', + 'data': { 'name': 'str', '*features': [ 'str' ] } } + +## +# @SchemaInfoArray: +# +# Additional SchemaInfo members for meta-type 'array'. +# +# @element-type: the array type's element type. +# +# Values of this type are JSON array on the wire. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoArray', + 'data': { 'element-type': 'str' } } + +## +# @SchemaInfoObject: +# +# Additional SchemaInfo members for meta-type 'object'. +# +# @members: the object type's (non-variant) members, in no particular order. +# +# @tag: the name of the member serving as type tag. +# An element of @members with this name must exist. +# +# @variants: variant members, i.e. additional members that +# depend on the type tag's value. Present exactly when +# @tag is present. The variants are in no particular order, +# and may even differ from the order of the values of the +# enum type of the @tag. +# +# Values of this type are JSON object on the wire. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoObject', + 'data': { 'members': [ 'SchemaInfoObjectMember' ], + '*tag': 'str', + '*variants': [ 'SchemaInfoObjectVariant' ] } } + +## +# @SchemaInfoObjectMember: +# +# An object member. +# +# @name: the member's name, as defined in the QAPI schema. +# +# @type: the name of the member's type. +# +# @default: default when used as command parameter. +# If absent, the parameter is mandatory. +# If present, the value must be null. The parameter is +# optional, and behavior when it's missing is not specified +# here. +# Future extension: if present and non-null, the parameter +# is optional, and defaults to this value. +# +# @features: names of features associated with the member, in no +# particular order. (since 5.0) +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoObjectMember', + 'data': { 'name': 'str', 'type': 'str', '*default': 'any', +# @default's type must be null or match @type + '*features': [ 'str' ] } } + +## +# @SchemaInfoObjectVariant: +# +# The variant members for a value of the type tag. +# +# @case: a value of the type tag. +# +# @type: the name of the object type that provides the variant members +# when the type tag has value @case. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoObjectVariant', + 'data': { 'case': 'str', 'type': 'str' } } + +## +# @SchemaInfoAlternate: +# +# Additional SchemaInfo members for meta-type 'alternate'. +# +# @members: the alternate type's members, in no particular order. +# The members' wire encoding is distinct, see +# docs/devel/qapi-code-gen.txt section Alternate types. +# +# On the wire, this can be any of the members. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoAlternate', + 'data': { 'members': [ 'SchemaInfoAlternateMember' ] } } + +## +# @SchemaInfoAlternateMember: +# +# An alternate member. +# +# @type: the name of the member's type. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoAlternateMember', + 'data': { 'type': 'str' } } + +## +# @SchemaInfoCommand: +# +# Additional SchemaInfo members for meta-type 'command'. +# +# @arg-type: the name of the object type that provides the command's +# parameters. +# +# @ret-type: the name of the command's result type. +# +# @allow-oob: whether the command allows out-of-band execution, +# defaults to false (Since: 2.12) +# +# TODO: @success-response (currently irrelevant, because it's QGA, not QMP) +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoCommand', + 'data': { 'arg-type': 'str', 'ret-type': 'str', + '*allow-oob': 'bool' } } + +## +# @SchemaInfoEvent: +# +# Additional SchemaInfo members for meta-type 'event'. +# +# @arg-type: the name of the object type that provides the event's +# parameters. +# +# Since: 2.5 +## +{ 'struct': 'SchemaInfoEvent', + 'data': { 'arg-type': 'str' } } diff --git a/qapi/job.json b/qapi/job.json new file mode 100644 index 000000000..1a6ef0345 --- /dev/null +++ b/qapi/job.json @@ -0,0 +1,266 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# == Background jobs +## + +## +# @JobType: +# +# Type of a background job. +# +# @commit: block commit job type, see "block-commit" +# +# @stream: block stream job type, see "block-stream" +# +# @mirror: drive mirror job type, see "drive-mirror" +# +# @backup: drive backup job type, see "drive-backup" +# +# @create: image creation job type, see "blockdev-create" (since 3.0) +# +# @amend: image options amend job type, see "x-blockdev-amend" (since 5.1) +# +# @snapshot-load: snapshot load job type, see "snapshot-load" (since 6.0) +# +# @snapshot-save: snapshot save job type, see "snapshot-save" (since 6.0) +# +# @snapshot-delete: snapshot delete job type, see "snapshot-delete" (since 6.0) +# +# Since: 1.7 +## +{ 'enum': 'JobType', + 'data': ['commit', 'stream', 'mirror', 'backup', 'create', 'amend', + 'snapshot-load', 'snapshot-save', 'snapshot-delete'] } + +## +# @JobStatus: +# +# Indicates the present state of a given job in its lifetime. +# +# @undefined: Erroneous, default state. Should not ever be visible. +# +# @created: The job has been created, but not yet started. +# +# @running: The job is currently running. +# +# @paused: The job is running, but paused. The pause may be requested by +# either the QMP user or by internal processes. +# +# @ready: The job is running, but is ready for the user to signal completion. +# This is used for long-running jobs like mirror that are designed to +# run indefinitely. +# +# @standby: The job is ready, but paused. This is nearly identical to @paused. +# The job may return to @ready or otherwise be canceled. +# +# @waiting: The job is waiting for other jobs in the transaction to converge +# to the waiting state. This status will likely not be visible for +# the last job in a transaction. +# +# @pending: The job has finished its work, but has finalization steps that it +# needs to make prior to completing. These changes will require +# manual intervention via @job-finalize if auto-finalize was set to +# false. These pending changes may still fail. +# +# @aborting: The job is in the process of being aborted, and will finish with +# an error. The job will afterwards report that it is @concluded. +# This status may not be visible to the management process. +# +# @concluded: The job has finished all work. If auto-dismiss was set to false, +# the job will remain in the query list until it is dismissed via +# @job-dismiss. +# +# @null: The job is in the process of being dismantled. This state should not +# ever be visible externally. +# +# Since: 2.12 +## +{ 'enum': 'JobStatus', + 'data': ['undefined', 'created', 'running', 'paused', 'ready', 'standby', + 'waiting', 'pending', 'aborting', 'concluded', 'null' ] } + +## +# @JobVerb: +# +# Represents command verbs that can be applied to a job. +# +# @cancel: see @job-cancel +# +# @pause: see @job-pause +# +# @resume: see @job-resume +# +# @set-speed: see @block-job-set-speed +# +# @complete: see @job-complete +# +# @dismiss: see @job-dismiss +# +# @finalize: see @job-finalize +# +# Since: 2.12 +## +{ 'enum': 'JobVerb', + 'data': ['cancel', 'pause', 'resume', 'set-speed', 'complete', 'dismiss', + 'finalize' ] } + +## +# @JOB_STATUS_CHANGE: +# +# Emitted when a job transitions to a different status. +# +# @id: The job identifier +# @status: The new job status +# +# Since: 3.0 +## +{ 'event': 'JOB_STATUS_CHANGE', + 'data': { 'id': 'str', + 'status': 'JobStatus' } } + +## +# @job-pause: +# +# Pause an active job. +# +# This command returns immediately after marking the active job for pausing. +# Pausing an already paused job is an error. +# +# The job will pause as soon as possible, which means transitioning into the +# PAUSED state if it was RUNNING, or into STANDBY if it was READY. The +# corresponding JOB_STATUS_CHANGE event will be emitted. +# +# Cancelling a paused job automatically resumes it. +# +# @id: The job identifier. +# +# Since: 3.0 +## +{ 'command': 'job-pause', 'data': { 'id': 'str' } } + +## +# @job-resume: +# +# Resume a paused job. +# +# This command returns immediately after resuming a paused job. Resuming an +# already running job is an error. +# +# @id : The job identifier. +# +# Since: 3.0 +## +{ 'command': 'job-resume', 'data': { 'id': 'str' } } + +## +# @job-cancel: +# +# Instruct an active background job to cancel at the next opportunity. +# This command returns immediately after marking the active job for +# cancellation. +# +# The job will cancel as soon as possible and then emit a JOB_STATUS_CHANGE +# event. Usually, the status will change to ABORTING, but it is possible that +# a job successfully completes (e.g. because it was almost done and there was +# no opportunity to cancel earlier than completing the job) and transitions to +# PENDING instead. +# +# @id: The job identifier. +# +# Since: 3.0 +## +{ 'command': 'job-cancel', 'data': { 'id': 'str' } } + + +## +# @job-complete: +# +# Manually trigger completion of an active job in the READY state. +# +# @id: The job identifier. +# +# Since: 3.0 +## +{ 'command': 'job-complete', 'data': { 'id': 'str' } } + +## +# @job-dismiss: +# +# Deletes a job that is in the CONCLUDED state. This command only needs to be +# run explicitly for jobs that don't have automatic dismiss enabled. +# +# This command will refuse to operate on any job that has not yet reached its +# terminal state, JOB_STATUS_CONCLUDED. For jobs that make use of JOB_READY +# event, job-cancel or job-complete will still need to be used as appropriate. +# +# @id: The job identifier. +# +# Since: 3.0 +## +{ 'command': 'job-dismiss', 'data': { 'id': 'str' } } + +## +# @job-finalize: +# +# Instructs all jobs in a transaction (or a single job if it is not part of any +# transaction) to finalize any graph changes and do any necessary cleanup. This +# command requires that all involved jobs are in the PENDING state. +# +# For jobs in a transaction, instructing one job to finalize will force +# ALL jobs in the transaction to finalize, so it is only necessary to instruct +# a single member job to finalize. +# +# @id: The identifier of any job in the transaction, or of a job that is not +# part of any transaction. +# +# Since: 3.0 +## +{ 'command': 'job-finalize', 'data': { 'id': 'str' } } + +## +# @JobInfo: +# +# Information about a job. +# +# @id: The job identifier +# +# @type: The kind of job that is being performed +# +# @status: Current job state/status +# +# @current-progress: Progress made until now. The unit is arbitrary and the +# value can only meaningfully be used for the ratio of +# @current-progress to @total-progress. The value is +# monotonically increasing. +# +# @total-progress: Estimated @current-progress value at the completion of +# the job. This value can arbitrarily change while the +# job is running, in both directions. +# +# @error: If this field is present, the job failed; if it is +# still missing in the CONCLUDED state, this indicates +# successful completion. +# +# The value is a human-readable error message to describe +# the reason for the job failure. It should not be parsed +# by applications. +# +# Since: 3.0 +## +{ 'struct': 'JobInfo', + 'data': { 'id': 'str', 'type': 'JobType', 'status': 'JobStatus', + 'current-progress': 'int', 'total-progress': 'int', + '*error': 'str' } } + +## +# @query-jobs: +# +# Return information about jobs. +# +# Returns: a list with a @JobInfo for each active job +# +# Since: 3.0 +## +{ 'command': 'query-jobs', 'returns': ['JobInfo'] } diff --git a/qapi/machine-target.json b/qapi/machine-target.json new file mode 100644 index 000000000..f5ec4bc17 --- /dev/null +++ b/qapi/machine-target.json @@ -0,0 +1,343 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# @CpuModelInfo: +# +# Virtual CPU model. +# +# A CPU model consists of the name of a CPU definition, to which +# delta changes are applied (e.g. features added/removed). Most magic values +# that an architecture might require should be hidden behind the name. +# However, if required, architectures can expose relevant properties. +# +# @name: the name of the CPU definition the model is based on +# @props: a dictionary of QOM properties to be applied +# +# Since: 2.8 +## +{ 'struct': 'CpuModelInfo', + 'data': { 'name': 'str', + '*props': 'any' } } + +## +# @CpuModelExpansionType: +# +# An enumeration of CPU model expansion types. +# +# @static: Expand to a static CPU model, a combination of a static base +# model name and property delta changes. As the static base model will +# never change, the expanded CPU model will be the same, independent of +# QEMU version, machine type, machine options, and accelerator options. +# Therefore, the resulting model can be used by tooling without having +# to specify a compatibility machine - e.g. when displaying the "host" +# model. The @static CPU models are migration-safe. + +# @full: Expand all properties. The produced model is not guaranteed to be +# migration-safe, but allows tooling to get an insight and work with +# model details. +# +# Note: When a non-migration-safe CPU model is expanded in static mode, some +# features enabled by the CPU model may be omitted, because they can't be +# implemented by a static CPU model definition (e.g. cache info passthrough and +# PMU passthrough in x86). If you need an accurate representation of the +# features enabled by a non-migration-safe CPU model, use @full. If you need a +# static representation that will keep ABI compatibility even when changing QEMU +# version or machine-type, use @static (but keep in mind that some features may +# be omitted). +# +# Since: 2.8 +## +{ 'enum': 'CpuModelExpansionType', + 'data': [ 'static', 'full' ] } + + +## +# @CpuModelCompareResult: +# +# An enumeration of CPU model comparison results. The result is usually +# calculated using e.g. CPU features or CPU generations. +# +# @incompatible: If model A is incompatible to model B, model A is not +# guaranteed to run where model B runs and the other way around. +# +# @identical: If model A is identical to model B, model A is guaranteed to run +# where model B runs and the other way around. +# +# @superset: If model A is a superset of model B, model B is guaranteed to run +# where model A runs. There are no guarantees about the other way. +# +# @subset: If model A is a subset of model B, model A is guaranteed to run +# where model B runs. There are no guarantees about the other way. +# +# Since: 2.8 +## +{ 'enum': 'CpuModelCompareResult', + 'data': [ 'incompatible', 'identical', 'superset', 'subset' ] } + +## +# @CpuModelBaselineInfo: +# +# The result of a CPU model baseline. +# +# @model: the baselined CpuModelInfo. +# +# Since: 2.8 +## +{ 'struct': 'CpuModelBaselineInfo', + 'data': { 'model': 'CpuModelInfo' }, + 'if': 'TARGET_S390X' } + +## +# @CpuModelCompareInfo: +# +# The result of a CPU model comparison. +# +# @result: The result of the compare operation. +# @responsible-properties: List of properties that led to the comparison result +# not being identical. +# +# @responsible-properties is a list of QOM property names that led to +# both CPUs not being detected as identical. For identical models, this +# list is empty. +# If a QOM property is read-only, that means there's no known way to make the +# CPU models identical. If the special property name "type" is included, the +# models are by definition not identical and cannot be made identical. +# +# Since: 2.8 +## +{ 'struct': 'CpuModelCompareInfo', + 'data': { 'result': 'CpuModelCompareResult', + 'responsible-properties': ['str'] }, + 'if': 'TARGET_S390X' } + +## +# @query-cpu-model-comparison: +# +# Compares two CPU models, returning how they compare in a specific +# configuration. The results indicates how both models compare regarding +# runnability. This result can be used by tooling to make decisions if a +# certain CPU model will run in a certain configuration or if a compatible +# CPU model has to be created by baselining. +# +# Usually, a CPU model is compared against the maximum possible CPU model +# of a certain configuration (e.g. the "host" model for KVM). If that CPU +# model is identical or a subset, it will run in that configuration. +# +# The result returned by this command may be affected by: +# +# * QEMU version: CPU models may look different depending on the QEMU version. +# (Except for CPU models reported as "static" in query-cpu-definitions.) +# * machine-type: CPU model may look different depending on the machine-type. +# (Except for CPU models reported as "static" in query-cpu-definitions.) +# * machine options (including accelerator): in some architectures, CPU models +# may look different depending on machine and accelerator options. (Except for +# CPU models reported as "static" in query-cpu-definitions.) +# * "-cpu" arguments and global properties: arguments to the -cpu option and +# global properties may affect expansion of CPU models. Using +# query-cpu-model-expansion while using these is not advised. +# +# Some architectures may not support comparing CPU models. s390x supports +# comparing CPU models. +# +# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is +# not supported, if a model cannot be used, if a model contains +# an unknown cpu definition name, unknown properties or properties +# with wrong types. +# +# Note: this command isn't specific to s390x, but is only implemented +# on this architecture currently. +# +# Since: 2.8 +## +{ 'command': 'query-cpu-model-comparison', + 'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' }, + 'returns': 'CpuModelCompareInfo', + 'if': 'TARGET_S390X' } + +## +# @query-cpu-model-baseline: +# +# Baseline two CPU models, creating a compatible third model. The created +# model will always be a static, migration-safe CPU model (see "static" +# CPU model expansion for details). +# +# This interface can be used by tooling to create a compatible CPU model out +# two CPU models. The created CPU model will be identical to or a subset of +# both CPU models when comparing them. Therefore, the created CPU model is +# guaranteed to run where the given CPU models run. +# +# The result returned by this command may be affected by: +# +# * QEMU version: CPU models may look different depending on the QEMU version. +# (Except for CPU models reported as "static" in query-cpu-definitions.) +# * machine-type: CPU model may look different depending on the machine-type. +# (Except for CPU models reported as "static" in query-cpu-definitions.) +# * machine options (including accelerator): in some architectures, CPU models +# may look different depending on machine and accelerator options. (Except for +# CPU models reported as "static" in query-cpu-definitions.) +# * "-cpu" arguments and global properties: arguments to the -cpu option and +# global properties may affect expansion of CPU models. Using +# query-cpu-model-expansion while using these is not advised. +# +# Some architectures may not support baselining CPU models. s390x supports +# baselining CPU models. +# +# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is +# not supported, if a model cannot be used, if a model contains +# an unknown cpu definition name, unknown properties or properties +# with wrong types. +# +# Note: this command isn't specific to s390x, but is only implemented +# on this architecture currently. +# +# Since: 2.8 +## +{ 'command': 'query-cpu-model-baseline', + 'data': { 'modela': 'CpuModelInfo', + 'modelb': 'CpuModelInfo' }, + 'returns': 'CpuModelBaselineInfo', + 'if': 'TARGET_S390X' } + +## +# @CpuModelExpansionInfo: +# +# The result of a cpu model expansion. +# +# @model: the expanded CpuModelInfo. +# +# Since: 2.8 +## +{ 'struct': 'CpuModelExpansionInfo', + 'data': { 'model': 'CpuModelInfo' }, + 'if': { 'any': [ 'TARGET_S390X', + 'TARGET_I386', + 'TARGET_ARM' ] } } + +## +# @query-cpu-model-expansion: +# +# Expands a given CPU model (or a combination of CPU model + additional options) +# to different granularities, allowing tooling to get an understanding what a +# specific CPU model looks like in QEMU under a certain configuration. +# +# This interface can be used to query the "host" CPU model. +# +# The data returned by this command may be affected by: +# +# * QEMU version: CPU models may look different depending on the QEMU version. +# (Except for CPU models reported as "static" in query-cpu-definitions.) +# * machine-type: CPU model may look different depending on the machine-type. +# (Except for CPU models reported as "static" in query-cpu-definitions.) +# * machine options (including accelerator): in some architectures, CPU models +# may look different depending on machine and accelerator options. (Except for +# CPU models reported as "static" in query-cpu-definitions.) +# * "-cpu" arguments and global properties: arguments to the -cpu option and +# global properties may affect expansion of CPU models. Using +# query-cpu-model-expansion while using these is not advised. +# +# Some architectures may not support all expansion types. s390x supports +# "full" and "static". Arm only supports "full". +# +# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is +# not supported, if the model cannot be expanded, if the model contains +# an unknown CPU definition name, unknown properties or properties +# with a wrong type. Also returns an error if an expansion type is +# not supported. +# +# Since: 2.8 +## +{ 'command': 'query-cpu-model-expansion', + 'data': { 'type': 'CpuModelExpansionType', + 'model': 'CpuModelInfo' }, + 'returns': 'CpuModelExpansionInfo', + 'if': { 'any': [ 'TARGET_S390X', + 'TARGET_I386', + 'TARGET_ARM' ] } } + +## +# @CpuDefinitionInfo: +# +# Virtual CPU definition. +# +# @name: the name of the CPU definition +# +# @migration-safe: whether a CPU definition can be safely used for +# migration in combination with a QEMU compatibility machine +# when migrating between different QEMU versions and between +# hosts with different sets of (hardware or software) +# capabilities. If not provided, information is not available +# and callers should not assume the CPU definition to be +# migration-safe. (since 2.8) +# +# @static: whether a CPU definition is static and will not change depending on +# QEMU version, machine type, machine options and accelerator options. +# A static model is always migration-safe. (since 2.8) +# +# @unavailable-features: List of properties that prevent +# the CPU model from running in the current +# host. (since 2.8) +# @typename: Type name that can be used as argument to @device-list-properties, +# to introspect properties configurable using -cpu or -global. +# (since 2.9) +# +# @alias-of: Name of CPU model this model is an alias for. The target of the +# CPU model alias may change depending on the machine type. +# Management software is supposed to translate CPU model aliases +# in the VM configuration, because aliases may stop being +# migration-safe in the future (since 4.1) +# +# @deprecated: If true, this CPU model is deprecated and may be removed in +# in some future version of QEMU according to the QEMU deprecation +# policy. (since 5.2) +# +# @unavailable-features is a list of QOM property names that +# represent CPU model attributes that prevent the CPU from running. +# If the QOM property is read-only, that means there's no known +# way to make the CPU model run in the current host. Implementations +# that choose not to provide specific information return the +# property name "type". +# If the property is read-write, it means that it MAY be possible +# to run the CPU model in the current host if that property is +# changed. Management software can use it as hints to suggest or +# choose an alternative for the user, or just to generate meaningful +# error messages explaining why the CPU model can't be used. +# If @unavailable-features is an empty list, the CPU model is +# runnable using the current host and machine-type. +# If @unavailable-features is not present, runnability +# information for the CPU is not available. +# +# Since: 1.2 +## +{ 'struct': 'CpuDefinitionInfo', + 'data': { 'name': 'str', + '*migration-safe': 'bool', + 'static': 'bool', + '*unavailable-features': [ 'str' ], + 'typename': 'str', + '*alias-of' : 'str', + 'deprecated' : 'bool' }, + 'if': { 'any': [ 'TARGET_PPC', + 'TARGET_ARM', + 'TARGET_I386', + 'TARGET_S390X', + 'TARGET_MIPS' ] } } + +## +# @query-cpu-definitions: +# +# Return a list of supported virtual CPU definitions +# +# Returns: a list of CpuDefInfo +# +# Since: 1.2 +## +{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'], + 'if': { 'any': [ 'TARGET_PPC', + 'TARGET_ARM', + 'TARGET_I386', + 'TARGET_S390X', + 'TARGET_MIPS' ] } } diff --git a/qapi/machine.json b/qapi/machine.json new file mode 100644 index 000000000..067e3f537 --- /dev/null +++ b/qapi/machine.json @@ -0,0 +1,1559 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Machines +## + +{ 'include': 'common.json' } + +## +# @SysEmuTarget: +# +# The comprehensive enumeration of QEMU system emulation ("softmmu") +# targets. Run "./configure --help" in the project root directory, and +# look for the \*-softmmu targets near the "--target-list" option. The +# individual target constants are not documented here, for the time +# being. +# +# @rx: since 5.0 +# @avr: since 5.1 +# +# Notes: The resulting QMP strings can be appended to the "qemu-system-" +# prefix to produce the corresponding QEMU executable name. This +# is true even for "qemu-system-x86_64". +# +# Since: 3.0 +## +{ 'enum' : 'SysEmuTarget', + 'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386', + 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64', + 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc', + 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', + 'sh4eb', 'sparc', 'sparc64', 'tricore', + 'x86_64', 'xtensa', 'xtensaeb' ] } + +## +# @CpuS390State: +# +# An enumeration of cpu states that can be assumed by a virtual +# S390 CPU +# +# Since: 2.12 +## +{ 'enum': 'CpuS390State', + 'prefix': 'S390_CPU_STATE', + 'data': [ 'uninitialized', 'stopped', 'check-stop', 'operating', 'load' ] } + +## +# @CpuInfoS390: +# +# Additional information about a virtual S390 CPU +# +# @cpu-state: the virtual CPU's state +# +# Since: 2.12 +## +{ 'struct': 'CpuInfoS390', 'data': { 'cpu-state': 'CpuS390State' } } + +## +# @CpuInfoFast: +# +# Information about a virtual CPU +# +# @cpu-index: index of the virtual CPU +# +# @qom-path: path to the CPU object in the QOM tree +# +# @thread-id: ID of the underlying host thread +# +# @props: properties describing to which node/socket/core/thread +# virtual CPU belongs to, provided if supported by board +# +# @target: the QEMU system emulation target, which determines which +# additional fields will be listed (since 3.0) +# +# Since: 2.12 +# +## +{ 'union' : 'CpuInfoFast', + 'base' : { 'cpu-index' : 'int', + 'qom-path' : 'str', + 'thread-id' : 'int', + '*props' : 'CpuInstanceProperties', + 'target' : 'SysEmuTarget' }, + 'discriminator' : 'target', + 'data' : { 's390x' : 'CpuInfoS390' } } + +## +# @query-cpus-fast: +# +# Returns information about all virtual CPUs. +# +# Returns: list of @CpuInfoFast +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-cpus-fast" } +# <- { "return": [ +# { +# "thread-id": 25627, +# "props": { +# "core-id": 0, +# "thread-id": 0, +# "socket-id": 0 +# }, +# "qom-path": "/machine/unattached/device[0]", +# "arch":"x86", +# "target":"x86_64", +# "cpu-index": 0 +# }, +# { +# "thread-id": 25628, +# "props": { +# "core-id": 0, +# "thread-id": 0, +# "socket-id": 1 +# }, +# "qom-path": "/machine/unattached/device[2]", +# "arch":"x86", +# "target":"x86_64", +# "cpu-index": 1 +# } +# ] +# } +## +{ 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] } + +## +# @MachineInfo: +# +# Information describing a machine. +# +# @name: the name of the machine +# +# @alias: an alias for the machine name +# +# @is-default: whether the machine is default +# +# @cpu-max: maximum number of CPUs supported by the machine type +# (since 1.5) +# +# @hotpluggable-cpus: cpu hotplug via -device is supported (since 2.7) +# +# @numa-mem-supported: true if '-numa node,mem' option is supported by +# the machine type and false otherwise (since 4.1) +# +# @deprecated: if true, the machine type is deprecated and may be removed +# in future versions of QEMU according to the QEMU deprecation +# policy (since 4.1) +# +# @default-cpu-type: default CPU model typename if none is requested via +# the -cpu argument. (since 4.2) +# +# @default-ram-id: the default ID of initial RAM memory backend (since 5.2) +# +# Since: 1.2 +## +{ 'struct': 'MachineInfo', + 'data': { 'name': 'str', '*alias': 'str', + '*is-default': 'bool', 'cpu-max': 'int', + 'hotpluggable-cpus': 'bool', 'numa-mem-supported': 'bool', + 'deprecated': 'bool', '*default-cpu-type': 'str', + '*default-ram-id': 'str' } } + +## +# @query-machines: +# +# Return a list of supported machines +# +# Returns: a list of MachineInfo +# +# Since: 1.2 +## +{ 'command': 'query-machines', 'returns': ['MachineInfo'] } + +## +# @CurrentMachineParams: +# +# Information describing the running machine parameters. +# +# @wakeup-suspend-support: true if the machine supports wake up from +# suspend +# +# Since: 4.0 +## +{ 'struct': 'CurrentMachineParams', + 'data': { 'wakeup-suspend-support': 'bool'} } + +## +# @query-current-machine: +# +# Return information on the current virtual machine. +# +# Returns: CurrentMachineParams +# +# Since: 4.0 +## +{ 'command': 'query-current-machine', 'returns': 'CurrentMachineParams' } + +## +# @TargetInfo: +# +# Information describing the QEMU target. +# +# @arch: the target architecture +# +# Since: 1.2 +## +{ 'struct': 'TargetInfo', + 'data': { 'arch': 'SysEmuTarget' } } + +## +# @query-target: +# +# Return information about the target for this QEMU +# +# Returns: TargetInfo +# +# Since: 1.2 +## +{ 'command': 'query-target', 'returns': 'TargetInfo' } + +## +# @UuidInfo: +# +# Guest UUID information (Universally Unique Identifier). +# +# @UUID: the UUID of the guest +# +# Since: 0.14 +# +# Notes: If no UUID was specified for the guest, a null UUID is returned. +## +{ 'struct': 'UuidInfo', 'data': {'UUID': 'str'} } + +## +# @query-uuid: +# +# Query the guest UUID information. +# +# Returns: The @UuidInfo for the guest +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-uuid" } +# <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } } +# +## +{ 'command': 'query-uuid', 'returns': 'UuidInfo', 'allow-preconfig': true } + +## +# @GuidInfo: +# +# GUID information. +# +# @guid: the globally unique identifier +# +# Since: 2.9 +## +{ 'struct': 'GuidInfo', 'data': {'guid': 'str'} } + +## +# @query-vm-generation-id: +# +# Show Virtual Machine Generation ID +# +# Since: 2.9 +## +{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' } + +## +# @system_reset: +# +# Performs a hard reset of a guest. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "system_reset" } +# <- { "return": {} } +# +## +{ 'command': 'system_reset' } + +## +# @system_powerdown: +# +# Requests that a guest perform a powerdown operation. +# +# Since: 0.14 +# +# Notes: A guest may or may not respond to this command. This command +# returning does not indicate that a guest has accepted the request or +# that it has shut down. Many guests will respond to this command by +# prompting the user in some way. +# Example: +# +# -> { "execute": "system_powerdown" } +# <- { "return": {} } +# +## +{ 'command': 'system_powerdown' } + +## +# @system_wakeup: +# +# Wake up guest from suspend. If the guest has wake-up from suspend +# support enabled (wakeup-suspend-support flag from +# query-current-machine), wake-up guest from suspend if the guest is +# in SUSPENDED state. Return an error otherwise. +# +# Since: 1.1 +# +# Returns: nothing. +# +# Note: prior to 4.0, this command does nothing in case the guest +# isn't suspended. +# +# Example: +# +# -> { "execute": "system_wakeup" } +# <- { "return": {} } +# +## +{ 'command': 'system_wakeup' } + +## +# @LostTickPolicy: +# +# Policy for handling lost ticks in timer devices. Ticks end up getting +# lost when, for example, the guest is paused. +# +# @discard: throw away the missed ticks and continue with future injection +# normally. The guest OS will see the timer jump ahead by a +# potentially quite significant amount all at once, as if the +# intervening chunk of time had simply not existed; needless to +# say, such a sudden jump can easily confuse a guest OS which is +# not specifically prepared to deal with it. Assuming the guest +# OS can deal correctly with the time jump, the time in the guest +# and in the host should now match. +# +# @delay: continue to deliver ticks at the normal rate. The guest OS will +# not notice anything is amiss, as from its point of view time will +# have continued to flow normally. The time in the guest should now +# be behind the time in the host by exactly the amount of time during +# which ticks have been missed. +# +# @slew: deliver ticks at a higher rate to catch up with the missed ticks. +# The guest OS will not notice anything is amiss, as from its point +# of view time will have continued to flow normally. Once the timer +# has managed to catch up with all the missing ticks, the time in +# the guest and in the host should match. +# +# Since: 2.0 +## +{ 'enum': 'LostTickPolicy', + 'data': ['discard', 'delay', 'slew' ] } + +## +# @inject-nmi: +# +# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64). +# The command fails when the guest doesn't support injecting. +# +# Returns: If successful, nothing +# +# Since: 0.14 +# +# Note: prior to 2.1, this command was only supported for x86 and s390 VMs +# +# Example: +# +# -> { "execute": "inject-nmi" } +# <- { "return": {} } +# +## +{ 'command': 'inject-nmi' } + +## +# @KvmInfo: +# +# Information about support for KVM acceleration +# +# @enabled: true if KVM acceleration is active +# +# @present: true if KVM acceleration is built into this executable +# +# Since: 0.14 +## +{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} } + +## +# @query-kvm: +# +# Returns information about KVM acceleration +# +# Returns: @KvmInfo +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-kvm" } +# <- { "return": { "enabled": true, "present": true } } +# +## +{ 'command': 'query-kvm', 'returns': 'KvmInfo' } + +## +# @NumaOptionsType: +# +# @node: NUMA nodes configuration +# +# @dist: NUMA distance configuration (since 2.10) +# +# @cpu: property based CPU(s) to node mapping (Since: 2.10) +# +# @hmat-lb: memory latency and bandwidth information (Since: 5.0) +# +# @hmat-cache: memory side cache information (Since: 5.0) +# +# Since: 2.1 +## +{ 'enum': 'NumaOptionsType', + 'data': [ 'node', 'dist', 'cpu', 'hmat-lb', 'hmat-cache' ] } + +## +# @NumaOptions: +# +# A discriminated record of NUMA options. (for OptsVisitor) +# +# Since: 2.1 +## +{ 'union': 'NumaOptions', + 'base': { 'type': 'NumaOptionsType' }, + 'discriminator': 'type', + 'data': { + 'node': 'NumaNodeOptions', + 'dist': 'NumaDistOptions', + 'cpu': 'NumaCpuOptions', + 'hmat-lb': 'NumaHmatLBOptions', + 'hmat-cache': 'NumaHmatCacheOptions' }} + +## +# @NumaNodeOptions: +# +# Create a guest NUMA node. (for OptsVisitor) +# +# @nodeid: NUMA node ID (increase by 1 from 0 if omitted) +# +# @cpus: VCPUs belonging to this node (assign VCPUS round-robin +# if omitted) +# +# @mem: memory size of this node; mutually exclusive with @memdev. +# Equally divide total memory among nodes if both @mem and @memdev are +# omitted. +# +# @memdev: memory backend object. If specified for one node, +# it must be specified for all nodes. +# +# @initiator: defined in ACPI 6.3 Chapter 5.2.27.3 Table 5-145, +# points to the nodeid which has the memory controller +# responsible for this NUMA node. This field provides +# additional information as to the initiator node that +# is closest (as in directly attached) to this node, and +# therefore has the best performance (since 5.0) +# +# Since: 2.1 +## +{ 'struct': 'NumaNodeOptions', + 'data': { + '*nodeid': 'uint16', + '*cpus': ['uint16'], + '*mem': 'size', + '*memdev': 'str', + '*initiator': 'uint16' }} + +## +# @NumaDistOptions: +# +# Set the distance between 2 NUMA nodes. +# +# @src: source NUMA node. +# +# @dst: destination NUMA node. +# +# @val: NUMA distance from source node to destination node. +# When a node is unreachable from another node, set the distance +# between them to 255. +# +# Since: 2.10 +## +{ 'struct': 'NumaDistOptions', + 'data': { + 'src': 'uint16', + 'dst': 'uint16', + 'val': 'uint8' }} + +## +# @X86CPURegister32: +# +# A X86 32-bit register +# +# Since: 1.5 +## +{ 'enum': 'X86CPURegister32', + 'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] } + +## +# @X86CPUFeatureWordInfo: +# +# Information about a X86 CPU feature word +# +# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word +# +# @cpuid-input-ecx: Input ECX value for CPUID instruction for that +# feature word +# +# @cpuid-register: Output register containing the feature bits +# +# @features: value of output register, containing the feature bits +# +# Since: 1.5 +## +{ 'struct': 'X86CPUFeatureWordInfo', + 'data': { 'cpuid-input-eax': 'int', + '*cpuid-input-ecx': 'int', + 'cpuid-register': 'X86CPURegister32', + 'features': 'int' } } + +## +# @DummyForceArrays: +# +# Not used by QMP; hack to let us use X86CPUFeatureWordInfoList internally +# +# Since: 2.5 +## +{ 'struct': 'DummyForceArrays', + 'data': { 'unused': ['X86CPUFeatureWordInfo'] } } + +## +# @NumaCpuOptions: +# +# Option "-numa cpu" overrides default cpu to node mapping. +# It accepts the same set of cpu properties as returned by +# query-hotpluggable-cpus[].props, where node-id could be used to +# override default node mapping. +# +# Since: 2.10 +## +{ 'struct': 'NumaCpuOptions', + 'base': 'CpuInstanceProperties', + 'data' : {} } + +## +# @HmatLBMemoryHierarchy: +# +# The memory hierarchy in the System Locality Latency and Bandwidth +# Information Structure of HMAT (Heterogeneous Memory Attribute Table) +# +# For more information about @HmatLBMemoryHierarchy, see chapter +# 5.2.27.4: Table 5-146: Field "Flags" of ACPI 6.3 spec. +# +# @memory: the structure represents the memory performance +# +# @first-level: first level of memory side cache +# +# @second-level: second level of memory side cache +# +# @third-level: third level of memory side cache +# +# Since: 5.0 +## +{ 'enum': 'HmatLBMemoryHierarchy', + 'data': [ 'memory', 'first-level', 'second-level', 'third-level' ] } + +## +# @HmatLBDataType: +# +# Data type in the System Locality Latency and Bandwidth +# Information Structure of HMAT (Heterogeneous Memory Attribute Table) +# +# For more information about @HmatLBDataType, see chapter +# 5.2.27.4: Table 5-146: Field "Data Type" of ACPI 6.3 spec. +# +# @access-latency: access latency (nanoseconds) +# +# @read-latency: read latency (nanoseconds) +# +# @write-latency: write latency (nanoseconds) +# +# @access-bandwidth: access bandwidth (Bytes per second) +# +# @read-bandwidth: read bandwidth (Bytes per second) +# +# @write-bandwidth: write bandwidth (Bytes per second) +# +# Since: 5.0 +## +{ 'enum': 'HmatLBDataType', + 'data': [ 'access-latency', 'read-latency', 'write-latency', + 'access-bandwidth', 'read-bandwidth', 'write-bandwidth' ] } + +## +# @NumaHmatLBOptions: +# +# Set the system locality latency and bandwidth information +# between Initiator and Target proximity Domains. +# +# For more information about @NumaHmatLBOptions, see chapter +# 5.2.27.4: Table 5-146 of ACPI 6.3 spec. +# +# @initiator: the Initiator Proximity Domain. +# +# @target: the Target Proximity Domain. +# +# @hierarchy: the Memory Hierarchy. Indicates the performance +# of memory or side cache. +# +# @data-type: presents the type of data, access/read/write +# latency or hit latency. +# +# @latency: the value of latency from @initiator to @target +# proximity domain, the latency unit is "ns(nanosecond)". +# +# @bandwidth: the value of bandwidth between @initiator and @target +# proximity domain, the bandwidth unit is +# "Bytes per second". +# +# Since: 5.0 +## +{ 'struct': 'NumaHmatLBOptions', + 'data': { + 'initiator': 'uint16', + 'target': 'uint16', + 'hierarchy': 'HmatLBMemoryHierarchy', + 'data-type': 'HmatLBDataType', + '*latency': 'uint64', + '*bandwidth': 'size' }} + +## +# @HmatCacheAssociativity: +# +# Cache associativity in the Memory Side Cache Information Structure +# of HMAT +# +# For more information of @HmatCacheAssociativity, see chapter +# 5.2.27.5: Table 5-147 of ACPI 6.3 spec. +# +# @none: None (no memory side cache in this proximity domain, +# or cache associativity unknown) +# +# @direct: Direct Mapped +# +# @complex: Complex Cache Indexing (implementation specific) +# +# Since: 5.0 +## +{ 'enum': 'HmatCacheAssociativity', + 'data': [ 'none', 'direct', 'complex' ] } + +## +# @HmatCacheWritePolicy: +# +# Cache write policy in the Memory Side Cache Information Structure +# of HMAT +# +# For more information of @HmatCacheWritePolicy, see chapter +# 5.2.27.5: Table 5-147: Field "Cache Attributes" of ACPI 6.3 spec. +# +# @none: None (no memory side cache in this proximity domain, +# or cache write policy unknown) +# +# @write-back: Write Back (WB) +# +# @write-through: Write Through (WT) +# +# Since: 5.0 +## +{ 'enum': 'HmatCacheWritePolicy', + 'data': [ 'none', 'write-back', 'write-through' ] } + +## +# @NumaHmatCacheOptions: +# +# Set the memory side cache information for a given memory domain. +# +# For more information of @NumaHmatCacheOptions, see chapter +# 5.2.27.5: Table 5-147: Field "Cache Attributes" of ACPI 6.3 spec. +# +# @node-id: the memory proximity domain to which the memory belongs. +# +# @size: the size of memory side cache in bytes. +# +# @level: the cache level described in this structure. +# +# @associativity: the cache associativity, +# none/direct-mapped/complex(complex cache indexing). +# +# @policy: the write policy, none/write-back/write-through. +# +# @line: the cache Line size in bytes. +# +# Since: 5.0 +## +{ 'struct': 'NumaHmatCacheOptions', + 'data': { + 'node-id': 'uint32', + 'size': 'size', + 'level': 'uint8', + 'associativity': 'HmatCacheAssociativity', + 'policy': 'HmatCacheWritePolicy', + 'line': 'uint16' }} + +## +# @memsave: +# +# Save a portion of guest memory to a file. +# +# @val: the virtual address of the guest to start from +# +# @size: the size of memory region to save +# +# @filename: the file to save the memory to as binary data +# +# @cpu-index: the index of the virtual CPU to use for translating the +# virtual address (defaults to CPU 0) +# +# Returns: Nothing on success +# +# Since: 0.14 +# +# Notes: Errors were not reliably returned until 1.1 +# +# Example: +# +# -> { "execute": "memsave", +# "arguments": { "val": 10, +# "size": 100, +# "filename": "/tmp/virtual-mem-dump" } } +# <- { "return": {} } +# +## +{ 'command': 'memsave', + 'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} } + +## +# @pmemsave: +# +# Save a portion of guest physical memory to a file. +# +# @val: the physical address of the guest to start from +# +# @size: the size of memory region to save +# +# @filename: the file to save the memory to as binary data +# +# Returns: Nothing on success +# +# Since: 0.14 +# +# Notes: Errors were not reliably returned until 1.1 +# +# Example: +# +# -> { "execute": "pmemsave", +# "arguments": { "val": 10, +# "size": 100, +# "filename": "/tmp/physical-mem-dump" } } +# <- { "return": {} } +# +## +{ 'command': 'pmemsave', + 'data': {'val': 'int', 'size': 'int', 'filename': 'str'} } + +## +# @Memdev: +# +# Information about memory backend +# +# @id: backend's ID if backend has 'id' property (since 2.9) +# +# @size: memory backend size +# +# @merge: whether memory merge support is enabled +# +# @dump: whether memory backend's memory is included in a core dump +# +# @prealloc: whether memory was preallocated +# +# @share: whether memory is private to QEMU or shared (since 6.1) +# +# @reserve: whether swap space (or huge pages) was reserved if applicable. +# This corresponds to the user configuration and not the actual +# behavior implemented in the OS to perform the reservation. +# For example, Linux will never reserve swap space for shared +# file mappings. (since 6.1) +# +# @host-nodes: host nodes for its memory policy +# +# @policy: memory policy of memory backend +# +# Since: 2.1 +## +{ 'struct': 'Memdev', + 'data': { + '*id': 'str', + 'size': 'size', + 'merge': 'bool', + 'dump': 'bool', + 'prealloc': 'bool', + 'share': 'bool', + '*reserve': 'bool', + 'host-nodes': ['uint16'], + 'policy': 'HostMemPolicy' }} + +## +# @query-memdev: +# +# Returns information for all memory backends. +# +# Returns: a list of @Memdev. +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "query-memdev" } +# <- { "return": [ +# { +# "id": "mem1", +# "size": 536870912, +# "merge": false, +# "dump": true, +# "prealloc": false, +# "host-nodes": [0, 1], +# "policy": "bind" +# }, +# { +# "size": 536870912, +# "merge": false, +# "dump": true, +# "prealloc": true, +# "host-nodes": [2, 3], +# "policy": "preferred" +# } +# ] +# } +# +## +{ 'command': 'query-memdev', 'returns': ['Memdev'], 'allow-preconfig': true } + +## +# @CpuInstanceProperties: +# +# List of properties to be used for hotplugging a CPU instance, +# it should be passed by management with device_add command when +# a CPU is being hotplugged. +# +# @node-id: NUMA node ID the CPU belongs to +# @socket-id: socket number within node/board the CPU belongs to +# @die-id: die number within node/board the CPU belongs to (Since 4.1) +# @core-id: core number within die the CPU belongs to +# @thread-id: thread number within core the CPU belongs to +# +# Note: currently there are 5 properties that could be present +# but management should be prepared to pass through other +# properties with device_add command to allow for future +# interface extension. This also requires the filed names to be kept in +# sync with the properties passed to -device/device_add. +# +# Since: 2.7 +## +{ 'struct': 'CpuInstanceProperties', + 'data': { '*node-id': 'int', + '*socket-id': 'int', + '*die-id': 'int', + '*core-id': 'int', + '*thread-id': 'int' + } +} + +## +# @HotpluggableCPU: +# +# @type: CPU object type for usage with device_add command +# @props: list of properties to be used for hotplugging CPU +# @vcpus-count: number of logical VCPU threads @HotpluggableCPU provides +# @qom-path: link to existing CPU object if CPU is present or +# omitted if CPU is not present. +# +# Since: 2.7 +## +{ 'struct': 'HotpluggableCPU', + 'data': { 'type': 'str', + 'vcpus-count': 'int', + 'props': 'CpuInstanceProperties', + '*qom-path': 'str' + } +} + +## +# @query-hotpluggable-cpus: +# +# TODO: Better documentation; currently there is none. +# +# Returns: a list of HotpluggableCPU objects. +# +# Since: 2.7 +# +# Example: +# +# For pseries machine type started with -smp 2,cores=2,maxcpus=4 -cpu POWER8: +# +# -> { "execute": "query-hotpluggable-cpus" } +# <- {"return": [ +# { "props": { "core": 8 }, "type": "POWER8-spapr-cpu-core", +# "vcpus-count": 1 }, +# { "props": { "core": 0 }, "type": "POWER8-spapr-cpu-core", +# "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"} +# ]}' +# +# For pc machine type started with -smp 1,maxcpus=2: +# +# -> { "execute": "query-hotpluggable-cpus" } +# <- {"return": [ +# { +# "type": "qemu64-x86_64-cpu", "vcpus-count": 1, +# "props": {"core-id": 0, "socket-id": 1, "thread-id": 0} +# }, +# { +# "qom-path": "/machine/unattached/device[0]", +# "type": "qemu64-x86_64-cpu", "vcpus-count": 1, +# "props": {"core-id": 0, "socket-id": 0, "thread-id": 0} +# } +# ]} +# +# For s390x-virtio-ccw machine type started with -smp 1,maxcpus=2 -cpu qemu +# (Since: 2.11): +# +# -> { "execute": "query-hotpluggable-cpus" } +# <- {"return": [ +# { +# "type": "qemu-s390x-cpu", "vcpus-count": 1, +# "props": { "core-id": 1 } +# }, +# { +# "qom-path": "/machine/unattached/device[0]", +# "type": "qemu-s390x-cpu", "vcpus-count": 1, +# "props": { "core-id": 0 } +# } +# ]} +# +## +{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'], + 'allow-preconfig': true } + +## +# @set-numa-node: +# +# Runtime equivalent of '-numa' CLI option, available at +# preconfigure stage to configure numa mapping before initializing +# machine. +# +# Since 3.0 +## +{ 'command': 'set-numa-node', 'boxed': true, + 'data': 'NumaOptions', + 'allow-preconfig': true +} + +## +# @balloon: +# +# Request the balloon driver to change its balloon size. +# +# @value: the target logical size of the VM in bytes. +# We can deduce the size of the balloon using this formula: +# +# logical_vm_size = vm_ram_size - balloon_size +# +# From it we have: balloon_size = vm_ram_size - @value +# +# Returns: - Nothing on success +# - If the balloon driver is enabled but not functional because the KVM +# kernel module cannot support it, KvmMissingCap +# - If no balloon device is present, DeviceNotActive +# +# Notes: This command just issues a request to the guest. When it returns, +# the balloon size may not have changed. A guest can change the balloon +# size independent of this command. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "balloon", "arguments": { "value": 536870912 } } +# <- { "return": {} } +# +# With a 2.5GiB guest this command inflated the ballon to 3GiB. +# +## +{ 'command': 'balloon', 'data': {'value': 'int'} } + +## +# @BalloonInfo: +# +# Information about the guest balloon device. +# +# @actual: the logical size of the VM in bytes +# Formula used: logical_vm_size = vm_ram_size - balloon_size +# +# Since: 0.14 +# +## +{ 'struct': 'BalloonInfo', 'data': {'actual': 'int' } } + +## +# @query-balloon: +# +# Return information about the balloon device. +# +# Returns: - @BalloonInfo on success +# - If the balloon driver is enabled but not functional because the KVM +# kernel module cannot support it, KvmMissingCap +# - If no balloon device is present, DeviceNotActive +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-balloon" } +# <- { "return": { +# "actual": 1073741824, +# } +# } +# +## +{ 'command': 'query-balloon', 'returns': 'BalloonInfo' } + +## +# @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 +# +# @actual: the logical size of the VM in bytes +# Formula used: logical_vm_size = vm_ram_size - balloon_size +# +# Note: this event is rate-limited. +# +# Since: 1.2 +# +# Example: +# +# <- { "event": "BALLOON_CHANGE", +# "data": { "actual": 944766976 }, +# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +# +## +{ 'event': 'BALLOON_CHANGE', + 'data': { 'actual': 'int' } } + +## +# @MemoryInfo: +# +# Actual memory information in bytes. +# +# @base-memory: size of "base" memory specified with command line +# option -m. +# +# @plugged-memory: size of memory that can be hot-unplugged. This field +# is omitted if target doesn't support memory hotplug +# (i.e. CONFIG_MEM_DEVICE not defined at build time). +# +# Since: 2.11 +## +{ 'struct': 'MemoryInfo', + 'data' : { 'base-memory': 'size', '*plugged-memory': 'size' } } + +## +# @query-memory-size-summary: +# +# Return the amount of initially allocated and present hotpluggable (if +# enabled) memory in bytes. +# +# Example: +# +# -> { "execute": "query-memory-size-summary" } +# <- { "return": { "base-memory": 4294967296, "plugged-memory": 0 } } +# +# Since: 2.11 +## +{ 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' } + +## +# @PCDIMMDeviceInfo: +# +# PCDIMMDevice state information +# +# @id: device's ID +# +# @addr: physical address, where device is mapped +# +# @size: size of memory that the device provides +# +# @slot: slot number at which device is plugged in +# +# @node: NUMA node number where device is plugged in +# +# @memdev: memory backend linked with device +# +# @hotplugged: true if device was hotplugged +# +# @hotpluggable: true if device if could be added/removed while machine is running +# +# Since: 2.1 +## +{ 'struct': 'PCDIMMDeviceInfo', + 'data': { '*id': 'str', + 'addr': 'int', + 'size': 'int', + 'slot': 'int', + 'node': 'int', + 'memdev': 'str', + 'hotplugged': 'bool', + 'hotpluggable': 'bool' + } +} + +## +# @VirtioPMEMDeviceInfo: +# +# VirtioPMEM state information +# +# @id: device's ID +# +# @memaddr: physical address in memory, where device is mapped +# +# @size: size of memory that the device provides +# +# @memdev: memory backend linked with device +# +# Since: 4.1 +## +{ 'struct': 'VirtioPMEMDeviceInfo', + 'data': { '*id': 'str', + 'memaddr': 'size', + 'size': 'size', + 'memdev': 'str' + } +} + +## +# @VirtioMEMDeviceInfo: +# +# VirtioMEMDevice state information +# +# @id: device's ID +# +# @memaddr: physical address in memory, where device is mapped +# +# @requested-size: the user requested size of the device +# +# @size: the (current) size of memory that the device provides +# +# @max-size: the maximum size of memory that the device can provide +# +# @block-size: the block size of memory that the device provides +# +# @node: NUMA node number where device is assigned to +# +# @memdev: memory backend linked with the region +# +# Since: 5.1 +## +{ 'struct': 'VirtioMEMDeviceInfo', + 'data': { '*id': 'str', + 'memaddr': 'size', + 'requested-size': 'size', + 'size': 'size', + 'max-size': 'size', + 'block-size': 'size', + 'node': 'int', + 'memdev': 'str' + } +} + +## +# @SgxEPCDeviceInfo: +# +# Sgx EPC state information +# +# @id: device's ID +# +# @memaddr: physical address in memory, where device is mapped +# +# @size: size of memory that the device provides +# +# @memdev: memory backend linked with device +# +# Since: 6.2 +## +{ 'struct': 'SgxEPCDeviceInfo', + 'data': { '*id': 'str', + 'memaddr': 'size', + 'size': 'size', + 'memdev': 'str' + } +} + +## +# @MemoryDeviceInfoKind: +# +# Since: 2.1 +## +{ 'enum': 'MemoryDeviceInfoKind', + 'data': [ 'dimm', 'nvdimm', 'virtio-pmem', 'virtio-mem', 'sgx-epc' ] } + +## +# @PCDIMMDeviceInfoWrapper: +# +# Since: 2.1 +## +{ 'struct': 'PCDIMMDeviceInfoWrapper', + 'data': { 'data': 'PCDIMMDeviceInfo' } } + +## +# @VirtioPMEMDeviceInfoWrapper: +# +# Since: 2.1 +## +{ 'struct': 'VirtioPMEMDeviceInfoWrapper', + 'data': { 'data': 'VirtioPMEMDeviceInfo' } } + +## +# @VirtioMEMDeviceInfoWrapper: +# +# Since: 2.1 +## +{ 'struct': 'VirtioMEMDeviceInfoWrapper', + 'data': { 'data': 'VirtioMEMDeviceInfo' } } + +## +# @SgxEPCDeviceInfoWrapper: +# +# Since: 6.2 +## +{ 'struct': 'SgxEPCDeviceInfoWrapper', + 'data': { 'data': 'SgxEPCDeviceInfo' } } + +## +# @MemoryDeviceInfo: +# +# Union containing information about a memory device +# +# nvdimm is included since 2.12. virtio-pmem is included since 4.1. +# virtio-mem is included since 5.1. sgx-epc is included since 6.2. +# +# Since: 2.1 +## +{ 'union': 'MemoryDeviceInfo', + 'base': { 'type': 'MemoryDeviceInfoKind' }, + 'discriminator': 'type', + 'data': { 'dimm': 'PCDIMMDeviceInfoWrapper', + 'nvdimm': 'PCDIMMDeviceInfoWrapper', + 'virtio-pmem': 'VirtioPMEMDeviceInfoWrapper', + 'virtio-mem': 'VirtioMEMDeviceInfoWrapper', + 'sgx-epc': 'SgxEPCDeviceInfoWrapper' + } +} + +## +# @SgxEPC: +# +# Sgx EPC cmdline information +# +# @memdev: memory backend linked with device +# +# Since: 6.2 +## +{ 'struct': 'SgxEPC', + 'data': { 'memdev': 'str' } } + +## +# @SgxEPCProperties: +# +# SGX properties of machine types. +# +# @sgx-epc: list of ids of memory-backend-epc objects. +# +# Since: 6.2 +## +{ 'struct': 'SgxEPCProperties', + 'data': { 'sgx-epc': ['SgxEPC'] } +} + +## +# @query-memory-devices: +# +# Lists available memory devices and their state +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "query-memory-devices" } +# <- { "return": [ { "data": +# { "addr": 5368709120, +# "hotpluggable": true, +# "hotplugged": true, +# "id": "d1", +# "memdev": "/objects/memX", +# "node": 0, +# "size": 1073741824, +# "slot": 0}, +# "type": "dimm" +# } ] } +# +## +{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] } + +## +# @MEMORY_DEVICE_SIZE_CHANGE: +# +# Emitted when the size of a memory device changes. Only emitted for memory +# devices that can actually change the size (e.g., virtio-mem due to guest +# action). +# +# @id: device's ID +# +# @size: the new size of memory that the device provides +# +# @qom-path: path to the device object in the QOM tree (since 6.2) +# +# Note: this event is rate-limited. +# +# Since: 5.1 +# +# Example: +# +# <- { "event": "MEMORY_DEVICE_SIZE_CHANGE", +# "data": { "id": "vm0", "size": 1073741824}, +# "timestamp": { "seconds": 1588168529, "microseconds": 201316 } } +# +## +{ 'event': 'MEMORY_DEVICE_SIZE_CHANGE', + 'data': { '*id': 'str', 'size': 'size', 'qom-path' : 'str'} } + + +## +# @MEM_UNPLUG_ERROR: +# +# Emitted when memory hot unplug error occurs. +# +# @device: device name +# +# @msg: Informative message +# +# Features: +# @deprecated: This event is deprecated. Use @DEVICE_UNPLUG_GUEST_ERROR +# instead. +# +# Since: 2.4 +# +# Example: +# +# <- { "event": "MEM_UNPLUG_ERROR" +# "data": { "device": "dimm1", +# "msg": "acpi: device unplug for unsupported device" +# }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'MEM_UNPLUG_ERROR', + 'data': { 'device': 'str', 'msg': 'str' }, + 'features': ['deprecated'] } + +## +# @SMPConfiguration: +# +# Schema for CPU topology configuration. A missing value lets +# QEMU figure out a suitable value based on the ones that are provided. +# +# @cpus: number of virtual CPUs in the virtual machine +# +# @sockets: number of sockets in the CPU topology +# +# @dies: number of dies per socket in the CPU topology +# +# @cores: number of cores per die in the CPU topology +# +# @threads: number of threads per core in the CPU topology +# +# @maxcpus: maximum number of hotpluggable virtual CPUs in the virtual machine +# +# Since: 6.1 +## +{ 'struct': 'SMPConfiguration', 'data': { + '*cpus': 'int', + '*sockets': 'int', + '*dies': 'int', + '*cores': 'int', + '*threads': 'int', + '*maxcpus': 'int' } } + +## +# @x-query-irq: +# +# Query interrupt statistics +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: interrupt statistics +# +# Since: 6.2 +## +{ 'command': 'x-query-irq', + 'returns': 'HumanReadableText', + 'features': [ 'unstable' ] } + +## +# @x-query-jit: +# +# Query TCG compiler statistics +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: TCG compiler statistics +# +# Since: 6.2 +## +{ 'command': 'x-query-jit', + 'returns': 'HumanReadableText', + 'if': 'CONFIG_TCG', + 'features': [ 'unstable' ] } + +## +# @x-query-numa: +# +# Query NUMA topology information +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: topology information +# +# Since: 6.2 +## +{ 'command': 'x-query-numa', + 'returns': 'HumanReadableText', + 'features': [ 'unstable' ] } + +## +# @x-query-opcount: +# +# Query TCG opcode counters +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: TCG opcode counters +# +# Since: 6.2 +## +{ 'command': 'x-query-opcount', + 'returns': 'HumanReadableText', + 'if': 'CONFIG_TCG', + 'features': [ 'unstable' ] } + +## +# @x-query-profile: +# +# Query TCG profiling information +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: profile information +# +# Since: 6.2 +## +{ 'command': 'x-query-profile', + 'returns': 'HumanReadableText', + 'features': [ 'unstable' ] } + +## +# @x-query-ramblock: +# +# Query system ramblock information +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: system ramblock information +# +# Since: 6.2 +## +{ 'command': 'x-query-ramblock', + 'returns': 'HumanReadableText', + 'features': [ 'unstable' ] } + +## +# @x-query-rdma: +# +# Query RDMA state +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: RDMA state +# +# Since: 6.2 +## +{ 'command': 'x-query-rdma', + 'returns': 'HumanReadableText', + 'features': [ 'unstable' ] } + +## +# @x-query-roms: +# +# Query information on the registered ROMS +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: registered ROMs +# +# Since: 6.2 +## +{ 'command': 'x-query-roms', + 'returns': 'HumanReadableText', + 'features': [ 'unstable' ] } + +## +# @x-query-usb: +# +# Query information on the USB devices +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: USB device information +# +# Since: 6.2 +## +{ 'command': 'x-query-usb', + 'returns': 'HumanReadableText', + 'features': [ 'unstable' ] } diff --git a/qapi/meson.build b/qapi/meson.build new file mode 100644 index 000000000..c0c49c15e --- /dev/null +++ b/qapi/meson.build @@ -0,0 +1,150 @@ +util_ss.add(files( + 'opts-visitor.c', + 'qapi-clone-visitor.c', + 'qapi-dealloc-visitor.c', + 'qapi-forward-visitor.c', + 'qapi-util.c', + 'qapi-visit-core.c', + 'qobject-input-visitor.c', + 'qobject-output-visitor.c', + 'string-input-visitor.c', + 'string-output-visitor.c', +)) +if have_system + util_ss.add(files('qapi-type-helpers.c')) +endif +if have_system or have_tools + util_ss.add(files( + 'qmp-dispatch.c', + 'qmp-event.c', + 'qmp-registry.c', + )) +endif + +qapi_all_modules = [ + 'authz', + 'block', + 'block-core', + 'block-export', + 'char', + 'common', + 'compat', + 'control', + 'crypto', + 'dump', + 'error', + 'introspect', + 'job', + 'machine', + 'machine-target', + 'migration', + 'misc', + 'misc-target', + 'net', + 'pragma', + 'qom', + 'replay', + 'run-state', + 'sockets', + 'trace', + 'transaction', + 'yank', +] +if have_system + qapi_all_modules += [ + 'acpi', + 'audio', + 'qdev', + 'pci', + 'rdma', + 'rocker', + 'tpm', + ] +endif +if have_system or have_tools + qapi_all_modules += [ + 'ui', + ] +endif + +qapi_storage_daemon_modules = [ + 'block-core', + 'block-export', + 'char', + 'common', + 'control', + 'crypto', + 'introspect', + 'job', + 'qom', + 'sockets', + 'pragma', + 'transaction', +] + +qapi_nonmodule_outputs = [ + 'qapi-introspect.c', 'qapi-introspect.h', + 'qapi-types.c', 'qapi-types.h', + 'qapi-visit.h', 'qapi-visit.c', + 'qapi-commands.h', 'qapi-commands.c', + 'qapi-init-commands.h', 'qapi-init-commands.c', + 'qapi-events.h', 'qapi-events.c', + 'qapi-emit-events.c', 'qapi-emit-events.h', +] + +# First build all sources +qapi_util_outputs = [ + 'qapi-builtin-types.c', 'qapi-builtin-visit.c', + 'qapi-builtin-types.h', 'qapi-builtin-visit.h', +] + +qapi_inputs = [] +qapi_specific_outputs = [] +foreach module : qapi_all_modules + qapi_inputs += [ files(module + '.json') ] + qapi_module_outputs = [ + 'qapi-types-@0@.c'.format(module), + 'qapi-types-@0@.h'.format(module), + 'qapi-visit-@0@.c'.format(module), + 'qapi-visit-@0@.h'.format(module), + ] + if have_system or have_tools + qapi_module_outputs += [ + 'qapi-events-@0@.c'.format(module), + 'qapi-events-@0@.h'.format(module), + 'qapi-commands-@0@.c'.format(module), + 'qapi-commands-@0@.h'.format(module), + ] + endif + if module.endswith('-target') + qapi_specific_outputs += qapi_module_outputs + else + qapi_util_outputs += qapi_module_outputs + endif +endforeach + +qapi_files = custom_target('shared QAPI source files', + output: qapi_util_outputs + qapi_specific_outputs + qapi_nonmodule_outputs, + input: [ files('qapi-schema.json') ], + command: [ qapi_gen, '-o', 'qapi', '-b', '@INPUT0@' ], + depend_files: [ qapi_inputs, qapi_gen_depends ]) + +# Now go through all the outputs and add them to the right sourceset. +# These loops must be synchronized with the output of the above custom target. + +i = 0 +foreach output : qapi_util_outputs + if output.endswith('.h') + genh += qapi_files[i] + endif + util_ss.add(qapi_files[i]) + i = i + 1 +endforeach + +foreach output : qapi_specific_outputs + qapi_nonmodule_outputs + if output.endswith('.h') + genh += qapi_files[i] + endif + specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: qapi_files[i]) + i = i + 1 +endforeach diff --git a/qapi/migration.json b/qapi/migration.json new file mode 100644 index 000000000..bbfd48cf0 --- /dev/null +++ b/qapi/migration.json @@ -0,0 +1,2023 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Migration +## + +{ 'include': 'common.json' } +{ 'include': 'sockets.json' } + +## +# @MigrationStats: +# +# Detailed migration status. +# +# @transferred: amount of bytes already transferred to the target VM +# +# @remaining: amount of bytes remaining to be transferred to the target VM +# +# @total: total amount of bytes involved in the migration process +# +# @duplicate: number of duplicate (zero) pages (since 1.2) +# +# @skipped: number of skipped zero pages (since 1.5) +# +# @normal: number of normal pages (since 1.2) +# +# @normal-bytes: number of normal bytes sent (since 1.2) +# +# @dirty-pages-rate: number of pages dirtied by second by the +# guest (since 1.3) +# +# @mbps: throughput in megabits/sec. (since 1.6) +# +# @dirty-sync-count: number of times that dirty ram was synchronized (since 2.1) +# +# @postcopy-requests: The number of page requests received from the destination +# (since 2.7) +# +# @page-size: The number of bytes per page for the various page-based +# statistics (since 2.10) +# +# @multifd-bytes: The number of bytes sent through multifd (since 3.0) +# +# @pages-per-second: the number of memory pages transferred per second +# (Since 4.0) +# +# Since: 0.14 +## +{ 'struct': 'MigrationStats', + 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' , + 'duplicate': 'int', 'skipped': 'int', 'normal': 'int', + 'normal-bytes': 'int', 'dirty-pages-rate' : 'int', + 'mbps' : 'number', 'dirty-sync-count' : 'int', + 'postcopy-requests' : 'int', 'page-size' : 'int', + 'multifd-bytes' : 'uint64', 'pages-per-second' : 'uint64' } } + +## +# @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 +# +# @cache-miss-rate: rate of cache miss (since 2.1) +# +# @encoding-rate: rate of encoded bytes (since 5.1) +# +# @overflow: number of overflows +# +# Since: 1.2 +## +{ 'struct': 'XBZRLECacheStats', + 'data': {'cache-size': 'size', 'bytes': 'int', 'pages': 'int', + 'cache-miss': 'int', 'cache-miss-rate': 'number', + 'encoding-rate': 'number', 'overflow': 'int' } } + +## +# @CompressionStats: +# +# Detailed migration compression statistics +# +# @pages: amount of pages compressed and transferred to the target VM +# +# @busy: count of times that no free thread was available to compress data +# +# @busy-rate: rate of thread busy +# +# @compressed-size: amount of bytes after compression +# +# @compression-rate: rate of compressed size +# +# Since: 3.1 +## +{ 'struct': 'CompressionStats', + 'data': {'pages': 'int', 'busy': 'int', 'busy-rate': 'number', + 'compressed-size': 'int', 'compression-rate': 'number' } } + +## +# @MigrationStatus: +# +# An enumeration of migration status. +# +# @none: no migration has ever happened. +# +# @setup: migration process has been initiated. +# +# @cancelling: in the process of cancelling migration. +# +# @cancelled: cancelling migration is finished. +# +# @active: in the process of doing migration. +# +# @postcopy-active: like active, but now in postcopy mode. (since 2.5) +# +# @postcopy-paused: during postcopy but paused. (since 3.0) +# +# @postcopy-recover: trying to recover from a paused postcopy. (since 3.0) +# +# @completed: migration is finished. +# +# @failed: some error occurred during migration process. +# +# @colo: VM is in the process of fault tolerance, VM can not get into this +# state unless colo capability is enabled for migration. (since 2.8) +# +# @pre-switchover: Paused before device serialisation. (since 2.11) +# +# @device: During device serialisation when pause-before-switchover is enabled +# (since 2.11) +# +# @wait-unplug: wait for device unplug request by guest OS to be completed. +# (since 4.2) +# +# Since: 2.3 +# +## +{ 'enum': 'MigrationStatus', + 'data': [ 'none', 'setup', 'cancelling', 'cancelled', + 'active', 'postcopy-active', 'postcopy-paused', + 'postcopy-recover', 'completed', 'failed', 'colo', + 'pre-switchover', 'device', 'wait-unplug' ] } +## +# @VfioStats: +# +# Detailed VFIO devices migration statistics +# +# @transferred: amount of bytes transferred to the target VM by VFIO devices +# +# Since: 5.2 +# +## +{ 'struct': 'VfioStats', + 'data': {'transferred': 'int' } } + +## +# @MigrationInfo: +# +# Information about current migration process. +# +# @status: @MigrationStatus describing the current migration status. +# If this field is not returned, no migration process +# has been initiated +# +# @ram: @MigrationStats containing detailed migration +# status, only returned if status is 'active' or +# 'completed'(since 1.2) +# +# @disk: @MigrationStats containing detailed disk migration +# status, only returned if status is 'active' and it is a block +# migration +# +# @xbzrle-cache: @XBZRLECacheStats containing detailed XBZRLE +# migration statistics, only returned if XBZRLE feature is on and +# status is 'active' or 'completed' (since 1.2) +# +# @total-time: total amount of milliseconds since migration started. +# If migration has ended, it returns the total migration +# time. (since 1.2) +# +# @downtime: only present when migration finishes correctly +# total downtime in milliseconds for the guest. +# (since 1.3) +# +# @expected-downtime: only present while migration is active +# expected downtime in milliseconds for the guest in last walk +# of the dirty bitmap. (since 1.3) +# +# @setup-time: amount of setup time in milliseconds *before* the +# iterations begin but *after* the QMP command is issued. This is designed +# to provide an accounting of any activities (such as RDMA pinning) which +# may be expensive, but do not actually occur during the iterative +# migration rounds themselves. (since 1.6) +# +# @cpu-throttle-percentage: percentage of time guest cpus are being +# throttled during auto-converge. This is only present when auto-converge +# has started throttling guest cpus. (Since 2.7) +# +# @error-desc: the human readable error description string, when +# @status is 'failed'. Clients should not attempt to parse the +# error strings. (Since 2.7) +# +# @postcopy-blocktime: total time when all vCPU were blocked during postcopy +# live migration. This is only present when the postcopy-blocktime +# migration capability is enabled. (Since 3.0) +# +# @postcopy-vcpu-blocktime: list of the postcopy blocktime per vCPU. This is +# only present when the postcopy-blocktime migration capability +# is enabled. (Since 3.0) +# +# @compression: migration compression statistics, only returned if compression +# feature is on and status is 'active' or 'completed' (Since 3.1) +# +# @socket-address: Only used for tcp, to know what the real port is (Since 4.0) +# +# @vfio: @VfioStats containing detailed VFIO devices migration statistics, +# only returned if VFIO device is present, migration is supported by all +# VFIO devices and status is 'active' or 'completed' (since 5.2) +# +# @blocked-reasons: A list of reasons an outgoing migration is blocked. +# Present and non-empty when migration is blocked. +# (since 6.0) +# +# Since: 0.14 +## +{ 'struct': 'MigrationInfo', + 'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats', + '*disk': 'MigrationStats', + '*vfio': 'VfioStats', + '*xbzrle-cache': 'XBZRLECacheStats', + '*total-time': 'int', + '*expected-downtime': 'int', + '*downtime': 'int', + '*setup-time': 'int', + '*cpu-throttle-percentage': 'int', + '*error-desc': 'str', + '*blocked-reasons': ['str'], + '*postcopy-blocktime' : 'uint32', + '*postcopy-vcpu-blocktime': ['uint32'], + '*compression': 'CompressionStats', + '*socket-address': ['SocketAddress'] } } + +## +# @query-migrate: +# +# Returns information about current migration process. If migration +# is active there will be another json-object with RAM migration +# status and if block migration is active another one with block +# migration status. +# +# Returns: @MigrationInfo +# +# Since: 0.14 +# +# Example: +# +# 1. Before the first migration +# +# -> { "execute": "query-migrate" } +# <- { "return": {} } +# +# 2. Migration is done and has succeeded +# +# -> { "execute": "query-migrate" } +# <- { "return": { +# "status": "completed", +# "total-time":12345, +# "setup-time":12345, +# "downtime":12345, +# "ram":{ +# "transferred":123, +# "remaining":123, +# "total":246, +# "duplicate":123, +# "normal":123, +# "normal-bytes":123456, +# "dirty-sync-count":15 +# } +# } +# } +# +# 3. Migration is done and has failed +# +# -> { "execute": "query-migrate" } +# <- { "return": { "status": "failed" } } +# +# 4. Migration is being performed and is not a block migration: +# +# -> { "execute": "query-migrate" } +# <- { +# "return":{ +# "status":"active", +# "total-time":12345, +# "setup-time":12345, +# "expected-downtime":12345, +# "ram":{ +# "transferred":123, +# "remaining":123, +# "total":246, +# "duplicate":123, +# "normal":123, +# "normal-bytes":123456, +# "dirty-sync-count":15 +# } +# } +# } +# +# 5. Migration is being performed and is a block migration: +# +# -> { "execute": "query-migrate" } +# <- { +# "return":{ +# "status":"active", +# "total-time":12345, +# "setup-time":12345, +# "expected-downtime":12345, +# "ram":{ +# "total":1057024, +# "remaining":1053304, +# "transferred":3720, +# "duplicate":123, +# "normal":123, +# "normal-bytes":123456, +# "dirty-sync-count":15 +# }, +# "disk":{ +# "total":20971520, +# "remaining":20880384, +# "transferred":91136 +# } +# } +# } +# +# 6. Migration is being performed and XBZRLE is active: +# +# -> { "execute": "query-migrate" } +# <- { +# "return":{ +# "status":"active", +# "total-time":12345, +# "setup-time":12345, +# "expected-downtime":12345, +# "ram":{ +# "total":1057024, +# "remaining":1053304, +# "transferred":3720, +# "duplicate":10, +# "normal":3333, +# "normal-bytes":3412992, +# "dirty-sync-count":15 +# }, +# "xbzrle-cache":{ +# "cache-size":67108864, +# "bytes":20971520, +# "pages":2444343, +# "cache-miss":2244, +# "cache-miss-rate":0.123, +# "encoding-rate":80.1, +# "overflow":34434 +# } +# } +# } +# +## +{ '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 +# +# @rdma-pin-all: Controls whether or not the entire VM memory footprint is +# mlock()'d on demand or all at once. Refer to docs/rdma.txt for usage. +# Disabled by default. (since 2.0) +# +# @zero-blocks: During storage migration encode blocks of zeroes efficiently. This +# essentially saves 1MB of zeroes per block on the wire. Enabling requires +# source and target VM to support this feature. To enable it is sufficient +# to enable the capability on the source VM. The feature is disabled by +# default. (since 1.6) +# +# @compress: Use multiple compression threads to accelerate live migration. +# This feature can help to reduce the migration traffic, by sending +# compressed pages. Please note that if compress and xbzrle are both +# on, compress only takes effect in the ram bulk stage, after that, +# it will be disabled and only xbzrle takes effect, this can help to +# minimize migration traffic. The feature is disabled by default. +# (since 2.4 ) +# +# @events: generate events for each migration state change +# (since 2.4 ) +# +# @auto-converge: If enabled, QEMU will automatically throttle down the guest +# to speed up convergence of RAM migration. (since 1.6) +# +# @postcopy-ram: Start executing on the migration target before all of RAM has +# been migrated, pulling the remaining pages along as needed. The +# capacity must have the same setting on both source and target +# or migration will not even start. NOTE: If the migration fails during +# postcopy the VM will fail. (since 2.6) +# +# @x-colo: If enabled, migration will never end, and the state of the VM on the +# primary side will be migrated continuously to the VM on secondary +# side, this process is called COarse-Grain LOck Stepping (COLO) for +# Non-stop Service. (since 2.8) +# +# @release-ram: if enabled, qemu will free the migrated ram pages on the source +# during postcopy-ram migration. (since 2.9) +# +# @block: If enabled, QEMU will also migrate the contents of all block +# devices. Default is disabled. A possible alternative uses +# mirror jobs to a builtin NBD server on the destination, which +# offers more flexibility. +# (Since 2.10) +# +# @return-path: If enabled, migration will use the return path even +# for precopy. (since 2.10) +# +# @pause-before-switchover: Pause outgoing migration before serialising device +# state and before disabling block IO (since 2.11) +# +# @multifd: Use more than one fd for migration (since 4.0) +# +# @dirty-bitmaps: If enabled, QEMU will migrate named dirty bitmaps. +# (since 2.12) +# +# @postcopy-blocktime: Calculate downtime for postcopy live migration +# (since 3.0) +# +# @late-block-activate: If enabled, the destination will not activate block +# devices (and thus take locks) immediately at the end of migration. +# (since 3.0) +# +# @x-ignore-shared: If enabled, QEMU will not migrate shared memory (since 4.0) +# +# @validate-uuid: Send the UUID of the source to allow the destination +# to ensure it is the same. (since 4.2) +# +# @background-snapshot: If enabled, the migration stream will be a snapshot +# of the VM exactly at the point when the migration +# procedure starts. The VM RAM is saved with running VM. +# (since 6.0) +# +# Features: +# @unstable: Members @x-colo and @x-ignore-shared are experimental. +# +# Since: 1.2 +## +{ 'enum': 'MigrationCapability', + 'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks', + 'compress', 'events', 'postcopy-ram', + { 'name': 'x-colo', 'features': [ 'unstable' ] }, + 'release-ram', + 'block', 'return-path', 'pause-before-switchover', 'multifd', + 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate', + { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] }, + 'validate-uuid', 'background-snapshot'] } + +## +# @MigrationCapabilityStatus: +# +# Migration capability information +# +# @capability: capability enum +# +# @state: capability state bool +# +# Since: 1.2 +## +{ 'struct': '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 +# +# Example: +# +# -> { "execute": "migrate-set-capabilities" , "arguments": +# { "capabilities": [ { "capability": "xbzrle", "state": true } ] } } +# +## +{ 'command': 'migrate-set-capabilities', + 'data': { 'capabilities': ['MigrationCapabilityStatus'] } } + +## +# @query-migrate-capabilities: +# +# Returns information about the current migration capabilities status +# +# Returns: @MigrationCapabilitiesStatus +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "query-migrate-capabilities" } +# <- { "return": [ +# {"state": false, "capability": "xbzrle"}, +# {"state": false, "capability": "rdma-pin-all"}, +# {"state": false, "capability": "auto-converge"}, +# {"state": false, "capability": "zero-blocks"}, +# {"state": false, "capability": "compress"}, +# {"state": true, "capability": "events"}, +# {"state": false, "capability": "postcopy-ram"}, +# {"state": false, "capability": "x-colo"} +# ]} +# +## +{ 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']} + +## +# @MultiFDCompression: +# +# An enumeration of multifd compression methods. +# +# @none: no compression. +# @zlib: use zlib compression method. +# @zstd: use zstd compression method. +# +# Since: 5.0 +# +## +{ 'enum': 'MultiFDCompression', + 'data': [ 'none', 'zlib', + { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] } + +## +# @BitmapMigrationBitmapAliasTransform: +# +# @persistent: If present, the bitmap will be made persistent +# or transient depending on this parameter. +# +# Since: 6.0 +## +{ 'struct': 'BitmapMigrationBitmapAliasTransform', + 'data': { + '*persistent': 'bool' + } } + +## +# @BitmapMigrationBitmapAlias: +# +# @name: The name of the bitmap. +# +# @alias: An alias name for migration (for example the bitmap name on +# the opposite site). +# +# @transform: Allows the modification of the migrated bitmap. +# (since 6.0) +# +# Since: 5.2 +## +{ 'struct': 'BitmapMigrationBitmapAlias', + 'data': { + 'name': 'str', + 'alias': 'str', + '*transform': 'BitmapMigrationBitmapAliasTransform' + } } + +## +# @BitmapMigrationNodeAlias: +# +# Maps a block node name and the bitmaps it has to aliases for dirty +# bitmap migration. +# +# @node-name: A block node name. +# +# @alias: An alias block node name for migration (for example the +# node name on the opposite site). +# +# @bitmaps: Mappings for the bitmaps on this node. +# +# Since: 5.2 +## +{ 'struct': 'BitmapMigrationNodeAlias', + 'data': { + 'node-name': 'str', + 'alias': 'str', + 'bitmaps': [ 'BitmapMigrationBitmapAlias' ] + } } + +## +# @MigrationParameter: +# +# Migration parameters enumeration +# +# @announce-initial: Initial delay (in milliseconds) before sending the first +# announce (Since 4.0) +# +# @announce-max: Maximum delay (in milliseconds) between packets in the +# announcement (Since 4.0) +# +# @announce-rounds: Number of self-announce packets sent after migration +# (Since 4.0) +# +# @announce-step: Increase in delay (in milliseconds) between subsequent +# packets in the announcement (Since 4.0) +# +# @compress-level: Set the compression level to be used in live migration, +# the compression level is an integer between 0 and 9, where 0 means +# no compression, 1 means the best compression speed, and 9 means best +# compression ratio which will consume more CPU. +# +# @compress-threads: Set compression thread count to be used in live migration, +# the compression thread count is an integer between 1 and 255. +# +# @compress-wait-thread: Controls behavior when all compression threads are +# currently busy. If true (default), wait for a free +# compression thread to become available; otherwise, +# send the page uncompressed. (Since 3.1) +# +# @decompress-threads: Set decompression thread count to be used in live +# migration, the decompression thread count is an integer between 1 +# and 255. Usually, decompression is at least 4 times as fast as +# compression, so set the decompress-threads to the number about 1/4 +# of compress-threads is adequate. +# +# @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period +# to trigger throttling. It is expressed as percentage. +# The default value is 50. (Since 5.0) +# +# @cpu-throttle-initial: Initial percentage of time guest cpus are throttled +# when migration auto-converge is activated. The +# default value is 20. (Since 2.7) +# +# @cpu-throttle-increment: throttle percentage increase each time +# auto-converge detects that migration is not making +# progress. The default value is 10. (Since 2.7) +# +# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage +# At the tail stage of throttling, the Guest is very +# sensitive to CPU percentage while the @cpu-throttle +# -increment is excessive usually at tail stage. +# If this parameter is true, we will compute the ideal +# CPU percentage used by the Guest, which may exactly make +# the dirty rate match the dirty rate threshold. Then we +# will choose a smaller throttle increment between the +# one specified by @cpu-throttle-increment and the one +# generated by ideal CPU percentage. +# Therefore, it is compatible to traditional throttling, +# meanwhile the throttle increment won't be excessive +# at tail stage. +# The default value is false. (Since 5.1) +# +# @tls-creds: ID of the 'tls-creds' object that provides credentials for +# establishing a TLS connection over the migration data channel. +# On the outgoing side of the migration, the credentials must +# be for a 'client' endpoint, while for the incoming side the +# credentials must be for a 'server' endpoint. Setting this +# will enable TLS for all migrations. The default is unset, +# resulting in unsecured migration at the QEMU level. (Since 2.7) +# +# @tls-hostname: hostname of the target host for the migration. This is +# required when using x509 based TLS credentials and the +# migration URI does not already include a hostname. For +# example if using fd: or exec: based migration, the +# hostname must be provided so that the server's x509 +# certificate identity can be validated. (Since 2.7) +# +# @tls-authz: ID of the 'authz' object subclass that provides access control +# checking of the TLS x509 certificate distinguished name. +# This object is only resolved at time of use, so can be deleted +# and recreated on the fly while the migration server is active. +# If missing, it will default to denying access (Since 4.0) +# +# @max-bandwidth: to set maximum speed for migration. maximum speed in +# bytes per second. (Since 2.8) +# +# @downtime-limit: set maximum tolerated downtime for migration. maximum +# downtime in milliseconds (Since 2.8) +# +# @x-checkpoint-delay: The delay time (in ms) between two COLO checkpoints in +# periodic mode. (Since 2.8) +# +# @block-incremental: Affects how much storage is migrated when the +# block migration capability is enabled. When false, the entire +# storage backing chain is migrated into a flattened image at +# the destination; when true, only the active qcow2 layer is +# migrated and the destination must already have access to the +# same backing chain as was used on the source. (since 2.10) +# +# @multifd-channels: Number of channels used to migrate data in +# parallel. This is the same number that the +# number of sockets used for migration. The +# default value is 2 (since 4.0) +# +# @xbzrle-cache-size: cache size to be used by XBZRLE migration. It +# needs to be a multiple of the target page size +# and a power of 2 +# (Since 2.11) +# +# @max-postcopy-bandwidth: Background transfer bandwidth during postcopy. +# Defaults to 0 (unlimited). In bytes per second. +# (Since 3.0) +# +# @max-cpu-throttle: maximum cpu throttle percentage. +# Defaults to 99. (Since 3.1) +# +# @multifd-compression: Which compression method to use. +# Defaults to none. (Since 5.0) +# +# @multifd-zlib-level: Set the compression level to be used in live +# migration, the compression level is an integer between 0 +# and 9, where 0 means no compression, 1 means the best +# compression speed, and 9 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @multifd-zstd-level: Set the compression level to be used in live +# migration, the compression level is an integer between 0 +# and 20, where 0 means no compression, 1 means the best +# compression speed, and 20 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @block-bitmap-mapping: Maps block nodes and bitmaps on them to +# aliases for the purpose of dirty bitmap migration. Such +# aliases may for example be the corresponding names on the +# opposite site. +# The mapping must be one-to-one, but not necessarily +# complete: On the source, unmapped bitmaps and all bitmaps +# on unmapped nodes will be ignored. On the destination, +# encountering an unmapped alias in the incoming migration +# stream will result in a report, and all further bitmap +# migration data will then be discarded. +# Note that the destination does not know about bitmaps it +# does not receive, so there is no limitation or requirement +# regarding the number of bitmaps received, or how they are +# named, or on which nodes they are placed. +# By default (when this parameter has never been set), bitmap +# names are mapped to themselves. Nodes are mapped to their +# block device name if there is one, and to their node name +# otherwise. (Since 5.2) +# +# Features: +# @unstable: Member @x-checkpoint-delay is experimental. +# +# Since: 2.4 +## +{ 'enum': 'MigrationParameter', + 'data': ['announce-initial', 'announce-max', + 'announce-rounds', 'announce-step', + 'compress-level', 'compress-threads', 'decompress-threads', + 'compress-wait-thread', 'throttle-trigger-threshold', + 'cpu-throttle-initial', 'cpu-throttle-increment', + 'cpu-throttle-tailslow', + 'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth', + 'downtime-limit', + { 'name': 'x-checkpoint-delay', 'features': [ 'unstable' ] }, + 'block-incremental', + 'multifd-channels', + 'xbzrle-cache-size', 'max-postcopy-bandwidth', + 'max-cpu-throttle', 'multifd-compression', + 'multifd-zlib-level' ,'multifd-zstd-level', + 'block-bitmap-mapping' ] } + +## +# @MigrateSetParameters: +# +# @announce-initial: Initial delay (in milliseconds) before sending the first +# announce (Since 4.0) +# +# @announce-max: Maximum delay (in milliseconds) between packets in the +# announcement (Since 4.0) +# +# @announce-rounds: Number of self-announce packets sent after migration +# (Since 4.0) +# +# @announce-step: Increase in delay (in milliseconds) between subsequent +# packets in the announcement (Since 4.0) +# +# @compress-level: compression level +# +# @compress-threads: compression thread count +# +# @compress-wait-thread: Controls behavior when all compression threads are +# currently busy. If true (default), wait for a free +# compression thread to become available; otherwise, +# send the page uncompressed. (Since 3.1) +# +# @decompress-threads: decompression thread count +# +# @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period +# to trigger throttling. It is expressed as percentage. +# The default value is 50. (Since 5.0) +# +# @cpu-throttle-initial: Initial percentage of time guest cpus are +# throttled when migration auto-converge is activated. +# The default value is 20. (Since 2.7) +# +# @cpu-throttle-increment: throttle percentage increase each time +# auto-converge detects that migration is not making +# progress. The default value is 10. (Since 2.7) +# +# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage +# At the tail stage of throttling, the Guest is very +# sensitive to CPU percentage while the @cpu-throttle +# -increment is excessive usually at tail stage. +# If this parameter is true, we will compute the ideal +# CPU percentage used by the Guest, which may exactly make +# the dirty rate match the dirty rate threshold. Then we +# will choose a smaller throttle increment between the +# one specified by @cpu-throttle-increment and the one +# generated by ideal CPU percentage. +# Therefore, it is compatible to traditional throttling, +# meanwhile the throttle increment won't be excessive +# at tail stage. +# The default value is false. (Since 5.1) +# +# @tls-creds: ID of the 'tls-creds' object that provides credentials +# for establishing a TLS connection over the migration data +# channel. On the outgoing side of the migration, the credentials +# must be for a 'client' endpoint, while for the incoming side the +# credentials must be for a 'server' endpoint. Setting this +# to a non-empty string enables TLS for all migrations. +# An empty string means that QEMU will use plain text mode for +# migration, rather than TLS (Since 2.9) +# Previously (since 2.7), this was reported by omitting +# tls-creds instead. +# +# @tls-hostname: hostname of the target host for the migration. This +# is required when using x509 based TLS credentials and the +# migration URI does not already include a hostname. For +# example if using fd: or exec: based migration, the +# hostname must be provided so that the server's x509 +# certificate identity can be validated. (Since 2.7) +# An empty string means that QEMU will use the hostname +# associated with the migration URI, if any. (Since 2.9) +# Previously (since 2.7), this was reported by omitting +# tls-hostname instead. +# +# @max-bandwidth: to set maximum speed for migration. maximum speed in +# bytes per second. (Since 2.8) +# +# @downtime-limit: set maximum tolerated downtime for migration. maximum +# downtime in milliseconds (Since 2.8) +# +# @x-checkpoint-delay: the delay time between two COLO checkpoints. (Since 2.8) +# +# @block-incremental: Affects how much storage is migrated when the +# block migration capability is enabled. When false, the entire +# storage backing chain is migrated into a flattened image at +# the destination; when true, only the active qcow2 layer is +# migrated and the destination must already have access to the +# same backing chain as was used on the source. (since 2.10) +# +# @multifd-channels: Number of channels used to migrate data in +# parallel. This is the same number that the +# number of sockets used for migration. The +# default value is 2 (since 4.0) +# +# @xbzrle-cache-size: cache size to be used by XBZRLE migration. It +# needs to be a multiple of the target page size +# and a power of 2 +# (Since 2.11) +# +# @max-postcopy-bandwidth: Background transfer bandwidth during postcopy. +# Defaults to 0 (unlimited). In bytes per second. +# (Since 3.0) +# +# @max-cpu-throttle: maximum cpu throttle percentage. +# The default value is 99. (Since 3.1) +# +# @multifd-compression: Which compression method to use. +# Defaults to none. (Since 5.0) +# +# @multifd-zlib-level: Set the compression level to be used in live +# migration, the compression level is an integer between 0 +# and 9, where 0 means no compression, 1 means the best +# compression speed, and 9 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @multifd-zstd-level: Set the compression level to be used in live +# migration, the compression level is an integer between 0 +# and 20, where 0 means no compression, 1 means the best +# compression speed, and 20 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @block-bitmap-mapping: Maps block nodes and bitmaps on them to +# aliases for the purpose of dirty bitmap migration. Such +# aliases may for example be the corresponding names on the +# opposite site. +# The mapping must be one-to-one, but not necessarily +# complete: On the source, unmapped bitmaps and all bitmaps +# on unmapped nodes will be ignored. On the destination, +# encountering an unmapped alias in the incoming migration +# stream will result in a report, and all further bitmap +# migration data will then be discarded. +# Note that the destination does not know about bitmaps it +# does not receive, so there is no limitation or requirement +# regarding the number of bitmaps received, or how they are +# named, or on which nodes they are placed. +# By default (when this parameter has never been set), bitmap +# names are mapped to themselves. Nodes are mapped to their +# block device name if there is one, and to their node name +# otherwise. (Since 5.2) +# +# Features: +# @unstable: Member @x-checkpoint-delay is experimental. +# +# Since: 2.4 +## +# TODO either fuse back into MigrationParameters, or make +# MigrationParameters members mandatory +{ 'struct': 'MigrateSetParameters', + 'data': { '*announce-initial': 'size', + '*announce-max': 'size', + '*announce-rounds': 'size', + '*announce-step': 'size', + '*compress-level': 'uint8', + '*compress-threads': 'uint8', + '*compress-wait-thread': 'bool', + '*decompress-threads': 'uint8', + '*throttle-trigger-threshold': 'uint8', + '*cpu-throttle-initial': 'uint8', + '*cpu-throttle-increment': 'uint8', + '*cpu-throttle-tailslow': 'bool', + '*tls-creds': 'StrOrNull', + '*tls-hostname': 'StrOrNull', + '*tls-authz': 'StrOrNull', + '*max-bandwidth': 'size', + '*downtime-limit': 'uint64', + '*x-checkpoint-delay': { 'type': 'uint32', + 'features': [ 'unstable' ] }, + '*block-incremental': 'bool', + '*multifd-channels': 'uint8', + '*xbzrle-cache-size': 'size', + '*max-postcopy-bandwidth': 'size', + '*max-cpu-throttle': 'uint8', + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + +## +# @migrate-set-parameters: +# +# Set various migration parameters. +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "migrate-set-parameters" , +# "arguments": { "compress-level": 1 } } +# +## +{ 'command': 'migrate-set-parameters', 'boxed': true, + 'data': 'MigrateSetParameters' } + +## +# @MigrationParameters: +# +# The optional members aren't actually optional. +# +# @announce-initial: Initial delay (in milliseconds) before sending the +# first announce (Since 4.0) +# +# @announce-max: Maximum delay (in milliseconds) between packets in the +# announcement (Since 4.0) +# +# @announce-rounds: Number of self-announce packets sent after migration +# (Since 4.0) +# +# @announce-step: Increase in delay (in milliseconds) between subsequent +# packets in the announcement (Since 4.0) +# +# @compress-level: compression level +# +# @compress-threads: compression thread count +# +# @compress-wait-thread: Controls behavior when all compression threads are +# currently busy. If true (default), wait for a free +# compression thread to become available; otherwise, +# send the page uncompressed. (Since 3.1) +# +# @decompress-threads: decompression thread count +# +# @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period +# to trigger throttling. It is expressed as percentage. +# The default value is 50. (Since 5.0) +# +# @cpu-throttle-initial: Initial percentage of time guest cpus are +# throttled when migration auto-converge is activated. +# (Since 2.7) +# +# @cpu-throttle-increment: throttle percentage increase each time +# auto-converge detects that migration is not making +# progress. (Since 2.7) +# +# @cpu-throttle-tailslow: Make CPU throttling slower at tail stage +# At the tail stage of throttling, the Guest is very +# sensitive to CPU percentage while the @cpu-throttle +# -increment is excessive usually at tail stage. +# If this parameter is true, we will compute the ideal +# CPU percentage used by the Guest, which may exactly make +# the dirty rate match the dirty rate threshold. Then we +# will choose a smaller throttle increment between the +# one specified by @cpu-throttle-increment and the one +# generated by ideal CPU percentage. +# Therefore, it is compatible to traditional throttling, +# meanwhile the throttle increment won't be excessive +# at tail stage. +# The default value is false. (Since 5.1) +# +# @tls-creds: ID of the 'tls-creds' object that provides credentials +# for establishing a TLS connection over the migration data +# channel. On the outgoing side of the migration, the credentials +# must be for a 'client' endpoint, while for the incoming side the +# credentials must be for a 'server' endpoint. +# An empty string means that QEMU will use plain text mode for +# migration, rather than TLS (Since 2.7) +# Note: 2.8 reports this by omitting tls-creds instead. +# +# @tls-hostname: hostname of the target host for the migration. This +# is required when using x509 based TLS credentials and the +# migration URI does not already include a hostname. For +# example if using fd: or exec: based migration, the +# hostname must be provided so that the server's x509 +# certificate identity can be validated. (Since 2.7) +# An empty string means that QEMU will use the hostname +# associated with the migration URI, if any. (Since 2.9) +# Note: 2.8 reports this by omitting tls-hostname instead. +# +# @tls-authz: ID of the 'authz' object subclass that provides access control +# checking of the TLS x509 certificate distinguished name. (Since +# 4.0) +# +# @max-bandwidth: to set maximum speed for migration. maximum speed in +# bytes per second. (Since 2.8) +# +# @downtime-limit: set maximum tolerated downtime for migration. maximum +# downtime in milliseconds (Since 2.8) +# +# @x-checkpoint-delay: the delay time between two COLO checkpoints. (Since 2.8) +# +# @block-incremental: Affects how much storage is migrated when the +# block migration capability is enabled. When false, the entire +# storage backing chain is migrated into a flattened image at +# the destination; when true, only the active qcow2 layer is +# migrated and the destination must already have access to the +# same backing chain as was used on the source. (since 2.10) +# +# @multifd-channels: Number of channels used to migrate data in +# parallel. This is the same number that the +# number of sockets used for migration. +# The default value is 2 (since 4.0) +# +# @xbzrle-cache-size: cache size to be used by XBZRLE migration. It +# needs to be a multiple of the target page size +# and a power of 2 +# (Since 2.11) +# +# @max-postcopy-bandwidth: Background transfer bandwidth during postcopy. +# Defaults to 0 (unlimited). In bytes per second. +# (Since 3.0) +# +# @max-cpu-throttle: maximum cpu throttle percentage. +# Defaults to 99. +# (Since 3.1) +# +# @multifd-compression: Which compression method to use. +# Defaults to none. (Since 5.0) +# +# @multifd-zlib-level: Set the compression level to be used in live +# migration, the compression level is an integer between 0 +# and 9, where 0 means no compression, 1 means the best +# compression speed, and 9 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @multifd-zstd-level: Set the compression level to be used in live +# migration, the compression level is an integer between 0 +# and 20, where 0 means no compression, 1 means the best +# compression speed, and 20 means best compression ratio which +# will consume more CPU. +# Defaults to 1. (Since 5.0) +# +# @block-bitmap-mapping: Maps block nodes and bitmaps on them to +# aliases for the purpose of dirty bitmap migration. Such +# aliases may for example be the corresponding names on the +# opposite site. +# The mapping must be one-to-one, but not necessarily +# complete: On the source, unmapped bitmaps and all bitmaps +# on unmapped nodes will be ignored. On the destination, +# encountering an unmapped alias in the incoming migration +# stream will result in a report, and all further bitmap +# migration data will then be discarded. +# Note that the destination does not know about bitmaps it +# does not receive, so there is no limitation or requirement +# regarding the number of bitmaps received, or how they are +# named, or on which nodes they are placed. +# By default (when this parameter has never been set), bitmap +# names are mapped to themselves. Nodes are mapped to their +# block device name if there is one, and to their node name +# otherwise. (Since 5.2) +# +# Features: +# @unstable: Member @x-checkpoint-delay is experimental. +# +# Since: 2.4 +## +{ 'struct': 'MigrationParameters', + 'data': { '*announce-initial': 'size', + '*announce-max': 'size', + '*announce-rounds': 'size', + '*announce-step': 'size', + '*compress-level': 'uint8', + '*compress-threads': 'uint8', + '*compress-wait-thread': 'bool', + '*decompress-threads': 'uint8', + '*throttle-trigger-threshold': 'uint8', + '*cpu-throttle-initial': 'uint8', + '*cpu-throttle-increment': 'uint8', + '*cpu-throttle-tailslow': 'bool', + '*tls-creds': 'str', + '*tls-hostname': 'str', + '*tls-authz': 'str', + '*max-bandwidth': 'size', + '*downtime-limit': 'uint64', + '*x-checkpoint-delay': { 'type': 'uint32', + 'features': [ 'unstable' ] }, + '*block-incremental': 'bool', + '*multifd-channels': 'uint8', + '*xbzrle-cache-size': 'size', + '*max-postcopy-bandwidth': 'size', + '*max-cpu-throttle': 'uint8', + '*multifd-compression': 'MultiFDCompression', + '*multifd-zlib-level': 'uint8', + '*multifd-zstd-level': 'uint8', + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + +## +# @query-migrate-parameters: +# +# Returns information about the current migration parameters +# +# Returns: @MigrationParameters +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "query-migrate-parameters" } +# <- { "return": { +# "decompress-threads": 2, +# "cpu-throttle-increment": 10, +# "compress-threads": 8, +# "compress-level": 1, +# "cpu-throttle-initial": 20, +# "max-bandwidth": 33554432, +# "downtime-limit": 300 +# } +# } +# +## +{ 'command': 'query-migrate-parameters', + 'returns': 'MigrationParameters' } + +## +# @client_migrate_info: +# +# Set migration information for remote display. This makes the server +# ask the client to automatically reconnect using the new parameters +# once migration finished successfully. Only implemented for SPICE. +# +# @protocol: must be "spice" +# @hostname: migration target hostname +# @port: spice tcp port for plaintext channels +# @tls-port: spice tcp port for tls-secured channels +# @cert-subject: server certificate subject +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "client_migrate_info", +# "arguments": { "protocol": "spice", +# "hostname": "virt42.lab.kraxel.org", +# "port": 1234 } } +# <- { "return": {} } +# +## +{ 'command': 'client_migrate_info', + 'data': { 'protocol': 'str', 'hostname': 'str', '*port': 'int', + '*tls-port': 'int', '*cert-subject': 'str' } } + +## +# @migrate-start-postcopy: +# +# Followup to a migration command to switch the migration to postcopy mode. +# The postcopy-ram capability must be set on both source and destination +# before the original migration command. +# +# Since: 2.5 +# +# Example: +# +# -> { "execute": "migrate-start-postcopy" } +# <- { "return": {} } +# +## +{ 'command': 'migrate-start-postcopy' } + +## +# @MIGRATION: +# +# Emitted when a migration event happens +# +# @status: @MigrationStatus describing the current migration status. +# +# Since: 2.4 +# +# Example: +# +# <- {"timestamp": {"seconds": 1432121972, "microseconds": 744001}, +# "event": "MIGRATION", +# "data": {"status": "completed"} } +# +## +{ 'event': 'MIGRATION', + 'data': {'status': 'MigrationStatus'}} + +## +# @MIGRATION_PASS: +# +# Emitted from the source side of a migration at the start of each pass +# (when it syncs the dirty bitmap) +# +# @pass: An incrementing count (starting at 1 on the first pass) +# +# Since: 2.6 +# +# Example: +# +# { "timestamp": {"seconds": 1449669631, "microseconds": 239225}, +# "event": "MIGRATION_PASS", "data": {"pass": 2} } +# +## +{ 'event': 'MIGRATION_PASS', + 'data': { 'pass': 'int' } } + +## +# @COLOMessage: +# +# The message transmission between Primary side and Secondary side. +# +# @checkpoint-ready: Secondary VM (SVM) is ready for checkpointing +# +# @checkpoint-request: Primary VM (PVM) tells SVM to prepare for checkpointing +# +# @checkpoint-reply: SVM gets PVM's checkpoint request +# +# @vmstate-send: VM's state will be sent by PVM. +# +# @vmstate-size: The total size of VMstate. +# +# @vmstate-received: VM's state has been received by SVM. +# +# @vmstate-loaded: VM's state has been loaded by SVM. +# +# Since: 2.8 +## +{ 'enum': 'COLOMessage', + 'data': [ 'checkpoint-ready', 'checkpoint-request', 'checkpoint-reply', + 'vmstate-send', 'vmstate-size', 'vmstate-received', + 'vmstate-loaded' ] } + +## +# @COLOMode: +# +# The COLO current mode. +# +# @none: COLO is disabled. +# +# @primary: COLO node in primary side. +# +# @secondary: COLO node in slave side. +# +# Since: 2.8 +## +{ 'enum': 'COLOMode', + 'data': [ 'none', 'primary', 'secondary'] } + +## +# @FailoverStatus: +# +# An enumeration of COLO failover status +# +# @none: no failover has ever happened +# +# @require: got failover requirement but not handled +# +# @active: in the process of doing failover +# +# @completed: finish the process of failover +# +# @relaunch: restart the failover process, from 'none' -> 'completed' (Since 2.9) +# +# Since: 2.8 +## +{ 'enum': 'FailoverStatus', + 'data': [ 'none', 'require', 'active', 'completed', 'relaunch' ] } + +## +# @COLO_EXIT: +# +# Emitted when VM finishes COLO mode due to some errors happening or +# at the request of users. +# +# @mode: report COLO mode when COLO exited. +# +# @reason: describes the reason for the COLO exit. +# +# Since: 3.1 +# +# Example: +# +# <- { "timestamp": {"seconds": 2032141960, "microseconds": 417172}, +# "event": "COLO_EXIT", "data": {"mode": "primary", "reason": "request" } } +# +## +{ 'event': 'COLO_EXIT', + 'data': {'mode': 'COLOMode', 'reason': 'COLOExitReason' } } + +## +# @COLOExitReason: +# +# The reason for a COLO exit. +# +# @none: failover has never happened. This state does not occur +# in the COLO_EXIT event, and is only visible in the result of +# query-colo-status. +# +# @request: COLO exit is due to an external request. +# +# @error: COLO exit is due to an internal error. +# +# @processing: COLO is currently handling a failover (since 4.0). +# +# Since: 3.1 +## +{ 'enum': 'COLOExitReason', + 'data': [ 'none', 'request', 'error' , 'processing' ] } + +## +# @x-colo-lost-heartbeat: +# +# Tell qemu that heartbeat is lost, request it to do takeover procedures. +# If this command is sent to the PVM, the Primary side will exit COLO mode. +# If sent to the Secondary, the Secondary side will run failover work, +# then takes over server operation to become the service VM. +# +# Features: +# @unstable: This command is experimental. +# +# Since: 2.8 +# +# Example: +# +# -> { "execute": "x-colo-lost-heartbeat" } +# <- { "return": {} } +# +## +{ 'command': 'x-colo-lost-heartbeat', + 'features': [ 'unstable' ] } + +## +# @migrate_cancel: +# +# Cancel the current executing migration process. +# +# Returns: nothing on success +# +# Notes: This command succeeds even if there is no migration process running. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "migrate_cancel" } +# <- { "return": {} } +# +## +{ 'command': 'migrate_cancel' } + +## +# @migrate-continue: +# +# Continue migration when it's in a paused state. +# +# @state: The state the migration is currently expected to be in +# +# Returns: nothing on success +# Since: 2.11 +# Example: +# +# -> { "execute": "migrate-continue" , "arguments": +# { "state": "pre-switchover" } } +# <- { "return": {} } +## +{ 'command': 'migrate-continue', 'data': {'state': 'MigrationStatus'} } + +## +# @migrate: +# +# Migrates the current running guest to another Virtual Machine. +# +# @uri: the Uniform Resource Identifier of the destination VM +# +# @blk: do block migration (full disk copy) +# +# @inc: incremental disk copy migration +# +# @detach: this argument exists only for compatibility reasons and +# is ignored by QEMU +# +# @resume: resume one paused migration, default "off". (since 3.0) +# +# Returns: nothing on success +# +# Since: 0.14 +# +# Notes: +# +# 1. The 'query-migrate' command should be used to check migration's progress +# and final result (this information is provided by the 'status' member) +# +# 2. All boolean arguments default to false +# +# 3. The user Monitor's "detach" argument is invalid in QMP and should not +# be used +# +# Example: +# +# -> { "execute": "migrate", "arguments": { "uri": "tcp:0:4446" } } +# <- { "return": {} } +# +## +{ 'command': 'migrate', + 'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', + '*detach': 'bool', '*resume': 'bool' } } + +## +# @migrate-incoming: +# +# Start an incoming migration, the qemu must have been started +# with -incoming defer +# +# @uri: The Uniform Resource Identifier identifying the source or +# address to listen on +# +# Returns: nothing on success +# +# Since: 2.3 +# +# Notes: +# +# 1. It's a bad idea to use a string for the uri, but it needs to stay +# compatible with -incoming and the format of the uri is already exposed +# above libvirt. +# +# 2. QEMU must be started with -incoming defer to allow migrate-incoming to +# be used. +# +# 3. The uri format is the same as for -incoming +# +# Example: +# +# -> { "execute": "migrate-incoming", +# "arguments": { "uri": "tcp::4446" } } +# <- { "return": {} } +# +## +{ 'command': 'migrate-incoming', 'data': {'uri': 'str' } } + +## +# @xen-save-devices-state: +# +# Save the state of all devices to file. The RAM and the block devices +# of the VM are not saved by this command. +# +# @filename: the file to save the state of the devices to as binary +# data. See xen-save-devices-state.txt for a description of the binary +# format. +# +# @live: Optional argument to ask QEMU to treat this command as part of a live +# migration. Default to true. (since 2.11) +# +# Returns: Nothing on success +# +# Since: 1.1 +# +# Example: +# +# -> { "execute": "xen-save-devices-state", +# "arguments": { "filename": "/tmp/save" } } +# <- { "return": {} } +# +## +{ 'command': 'xen-save-devices-state', + 'data': {'filename': 'str', '*live':'bool' } } + +## +# @xen-set-global-dirty-log: +# +# Enable or disable the global dirty log mode. +# +# @enable: true to enable, false to disable. +# +# Returns: nothing +# +# Since: 1.3 +# +# Example: +# +# -> { "execute": "xen-set-global-dirty-log", +# "arguments": { "enable": true } } +# <- { "return": {} } +# +## +{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } } + +## +# @xen-load-devices-state: +# +# Load the state of all devices from file. The RAM and the block devices +# of the VM are not loaded by this command. +# +# @filename: the file to load the state of the devices from as binary +# data. See xen-save-devices-state.txt for a description of the binary +# format. +# +# Since: 2.7 +# +# Example: +# +# -> { "execute": "xen-load-devices-state", +# "arguments": { "filename": "/tmp/resume" } } +# <- { "return": {} } +# +## +{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} } + +## +# @xen-set-replication: +# +# Enable or disable replication. +# +# @enable: true to enable, false to disable. +# +# @primary: true for primary or false for secondary. +# +# @failover: true to do failover, false to stop. but cannot be +# specified if 'enable' is true. default value is false. +# +# Returns: nothing. +# +# Example: +# +# -> { "execute": "xen-set-replication", +# "arguments": {"enable": true, "primary": false} } +# <- { "return": {} } +# +# Since: 2.9 +## +{ 'command': 'xen-set-replication', + 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' }, + 'if': 'CONFIG_REPLICATION' } + +## +# @ReplicationStatus: +# +# The result format for 'query-xen-replication-status'. +# +# @error: true if an error happened, false if replication is normal. +# +# @desc: the human readable error description string, when +# @error is 'true'. +# +# Since: 2.9 +## +{ 'struct': 'ReplicationStatus', + 'data': { 'error': 'bool', '*desc': 'str' }, + 'if': 'CONFIG_REPLICATION' } + +## +# @query-xen-replication-status: +# +# Query replication status while the vm is running. +# +# Returns: A @ReplicationResult object showing the status. +# +# Example: +# +# -> { "execute": "query-xen-replication-status" } +# <- { "return": { "error": false } } +# +# Since: 2.9 +## +{ 'command': 'query-xen-replication-status', + 'returns': 'ReplicationStatus', + 'if': 'CONFIG_REPLICATION' } + +## +# @xen-colo-do-checkpoint: +# +# Xen uses this command to notify replication to trigger a checkpoint. +# +# Returns: nothing. +# +# Example: +# +# -> { "execute": "xen-colo-do-checkpoint" } +# <- { "return": {} } +# +# Since: 2.9 +## +{ 'command': 'xen-colo-do-checkpoint', + 'if': 'CONFIG_REPLICATION' } + +## +# @COLOStatus: +# +# The result format for 'query-colo-status'. +# +# @mode: COLO running mode. If COLO is running, this field will return +# 'primary' or 'secondary'. +# +# @last-mode: COLO last running mode. If COLO is running, this field +# will return same like mode field, after failover we can +# use this field to get last colo mode. (since 4.0) +# +# @reason: describes the reason for the COLO exit. +# +# Since: 3.1 +## +{ 'struct': 'COLOStatus', + 'data': { 'mode': 'COLOMode', 'last-mode': 'COLOMode', + 'reason': 'COLOExitReason' } } + +## +# @query-colo-status: +# +# Query COLO status while the vm is running. +# +# Returns: A @COLOStatus object showing the status. +# +# Example: +# +# -> { "execute": "query-colo-status" } +# <- { "return": { "mode": "primary", "reason": "request" } } +# +# Since: 3.1 +## +{ 'command': 'query-colo-status', + 'returns': 'COLOStatus' } + +## +# @migrate-recover: +# +# Provide a recovery migration stream URI. +# +# @uri: the URI to be used for the recovery of migration stream. +# +# Returns: nothing. +# +# Example: +# +# -> { "execute": "migrate-recover", +# "arguments": { "uri": "tcp:192.168.1.200:12345" } } +# <- { "return": {} } +# +# Since: 3.0 +## +{ 'command': 'migrate-recover', + 'data': { 'uri': 'str' }, + 'allow-oob': true } + +## +# @migrate-pause: +# +# Pause a migration. Currently it only supports postcopy. +# +# Returns: nothing. +# +# Example: +# +# -> { "execute": "migrate-pause" } +# <- { "return": {} } +# +# Since: 3.0 +## +{ 'command': 'migrate-pause', 'allow-oob': true } + +## +# @UNPLUG_PRIMARY: +# +# Emitted from source side of a migration when migration state is +# WAIT_UNPLUG. Device was unplugged by guest operating system. +# Device resources in QEMU are kept on standby to be able to re-plug it in case +# of migration failure. +# +# @device-id: QEMU device id of the unplugged device +# +# Since: 4.2 +# +# Example: +# {"event": "UNPLUG_PRIMARY", "data": {"device-id": "hostdev0"} } +# +## +{ 'event': 'UNPLUG_PRIMARY', + 'data': { 'device-id': 'str' } } + +## +# @DirtyRateVcpu: +# +# Dirty rate of vcpu. +# +# @id: vcpu index. +# +# @dirty-rate: dirty rate. +# +# Since: 6.2 +# +## +{ 'struct': 'DirtyRateVcpu', + 'data': { 'id': 'int', 'dirty-rate': 'int64' } } + +## +# @DirtyRateStatus: +# +# An enumeration of dirtyrate status. +# +# @unstarted: the dirtyrate thread has not been started. +# +# @measuring: the dirtyrate thread is measuring. +# +# @measured: the dirtyrate thread has measured and results are available. +# +# Since: 5.2 +# +## +{ 'enum': 'DirtyRateStatus', + 'data': [ 'unstarted', 'measuring', 'measured'] } + +## +# @DirtyRateMeasureMode: +# +# An enumeration of mode of measuring dirtyrate. +# +# @page-sampling: calculate dirtyrate by sampling pages. +# +# @dirty-ring: calculate dirtyrate by dirty ring. +# +# @dirty-bitmap: calculate dirtyrate by dirty bitmap. +# +# Since: 6.2 +# +## +{ 'enum': 'DirtyRateMeasureMode', + 'data': ['page-sampling', 'dirty-ring', 'dirty-bitmap'] } + +## +# @DirtyRateInfo: +# +# Information about current dirty page rate of vm. +# +# @dirty-rate: an estimate of the dirty page rate of the VM in units of +# MB/s, present only when estimating the rate has completed. +# +# @status: status containing dirtyrate query status includes +# 'unstarted' or 'measuring' or 'measured' +# +# @start-time: start time in units of second for calculation +# +# @calc-time: time in units of second for sample dirty pages +# +# @sample-pages: page count per GB for sample dirty pages +# the default value is 512 (since 6.1) +# +# @mode: mode containing method of calculate dirtyrate includes +# 'page-sampling' and 'dirty-ring' (Since 6.2) +# +# @vcpu-dirty-rate: dirtyrate for each vcpu if dirty-ring +# mode specified (Since 6.2) +# +# Since: 5.2 +# +## +{ 'struct': 'DirtyRateInfo', + 'data': {'*dirty-rate': 'int64', + 'status': 'DirtyRateStatus', + 'start-time': 'int64', + 'calc-time': 'int64', + 'sample-pages': 'uint64', + 'mode': 'DirtyRateMeasureMode', + '*vcpu-dirty-rate': [ 'DirtyRateVcpu' ] } } + +## +# @calc-dirty-rate: +# +# start calculating dirty page rate for vm +# +# @calc-time: time in units of second for sample dirty pages +# +# @sample-pages: page count per GB for sample dirty pages +# the default value is 512 (since 6.1) +# +# @mode: mechanism of calculating dirtyrate includes +# 'page-sampling' and 'dirty-ring' (Since 6.1) +# +# Since: 5.2 +# +# Example: +# {"command": "calc-dirty-rate", "data": {"calc-time": 1, +# 'sample-pages': 512} } +# +## +{ 'command': 'calc-dirty-rate', 'data': {'calc-time': 'int64', + '*sample-pages': 'int', + '*mode': 'DirtyRateMeasureMode'} } + +## +# @query-dirty-rate: +# +# query dirty page rate in units of MB/s for vm +# +# Since: 5.2 +## +{ 'command': 'query-dirty-rate', 'returns': 'DirtyRateInfo' } + +## +# @snapshot-save: +# +# Save a VM snapshot +# +# @job-id: identifier for the newly created job +# @tag: name of the snapshot to create +# @vmstate: block device node name to save vmstate to +# @devices: list of block device node names to save a snapshot to +# +# Applications should not assume that the snapshot save is complete +# when this command returns. The job commands / events must be used +# to determine completion and to fetch details of any errors that arise. +# +# Note that execution of the guest CPUs may be stopped during the +# time it takes to save the snapshot. A future version of QEMU +# may ensure CPUs are executing continuously. +# +# It is strongly recommended that @devices contain all writable +# block device nodes if a consistent snapshot is required. +# +# If @tag already exists, an error will be reported +# +# Returns: nothing +# +# Example: +# +# -> { "execute": "snapshot-save", +# "data": { +# "job-id": "snapsave0", +# "tag": "my-snap", +# "vmstate": "disk0", +# "devices": ["disk0", "disk1"] +# } +# } +# <- { "return": { } } +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "created", "id": "snapsave0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "running", "id": "snapsave0"}} +# <- {"event": "STOP"} +# <- {"event": "RESUME"} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "waiting", "id": "snapsave0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "pending", "id": "snapsave0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "concluded", "id": "snapsave0"}} +# -> {"execute": "query-jobs"} +# <- {"return": [{"current-progress": 1, +# "status": "concluded", +# "total-progress": 1, +# "type": "snapshot-save", +# "id": "snapsave0"}]} +# +# Since: 6.0 +## +{ 'command': 'snapshot-save', + 'data': { 'job-id': 'str', + 'tag': 'str', + 'vmstate': 'str', + 'devices': ['str'] } } + +## +# @snapshot-load: +# +# Load a VM snapshot +# +# @job-id: identifier for the newly created job +# @tag: name of the snapshot to load. +# @vmstate: block device node name to load vmstate from +# @devices: list of block device node names to load a snapshot from +# +# Applications should not assume that the snapshot load is complete +# when this command returns. The job commands / events must be used +# to determine completion and to fetch details of any errors that arise. +# +# Note that execution of the guest CPUs will be stopped during the +# time it takes to load the snapshot. +# +# It is strongly recommended that @devices contain all writable +# block device nodes that can have changed since the original +# @snapshot-save command execution. +# +# Returns: nothing +# +# Example: +# +# -> { "execute": "snapshot-load", +# "data": { +# "job-id": "snapload0", +# "tag": "my-snap", +# "vmstate": "disk0", +# "devices": ["disk0", "disk1"] +# } +# } +# <- { "return": { } } +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "created", "id": "snapload0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "running", "id": "snapload0"}} +# <- {"event": "STOP"} +# <- {"event": "RESUME"} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "waiting", "id": "snapload0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "pending", "id": "snapload0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "concluded", "id": "snapload0"}} +# -> {"execute": "query-jobs"} +# <- {"return": [{"current-progress": 1, +# "status": "concluded", +# "total-progress": 1, +# "type": "snapshot-load", +# "id": "snapload0"}]} +# +# Since: 6.0 +## +{ 'command': 'snapshot-load', + 'data': { 'job-id': 'str', + 'tag': 'str', + 'vmstate': 'str', + 'devices': ['str'] } } + +## +# @snapshot-delete: +# +# Delete a VM snapshot +# +# @job-id: identifier for the newly created job +# @tag: name of the snapshot to delete. +# @devices: list of block device node names to delete a snapshot from +# +# Applications should not assume that the snapshot delete is complete +# when this command returns. The job commands / events must be used +# to determine completion and to fetch details of any errors that arise. +# +# Returns: nothing +# +# Example: +# +# -> { "execute": "snapshot-delete", +# "data": { +# "job-id": "snapdelete0", +# "tag": "my-snap", +# "devices": ["disk0", "disk1"] +# } +# } +# <- { "return": { } } +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "created", "id": "snapdelete0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "running", "id": "snapdelete0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "waiting", "id": "snapdelete0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "pending", "id": "snapdelete0"}} +# <- {"event": "JOB_STATUS_CHANGE", +# "data": {"status": "concluded", "id": "snapdelete0"}} +# -> {"execute": "query-jobs"} +# <- {"return": [{"current-progress": 1, +# "status": "concluded", +# "total-progress": 1, +# "type": "snapshot-delete", +# "id": "snapdelete0"}]} +# +# Since: 6.0 +## +{ 'command': 'snapshot-delete', + 'data': { 'job-id': 'str', + 'tag': 'str', + 'devices': ['str'] } } diff --git a/qapi/misc-target.json b/qapi/misc-target.json new file mode 100644 index 000000000..5aa2b95b7 --- /dev/null +++ b/qapi/misc-target.json @@ -0,0 +1,399 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# @RTC_CHANGE: +# +# Emitted when the guest changes the RTC time. +# +# @offset: offset between base RTC clock (as specified by -rtc base), and +# new RTC clock value +# +# Note: This event is rate-limited. +# +# Since: 0.13 +# +# Example: +# +# <- { "event": "RTC_CHANGE", +# "data": { "offset": 78 }, +# "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } +# +## +{ 'event': 'RTC_CHANGE', + 'data': { 'offset': 'int' }, + 'if': { 'any': [ 'TARGET_ALPHA', + 'TARGET_ARM', + 'TARGET_HPPA', + 'TARGET_I386', + 'TARGET_MIPS', + 'TARGET_MIPS64', + 'TARGET_PPC', + 'TARGET_PPC64', + 'TARGET_S390X', + 'TARGET_SH4', + 'TARGET_SPARC' ] } } + +## +# @rtc-reset-reinjection: +# +# This command will reset the RTC interrupt reinjection backlog. +# Can be used if another mechanism to synchronize guest time +# is in effect, for example QEMU guest agent's guest-set-time +# command. +# +# Since: 2.1 +# +# Example: +# +# -> { "execute": "rtc-reset-reinjection" } +# <- { "return": {} } +# +## +{ 'command': 'rtc-reset-reinjection', + 'if': 'TARGET_I386' } + + +## +# @SevState: +# +# An enumeration of SEV state information used during @query-sev. +# +# @uninit: The guest is uninitialized. +# +# @launch-update: The guest is currently being launched; plaintext data and +# register state is being imported. +# +# @launch-secret: The guest is currently being launched; ciphertext data +# is being imported. +# +# @running: The guest is fully launched or migrated in. +# +# @send-update: The guest is currently being migrated out to another machine. +# +# @receive-update: The guest is currently being migrated from another machine. +# +# Since: 2.12 +## +{ 'enum': 'SevState', + 'data': ['uninit', 'launch-update', 'launch-secret', 'running', + 'send-update', 'receive-update' ], + 'if': 'TARGET_I386' } + +## +# @SevInfo: +# +# Information about Secure Encrypted Virtualization (SEV) support +# +# @enabled: true if SEV is active +# +# @api-major: SEV API major version +# +# @api-minor: SEV API minor version +# +# @build-id: SEV FW build id +# +# @policy: SEV policy value +# +# @state: SEV guest state +# +# @handle: SEV firmware handle +# +# Since: 2.12 +## +{ 'struct': 'SevInfo', + 'data': { 'enabled': 'bool', + 'api-major': 'uint8', + 'api-minor' : 'uint8', + 'build-id' : 'uint8', + 'policy' : 'uint32', + 'state' : 'SevState', + 'handle' : 'uint32' + }, + 'if': 'TARGET_I386' +} + +## +# @query-sev: +# +# Returns information about SEV +# +# Returns: @SevInfo +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev" } +# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0, +# "build-id" : 0, "policy" : 0, "state" : "running", +# "handle" : 1 } } +# +## +{ 'command': 'query-sev', 'returns': 'SevInfo', + 'if': 'TARGET_I386' } + + +## +# @SevLaunchMeasureInfo: +# +# SEV Guest Launch measurement information +# +# @data: the measurement value encoded in base64 +# +# Since: 2.12 +# +## +{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'}, + 'if': 'TARGET_I386' } + +## +# @query-sev-launch-measure: +# +# Query the SEV guest launch information. +# +# Returns: The @SevLaunchMeasureInfo for the guest +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev-launch-measure" } +# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } } +# +## +{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo', + 'if': 'TARGET_I386' } + + +## +# @SevCapability: +# +# The struct describes capability for a Secure Encrypted Virtualization +# feature. +# +# @pdh: Platform Diffie-Hellman key (base64 encoded) +# +# @cert-chain: PDH certificate chain (base64 encoded) +# +# @cbitpos: C-bit location in page table entry +# +# @reduced-phys-bits: Number of physical Address bit reduction when SEV is +# enabled +# +# Since: 2.12 +## +{ 'struct': 'SevCapability', + 'data': { 'pdh': 'str', + 'cert-chain': 'str', + 'cbitpos': 'int', + 'reduced-phys-bits': 'int'}, + 'if': 'TARGET_I386' } + +## +# @query-sev-capabilities: +# +# This command is used to get the SEV capabilities, and is supported on AMD +# X86 platforms only. +# +# Returns: SevCapability objects. +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev-capabilities" } +# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE", +# "cbitpos": 47, "reduced-phys-bits": 5}} +# +## +{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability', + 'if': 'TARGET_I386' } + +## +# @sev-inject-launch-secret: +# +# This command injects a secret blob into memory of SEV guest. +# +# @packet-header: the launch secret packet header encoded in base64 +# +# @secret: the launch secret data to be injected encoded in base64 +# +# @gpa: the guest physical address where secret will be injected. +# +# Since: 6.0 +# +## +{ 'command': 'sev-inject-launch-secret', + 'data': { 'packet-header': 'str', 'secret': 'str', '*gpa': 'uint64' }, + 'if': 'TARGET_I386' } + +## +# @SevAttestationReport: +# +# The struct describes attestation report for a Secure Encrypted +# Virtualization feature. +# +# @data: guest attestation report (base64 encoded) +# +# +# Since: 6.1 +## +{ 'struct': 'SevAttestationReport', + 'data': { 'data': 'str'}, + 'if': 'TARGET_I386' } + +## +# @query-sev-attestation-report: +# +# This command is used to get the SEV attestation report, and is +# supported on AMD X86 platforms only. +# +# @mnonce: a random 16 bytes value encoded in base64 (it will be +# included in report) +# +# Returns: SevAttestationReport objects. +# +# Since: 6.1 +# +# Example: +# +# -> { "execute" : "query-sev-attestation-report", +# "arguments": { "mnonce": "aaaaaaa" } } +# <- { "return" : { "data": "aaaaaaaabbbddddd"} } +# +## +{ 'command': 'query-sev-attestation-report', + 'data': { 'mnonce': 'str' }, + 'returns': 'SevAttestationReport', + 'if': 'TARGET_I386' } + +## +# @dump-skeys: +# +# Dump guest's storage keys +# +# @filename: the path to the file to dump to +# +# This command is only supported on s390 architecture. +# +# Since: 2.5 +# +# Example: +# +# -> { "execute": "dump-skeys", +# "arguments": { "filename": "/tmp/skeys" } } +# <- { "return": {} } +# +## +{ 'command': 'dump-skeys', + 'data': { 'filename': 'str' }, + 'if': 'TARGET_S390X' } + +## +# @GICCapability: +# +# The struct describes capability for a specific GIC (Generic +# Interrupt Controller) version. These bits are not only decided by +# QEMU/KVM software version, but also decided by the hardware that +# the program is running upon. +# +# @version: version of GIC to be described. Currently, only 2 and 3 +# are supported. +# +# @emulated: whether current QEMU/hardware supports emulated GIC +# device in user space. +# +# @kernel: whether current QEMU/hardware supports hardware +# accelerated GIC device in kernel. +# +# Since: 2.6 +## +{ 'struct': 'GICCapability', + 'data': { 'version': 'int', + 'emulated': 'bool', + 'kernel': 'bool' }, + 'if': 'TARGET_ARM' } + +## +# @query-gic-capabilities: +# +# This command is ARM-only. It will return a list of GICCapability +# objects that describe its capability bits. +# +# Returns: a list of GICCapability objects. +# +# Since: 2.6 +# +# Example: +# +# -> { "execute": "query-gic-capabilities" } +# <- { "return": [{ "version": 2, "emulated": true, "kernel": false }, +# { "version": 3, "emulated": false, "kernel": true } ] } +# +## +{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'], + 'if': 'TARGET_ARM' } + + +## +# @SGXInfo: +# +# Information about intel Safe Guard eXtension (SGX) support +# +# @sgx: true if SGX is supported +# +# @sgx1: true if SGX1 is supported +# +# @sgx2: true if SGX2 is supported +# +# @flc: true if FLC is supported +# +# @section-size: The EPC section size for guest +# +# Since: 6.2 +## +{ 'struct': 'SGXInfo', + 'data': { 'sgx': 'bool', + 'sgx1': 'bool', + 'sgx2': 'bool', + 'flc': 'bool', + 'section-size': 'uint64'}, + 'if': 'TARGET_I386' } + +## +# @query-sgx: +# +# Returns information about SGX +# +# Returns: @SGXInfo +# +# Since: 6.2 +# +# Example: +# +# -> { "execute": "query-sgx" } +# <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true, +# "flc": true, "section-size" : 0 } } +# +## +{ 'command': 'query-sgx', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } + +## +# @query-sgx-capabilities: +# +# Returns information from host SGX capabilities +# +# Returns: @SGXInfo +# +# Since: 6.2 +# +# Example: +# +# -> { "execute": "query-sgx-capabilities" } +# <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true, +# "flc": true, "section-size" : 0 } } +# +## +{ 'command': 'query-sgx-capabilities', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } diff --git a/qapi/misc.json b/qapi/misc.json new file mode 100644 index 000000000..358548abe --- /dev/null +++ b/qapi/misc.json @@ -0,0 +1,529 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Miscellanea +## + +{ 'include': 'common.json' } + +## +# @add_client: +# +# Allow client connections for VNC, Spice and socket based +# character devices to be passed in to QEMU via SCM_RIGHTS. +# +# @protocol: protocol name. Valid names are "vnc", "spice" or the +# name of a character device (eg. from -chardev id=XXXX) +# +# @fdname: file descriptor name previously passed via 'getfd' command +# +# @skipauth: whether to skip authentication. Only applies +# to "vnc" and "spice" protocols +# +# @tls: whether to perform TLS. Only applies to the "spice" +# protocol +# +# Returns: nothing on success. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "add_client", "arguments": { "protocol": "vnc", +# "fdname": "myclient" } } +# <- { "return": {} } +# +## +{ 'command': 'add_client', + 'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool', + '*tls': 'bool' } } + +## +# @NameInfo: +# +# Guest name information. +# +# @name: The name of the guest +# +# Since: 0.14 +## +{ 'struct': 'NameInfo', 'data': {'*name': 'str'} } + +## +# @query-name: +# +# Return the name information of a guest. +# +# Returns: @NameInfo of the guest +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-name" } +# <- { "return": { "name": "qemu-name" } } +# +## +{ 'command': 'query-name', 'returns': 'NameInfo', 'allow-preconfig': true } + +## +# @IOThreadInfo: +# +# Information about an iothread +# +# @id: the identifier of the iothread +# +# @thread-id: ID of the underlying host thread +# +# @poll-max-ns: maximum polling time in ns, 0 means polling is disabled +# (since 2.9) +# +# @poll-grow: how many ns will be added to polling time, 0 means that it's not +# configured (since 2.9) +# +# @poll-shrink: how many ns will be removed from polling time, 0 means that +# it's not configured (since 2.9) +# +# @aio-max-batch: maximum number of requests in a batch for the AIO engine, +# 0 means that the engine will use its default (since 6.1) +# +# Since: 2.0 +## +{ 'struct': 'IOThreadInfo', + 'data': {'id': 'str', + 'thread-id': 'int', + 'poll-max-ns': 'int', + 'poll-grow': 'int', + 'poll-shrink': 'int', + 'aio-max-batch': 'int' } } + +## +# @query-iothreads: +# +# Returns a list of information about each iothread. +# +# Note: this list excludes the QEMU main loop thread, which is not declared +# using the -object iothread command-line option. It is always the main thread +# of the process. +# +# Returns: a list of @IOThreadInfo for each iothread +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "query-iothreads" } +# <- { "return": [ +# { +# "id":"iothread0", +# "thread-id":3134 +# }, +# { +# "id":"iothread1", +# "thread-id":3135 +# } +# ] +# } +# +## +{ 'command': 'query-iothreads', 'returns': ['IOThreadInfo'], + 'allow-preconfig': true } + +## +# @stop: +# +# Stop all guest VCPU execution. +# +# Since: 0.14 +# +# Notes: This function will succeed even if the guest is already in the stopped +# state. In "inmigrate" state, it will ensure that the guest +# remains paused once migration finishes, as if the -S option was +# passed on the command line. +# +# Example: +# +# -> { "execute": "stop" } +# <- { "return": {} } +# +## +{ 'command': 'stop' } + +## +# @cont: +# +# Resume guest VCPU execution. +# +# Since: 0.14 +# +# Returns: If successful, nothing +# +# Notes: This command will succeed if the guest is currently running. It +# will also succeed if the guest is in the "inmigrate" state; in +# this case, the effect of the command is to make sure the guest +# starts once migration finishes, removing the effect of the -S +# command line option if it was passed. +# +# Example: +# +# -> { "execute": "cont" } +# <- { "return": {} } +# +## +{ 'command': 'cont' } + +## +# @x-exit-preconfig: +# +# Exit from "preconfig" state +# +# This command makes QEMU exit the preconfig state and proceed with +# VM initialization using configuration data provided on the command line +# and via the QMP monitor during the preconfig state. The command is only +# available during the preconfig state (i.e. when the --preconfig command +# line option was in use). +# +# Features: +# @unstable: This command is experimental. +# +# Since 3.0 +# +# Returns: nothing +# +# Example: +# +# -> { "execute": "x-exit-preconfig" } +# <- { "return": {} } +# +## +{ 'command': 'x-exit-preconfig', 'allow-preconfig': true, + 'features': [ 'unstable' ] } + +## +# @human-monitor-command: +# +# Execute a command on the human monitor and return the output. +# +# @command-line: the command to execute in the human monitor +# +# @cpu-index: The CPU to use for commands that require an implicit CPU +# +# Features: +# @savevm-monitor-nodes: If present, HMP command savevm only snapshots +# monitor-owned nodes if they have no parents. +# This allows the use of 'savevm' with +# -blockdev. (since 4.2) +# +# Returns: the output of the command as a string +# +# Since: 0.14 +# +# Notes: This command only exists as a stop-gap. Its use is highly +# discouraged. The semantics of this command are not +# guaranteed: this means that command names, arguments and +# responses can change or be removed at ANY time. Applications +# that rely on long term stability guarantees should NOT +# use this command. +# +# Known limitations: +# +# * This command is stateless, this means that commands that depend +# on state information (such as getfd) might not work +# +# * Commands that prompt the user for data don't currently work +# +# Example: +# +# -> { "execute": "human-monitor-command", +# "arguments": { "command-line": "info kvm" } } +# <- { "return": "kvm support: enabled\r\n" } +# +## +{ 'command': 'human-monitor-command', + 'data': {'command-line': 'str', '*cpu-index': 'int'}, + 'returns': 'str', + 'features': [ 'savevm-monitor-nodes' ] } + +## +# @getfd: +# +# Receive a file descriptor via SCM rights and assign it a name +# +# @fdname: file descriptor name +# +# Returns: Nothing on success +# +# Since: 0.14 +# +# Notes: If @fdname already exists, the file descriptor assigned to +# it will be closed and replaced by the received file +# descriptor. +# +# The 'closefd' command can be used to explicitly close the +# file descriptor when it is no longer needed. +# +# Example: +# +# -> { "execute": "getfd", "arguments": { "fdname": "fd1" } } +# <- { "return": {} } +# +## +{ 'command': 'getfd', 'data': {'fdname': 'str'} } + +## +# @closefd: +# +# Close a file descriptor previously passed via SCM rights +# +# @fdname: file descriptor name +# +# Returns: Nothing on success +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "closefd", "arguments": { "fdname": "fd1" } } +# <- { "return": {} } +# +## +{ 'command': 'closefd', 'data': {'fdname': 'str'} } + +## +# @AddfdInfo: +# +# Information about a file descriptor that was added to an fd set. +# +# @fdset-id: The ID of the fd set that @fd was added to. +# +# @fd: The file descriptor that was received via SCM rights and +# added to the fd set. +# +# Since: 1.2 +## +{ 'struct': 'AddfdInfo', 'data': {'fdset-id': 'int', 'fd': 'int'} } + +## +# @add-fd: +# +# Add a file descriptor, that was passed via SCM rights, to an fd set. +# +# @fdset-id: The ID of the fd set to add the file descriptor to. +# +# @opaque: A free-form string that can be used to describe the fd. +# +# Returns: - @AddfdInfo on success +# - If file descriptor was not received, FdNotSupplied +# - If @fdset-id is a negative value, InvalidParameterValue +# +# Notes: The list of fd sets is shared by all monitor connections. +# +# If @fdset-id is not specified, a new fd set will be created. +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "add-fd", "arguments": { "fdset-id": 1 } } +# <- { "return": { "fdset-id": 1, "fd": 3 } } +# +## +{ 'command': 'add-fd', + 'data': { '*fdset-id': 'int', + '*opaque': 'str' }, + 'returns': 'AddfdInfo' } + +## +# @remove-fd: +# +# Remove a file descriptor from an fd set. +# +# @fdset-id: The ID of the fd set that the file descriptor belongs to. +# +# @fd: The file descriptor that is to be removed. +# +# Returns: - Nothing on success +# - If @fdset-id or @fd is not found, FdNotFound +# +# Since: 1.2 +# +# Notes: The list of fd sets is shared by all monitor connections. +# +# If @fd is not specified, all file descriptors in @fdset-id +# will be removed. +# +# Example: +# +# -> { "execute": "remove-fd", "arguments": { "fdset-id": 1, "fd": 3 } } +# <- { "return": {} } +# +## +{ 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} } + +## +# @FdsetFdInfo: +# +# Information about a file descriptor that belongs to an fd set. +# +# @fd: The file descriptor value. +# +# @opaque: A free-form string that can be used to describe the fd. +# +# Since: 1.2 +## +{ 'struct': 'FdsetFdInfo', + 'data': {'fd': 'int', '*opaque': 'str'} } + +## +# @FdsetInfo: +# +# Information about an fd set. +# +# @fdset-id: The ID of the fd set. +# +# @fds: A list of file descriptors that belong to this fd set. +# +# Since: 1.2 +## +{ 'struct': 'FdsetInfo', + 'data': {'fdset-id': 'int', 'fds': ['FdsetFdInfo']} } + +## +# @query-fdsets: +# +# Return information describing all fd sets. +# +# Returns: A list of @FdsetInfo +# +# Since: 1.2 +# +# Note: The list of fd sets is shared by all monitor connections. +# +# Example: +# +# -> { "execute": "query-fdsets" } +# <- { "return": [ +# { +# "fds": [ +# { +# "fd": 30, +# "opaque": "rdonly:/path/to/file" +# }, +# { +# "fd": 24, +# "opaque": "rdwr:/path/to/file" +# } +# ], +# "fdset-id": 1 +# }, +# { +# "fds": [ +# { +# "fd": 28 +# }, +# { +# "fd": 29 +# } +# ], +# "fdset-id": 0 +# } +# ] +# } +# +## +{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] } + +## +# @CommandLineParameterType: +# +# Possible types for an option parameter. +# +# @string: accepts a character string +# +# @boolean: accepts "on" or "off" +# +# @number: accepts a number +# +# @size: accepts a number followed by an optional suffix (K)ilo, +# (M)ega, (G)iga, (T)era +# +# Since: 1.5 +## +{ 'enum': 'CommandLineParameterType', + 'data': ['string', 'boolean', 'number', 'size'] } + +## +# @CommandLineParameterInfo: +# +# Details about a single parameter of a command line option. +# +# @name: parameter name +# +# @type: parameter @CommandLineParameterType +# +# @help: human readable text string, not suitable for parsing. +# +# @default: default value string (since 2.1) +# +# Since: 1.5 +## +{ 'struct': 'CommandLineParameterInfo', + 'data': { 'name': 'str', + 'type': 'CommandLineParameterType', + '*help': 'str', + '*default': 'str' } } + +## +# @CommandLineOptionInfo: +# +# Details about a command line option, including its list of parameter details +# +# @option: option name +# +# @parameters: an array of @CommandLineParameterInfo +# +# Since: 1.5 +## +{ 'struct': 'CommandLineOptionInfo', + 'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } } + +## +# @query-command-line-options: +# +# Query command line option schema. +# +# @option: option name +# +# Returns: list of @CommandLineOptionInfo for all options (or for the given +# @option). Returns an error if the given @option doesn't exist. +# +# Since: 1.5 +# +# Example: +# +# -> { "execute": "query-command-line-options", +# "arguments": { "option": "option-rom" } } +# <- { "return": [ +# { +# "parameters": [ +# { +# "name": "romfile", +# "type": "string" +# }, +# { +# "name": "bootindex", +# "type": "number" +# } +# ], +# "option": "option-rom" +# } +# ] +# } +# +## +{'command': 'query-command-line-options', + 'data': { '*option': 'str' }, + 'returns': ['CommandLineOptionInfo'], + 'allow-preconfig': true } diff --git a/qapi/net.json b/qapi/net.json new file mode 100644 index 000000000..7fab2e7cd --- /dev/null +++ b/qapi/net.json @@ -0,0 +1,698 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Net devices +## + +{ 'include': 'common.json' } + +## +# @set_link: +# +# Sets the link status of a virtual network adapter. +# +# @name: the device name of the virtual network adapter +# +# @up: true to set the link status to be up +# +# Returns: Nothing on success +# If @name is not a valid network device, DeviceNotFound +# +# Since: 0.14 +# +# Notes: Not all network adapters support setting link status. This command +# will succeed even if the network adapter does not support link status +# notification. +# +# Example: +# +# -> { "execute": "set_link", +# "arguments": { "name": "e1000.0", "up": false } } +# <- { "return": {} } +# +## +{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} } + +## +# @netdev_add: +# +# Add a network backend. +# +# Additional arguments depend on the type. +# +# Since: 0.14 +# +# Returns: Nothing on success +# If @type is not a valid network backend, DeviceNotFound +# +# Example: +# +# -> { "execute": "netdev_add", +# "arguments": { "type": "user", "id": "netdev1", +# "dnssearch": "example.org" } } +# <- { "return": {} } +# +## +{ 'command': 'netdev_add', 'data': 'Netdev', 'boxed': true, + 'allow-preconfig': true } + +## +# @netdev_del: +# +# Remove a network backend. +# +# @id: the name of the network backend to remove +# +# Returns: Nothing on success +# If @id is not a valid network backend, DeviceNotFound +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "netdev_del", "arguments": { "id": "netdev1" } } +# <- { "return": {} } +# +## +{ 'command': 'netdev_del', 'data': {'id': 'str'}, + 'allow-preconfig': true } + +## +# @NetLegacyNicOptions: +# +# Create a new Network Interface Card. +# +# @netdev: id of -netdev to connect to +# +# @macaddr: MAC address +# +# @model: device model (e1000, rtl8139, virtio etc.) +# +# @addr: PCI device address +# +# @vectors: number of MSI-x vectors, 0 to disable MSI-X +# +# Since: 1.2 +## +{ 'struct': 'NetLegacyNicOptions', + 'data': { + '*netdev': 'str', + '*macaddr': 'str', + '*model': 'str', + '*addr': 'str', + '*vectors': 'uint32' } } + +## +# @NetdevUserOptions: +# +# Use the user mode network stack which requires no administrator privilege to +# run. +# +# @hostname: client hostname reported by the builtin DHCP server +# +# @restrict: isolate the guest from the host +# +# @ipv4: whether to support IPv4, default true for enabled +# (since 2.6) +# +# @ipv6: whether to support IPv6, default true for enabled +# (since 2.6) +# +# @ip: legacy parameter, use net= instead +# +# @net: IP network address that the guest will see, in the +# form addr[/netmask] The netmask is optional, and can be +# either in the form a.b.c.d or as a number of valid top-most +# bits. Default is 10.0.2.0/24. +# +# @host: guest-visible address of the host +# +# @tftp: root directory of the built-in TFTP server +# +# @bootfile: BOOTP filename, for use with tftp= +# +# @dhcpstart: the first of the 16 IPs the built-in DHCP server can +# assign +# +# @dns: guest-visible address of the virtual nameserver +# +# @dnssearch: list of DNS suffixes to search, passed as DHCP option +# to the guest +# +# @domainname: guest-visible domain name of the virtual nameserver +# (since 3.0) +# +# @ipv6-prefix: IPv6 network prefix (default is fec0::) (since +# 2.6). The network prefix is given in the usual +# hexadecimal IPv6 address notation. +# +# @ipv6-prefixlen: IPv6 network prefix length (default is 64) +# (since 2.6) +# +# @ipv6-host: guest-visible IPv6 address of the host (since 2.6) +# +# @ipv6-dns: guest-visible IPv6 address of the virtual +# nameserver (since 2.6) +# +# @smb: root directory of the built-in SMB server +# +# @smbserver: IP address of the built-in SMB server +# +# @hostfwd: redirect incoming TCP or UDP host connections to guest +# endpoints +# +# @guestfwd: forward guest TCP connections +# +# @tftp-server-name: RFC2132 "TFTP server name" string (Since 3.1) +# +# Since: 1.2 +## +{ 'struct': 'NetdevUserOptions', + 'data': { + '*hostname': 'str', + '*restrict': 'bool', + '*ipv4': 'bool', + '*ipv6': 'bool', + '*ip': 'str', + '*net': 'str', + '*host': 'str', + '*tftp': 'str', + '*bootfile': 'str', + '*dhcpstart': 'str', + '*dns': 'str', + '*dnssearch': ['String'], + '*domainname': 'str', + '*ipv6-prefix': 'str', + '*ipv6-prefixlen': 'int', + '*ipv6-host': 'str', + '*ipv6-dns': 'str', + '*smb': 'str', + '*smbserver': 'str', + '*hostfwd': ['String'], + '*guestfwd': ['String'], + '*tftp-server-name': 'str' } } + +## +# @NetdevTapOptions: +# +# Used to configure a host TAP network interface backend. +# +# @ifname: interface name +# +# @fd: file descriptor of an already opened tap +# +# @fds: multiple file descriptors of already opened multiqueue capable +# tap +# +# @script: script to initialize the interface +# +# @downscript: script to shut down the interface +# +# @br: bridge name (since 2.8) +# +# @helper: command to execute to configure bridge +# +# @sndbuf: send buffer limit. Understands [TGMKkb] suffixes. +# +# @vnet_hdr: enable the IFF_VNET_HDR flag on the tap interface +# +# @vhost: enable vhost-net network accelerator +# +# @vhostfd: file descriptor of an already opened vhost net device +# +# @vhostfds: file descriptors of multiple already opened vhost net +# devices +# +# @vhostforce: vhost on for non-MSIX virtio guests +# +# @queues: number of queues to be created for multiqueue capable tap +# +# @poll-us: maximum number of microseconds that could +# be spent on busy polling for tap (since 2.7) +# +# Since: 1.2 +## +{ 'struct': 'NetdevTapOptions', + 'data': { + '*ifname': 'str', + '*fd': 'str', + '*fds': 'str', + '*script': 'str', + '*downscript': 'str', + '*br': 'str', + '*helper': 'str', + '*sndbuf': 'size', + '*vnet_hdr': 'bool', + '*vhost': 'bool', + '*vhostfd': 'str', + '*vhostfds': 'str', + '*vhostforce': 'bool', + '*queues': 'uint32', + '*poll-us': 'uint32'} } + +## +# @NetdevSocketOptions: +# +# Socket netdevs are used to establish a network connection to another +# QEMU virtual machine via a TCP socket. +# +# @fd: file descriptor of an already opened socket +# +# @listen: port number, and optional hostname, to listen on +# +# @connect: port number, and optional hostname, to connect to +# +# @mcast: UDP multicast address and port number +# +# @localaddr: source address and port for multicast and udp packets +# +# @udp: UDP unicast address and port number +# +# Since: 1.2 +## +{ 'struct': 'NetdevSocketOptions', + 'data': { + '*fd': 'str', + '*listen': 'str', + '*connect': 'str', + '*mcast': 'str', + '*localaddr': 'str', + '*udp': 'str' } } + +## +# @NetdevL2TPv3Options: +# +# Configure an Ethernet over L2TPv3 tunnel. +# +# @src: source address +# +# @dst: destination address +# +# @srcport: source port - mandatory for udp, optional for ip +# +# @dstport: destination port - mandatory for udp, optional for ip +# +# @ipv6: force the use of ipv6 +# +# @udp: use the udp version of l2tpv3 encapsulation +# +# @cookie64: use 64 bit coookies +# +# @counter: have sequence counter +# +# @pincounter: pin sequence counter to zero - +# workaround for buggy implementations or +# networks with packet reorder +# +# @txcookie: 32 or 64 bit transmit cookie +# +# @rxcookie: 32 or 64 bit receive cookie +# +# @txsession: 32 bit transmit session +# +# @rxsession: 32 bit receive session - if not specified +# set to the same value as transmit +# +# @offset: additional offset - allows the insertion of +# additional application-specific data before the packet payload +# +# Since: 2.1 +## +{ 'struct': 'NetdevL2TPv3Options', + 'data': { + 'src': 'str', + 'dst': 'str', + '*srcport': 'str', + '*dstport': 'str', + '*ipv6': 'bool', + '*udp': 'bool', + '*cookie64': 'bool', + '*counter': 'bool', + '*pincounter': 'bool', + '*txcookie': 'uint64', + '*rxcookie': 'uint64', + 'txsession': 'uint32', + '*rxsession': 'uint32', + '*offset': 'uint32' } } + +## +# @NetdevVdeOptions: +# +# Connect to a vde switch running on the host. +# +# @sock: socket path +# +# @port: port number +# +# @group: group owner of socket +# +# @mode: permissions for socket +# +# Since: 1.2 +## +{ 'struct': 'NetdevVdeOptions', + 'data': { + '*sock': 'str', + '*port': 'uint16', + '*group': 'str', + '*mode': 'uint16' } } + +## +# @NetdevBridgeOptions: +# +# Connect a host TAP network interface to a host bridge device. +# +# @br: bridge name +# +# @helper: command to execute to configure bridge +# +# Since: 1.2 +## +{ 'struct': 'NetdevBridgeOptions', + 'data': { + '*br': 'str', + '*helper': 'str' } } + +## +# @NetdevHubPortOptions: +# +# Connect two or more net clients through a software hub. +# +# @hubid: hub identifier number +# @netdev: used to connect hub to a netdev instead of a device (since 2.12) +# +# Since: 1.2 +## +{ 'struct': 'NetdevHubPortOptions', + 'data': { + 'hubid': 'int32', + '*netdev': 'str' } } + +## +# @NetdevNetmapOptions: +# +# Connect a client to a netmap-enabled NIC or to a VALE switch port +# +# @ifname: Either the name of an existing network interface supported by +# netmap, or the name of a VALE port (created on the fly). +# A VALE port name is in the form 'valeXXX:YYY', where XXX and +# YYY are non-negative integers. XXX identifies a switch and +# YYY identifies a port of the switch. VALE ports having the +# same XXX are therefore connected to the same switch. +# +# @devname: path of the netmap device (default: '/dev/netmap'). +# +# Since: 2.0 +## +{ 'struct': 'NetdevNetmapOptions', + 'data': { + 'ifname': 'str', + '*devname': 'str' } } + +## +# @NetdevVhostUserOptions: +# +# Vhost-user network backend +# +# @chardev: name of a unix socket chardev +# +# @vhostforce: vhost on for non-MSIX virtio guests (default: false). +# +# @queues: number of queues to be created for multiqueue vhost-user +# (default: 1) (Since 2.5) +# +# Since: 2.1 +## +{ 'struct': 'NetdevVhostUserOptions', + 'data': { + 'chardev': 'str', + '*vhostforce': 'bool', + '*queues': 'int' } } + +## +# @NetdevVhostVDPAOptions: +# +# Vhost-vdpa network backend +# +# vDPA device is a device that uses a datapath which complies with the virtio +# specifications with a vendor specific control path. +# +# @vhostdev: path of vhost-vdpa device +# (default:'/dev/vhost-vdpa-0') +# +# @queues: number of queues to be created for multiqueue vhost-vdpa +# (default: 1) +# +# Since: 5.1 +## +{ 'struct': 'NetdevVhostVDPAOptions', + 'data': { + '*vhostdev': 'str', + '*queues': 'int' } } + +## +# @NetClientDriver: +# +# Available netdev drivers. +# +# Since: 2.7 +# +# @vhost-vdpa since 5.1 +## +{ 'enum': 'NetClientDriver', + 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', + 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] } + +## +# @Netdev: +# +# Captures the configuration of a network device. +# +# @id: identifier for monitor commands. +# +# @type: Specify the driver used for interpreting remaining arguments. +# +# Since: 1.2 +# +# 'l2tpv3' - since 2.1 +## +{ 'union': 'Netdev', + 'base': { 'id': 'str', 'type': 'NetClientDriver' }, + 'discriminator': 'type', + 'data': { + 'nic': 'NetLegacyNicOptions', + 'user': 'NetdevUserOptions', + 'tap': 'NetdevTapOptions', + 'l2tpv3': 'NetdevL2TPv3Options', + 'socket': 'NetdevSocketOptions', + 'vde': 'NetdevVdeOptions', + 'bridge': 'NetdevBridgeOptions', + 'hubport': 'NetdevHubPortOptions', + 'netmap': 'NetdevNetmapOptions', + 'vhost-user': 'NetdevVhostUserOptions', + 'vhost-vdpa': 'NetdevVhostVDPAOptions' } } + +## +# @RxState: +# +# Packets receiving state +# +# @normal: filter assigned packets according to the mac-table +# +# @none: don't receive any assigned packet +# +# @all: receive all assigned packets +# +# Since: 1.6 +## +{ 'enum': 'RxState', 'data': [ 'normal', 'none', 'all' ] } + +## +# @RxFilterInfo: +# +# Rx-filter information for a NIC. +# +# @name: net client name +# +# @promiscuous: whether promiscuous mode is enabled +# +# @multicast: multicast receive state +# +# @unicast: unicast receive state +# +# @vlan: vlan receive state (Since 2.0) +# +# @broadcast-allowed: whether to receive broadcast +# +# @multicast-overflow: multicast table is overflowed or not +# +# @unicast-overflow: unicast table is overflowed or not +# +# @main-mac: the main macaddr string +# +# @vlan-table: a list of active vlan id +# +# @unicast-table: a list of unicast macaddr string +# +# @multicast-table: a list of multicast macaddr string +# +# Since: 1.6 +## +{ 'struct': 'RxFilterInfo', + 'data': { + 'name': 'str', + 'promiscuous': 'bool', + 'multicast': 'RxState', + 'unicast': 'RxState', + 'vlan': 'RxState', + 'broadcast-allowed': 'bool', + 'multicast-overflow': 'bool', + 'unicast-overflow': 'bool', + 'main-mac': 'str', + 'vlan-table': ['int'], + 'unicast-table': ['str'], + 'multicast-table': ['str'] }} + +## +# @query-rx-filter: +# +# Return rx-filter information for all NICs (or for the given NIC). +# +# @name: net client name +# +# Returns: list of @RxFilterInfo for all NICs (or for the given NIC). +# Returns an error if the given @name doesn't exist, or given +# NIC doesn't support rx-filter querying, or given net client +# isn't a NIC. +# +# Since: 1.6 +# +# Example: +# +# -> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } } +# <- { "return": [ +# { +# "promiscuous": true, +# "name": "vnet0", +# "main-mac": "52:54:00:12:34:56", +# "unicast": "normal", +# "vlan": "normal", +# "vlan-table": [ +# 4, +# 0 +# ], +# "unicast-table": [ +# ], +# "multicast": "normal", +# "multicast-overflow": false, +# "unicast-overflow": false, +# "multicast-table": [ +# "01:00:5e:00:00:01", +# "33:33:00:00:00:01", +# "33:33:ff:12:34:56" +# ], +# "broadcast-allowed": false +# } +# ] +# } +# +## +{ 'command': 'query-rx-filter', + 'data': { '*name': 'str' }, + 'returns': ['RxFilterInfo'] } + +## +# @NIC_RX_FILTER_CHANGED: +# +# Emitted once until the 'query-rx-filter' command is executed, the first event +# will always be emitted +# +# @name: net client name +# +# @path: device path +# +# Since: 1.6 +# +# Example: +# +# <- { "event": "NIC_RX_FILTER_CHANGED", +# "data": { "name": "vnet0", +# "path": "/machine/peripheral/vnet0/virtio-backend" }, +# "timestamp": { "seconds": 1368697518, "microseconds": 326866 } } +# } +# +## +{ 'event': 'NIC_RX_FILTER_CHANGED', + 'data': { '*name': 'str', 'path': 'str' } } + +## +# @AnnounceParameters: +# +# Parameters for self-announce timers +# +# @initial: Initial delay (in ms) before sending the first GARP/RARP +# announcement +# +# @max: Maximum delay (in ms) between GARP/RARP announcement packets +# +# @rounds: Number of self-announcement attempts +# +# @step: Delay increase (in ms) after each self-announcement attempt +# +# @interfaces: An optional list of interface names, which restricts the +# announcement to the listed interfaces. (Since 4.1) +# +# @id: A name to be used to identify an instance of announce-timers +# and to allow it to modified later. Not for use as +# part of the migration parameters. (Since 4.1) +# +# Since: 4.0 +## + +{ 'struct': 'AnnounceParameters', + 'data': { 'initial': 'int', + 'max': 'int', + 'rounds': 'int', + 'step': 'int', + '*interfaces': ['str'], + '*id' : 'str' } } + +## +# @announce-self: +# +# Trigger generation of broadcast RARP frames to update network switches. +# This can be useful when network bonds fail-over the active slave. +# +# Example: +# +# -> { "execute": "announce-self", +# "arguments": { +# "initial": 50, "max": 550, "rounds": 10, "step": 50, +# "interfaces": ["vn2", "vn3"], "id": "bob" } } +# <- { "return": {} } +# +# Since: 4.0 +## +{ 'command': 'announce-self', 'boxed': true, + 'data' : 'AnnounceParameters'} + +## +# @FAILOVER_NEGOTIATED: +# +# Emitted when VIRTIO_NET_F_STANDBY was enabled during feature negotiation. +# Failover primary devices which were hidden (not hotplugged when requested) +# before will now be hotplugged by the virtio-net standby device. +# +# device-id: QEMU device id of the unplugged device +# Since: 4.2 +# +# Example: +# +# <- { "event": "FAILOVER_NEGOTIATED", +# "data": "net1" } +# +## +{ 'event': 'FAILOVER_NEGOTIATED', + 'data': {'device-id': 'str'} } diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c new file mode 100644 index 000000000..587f31baf --- /dev/null +++ b/qapi/opts-visitor.c @@ -0,0 +1,586 @@ +/* + * Options Visitor + * + * Copyright Red Hat, Inc. 2012-2016 + * + * Author: Laszlo Ersek <lersek@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/cutils.h" +#include "qapi/qmp/qerror.h" +#include "qapi/opts-visitor.h" +#include "qemu/queue.h" +#include "qemu/option_int.h" +#include "qapi/visitor-impl.h" + + +enum ListMode +{ + LM_NONE, /* not traversing a list of repeated options */ + + LM_IN_PROGRESS, /* + * opts_next_list() ready to be called. + * + * Generating the next list link will consume the most + * recently parsed QemuOpt instance of the repeated + * option. + * + * Parsing a value into the list link will examine the + * next QemuOpt instance of the repeated option, and + * possibly enter LM_SIGNED_INTERVAL or + * LM_UNSIGNED_INTERVAL. + */ + + LM_SIGNED_INTERVAL, /* + * opts_next_list() has been called. + * + * Generating the next list link will consume the most + * recently stored element from the signed interval, + * parsed from the most recent QemuOpt instance of the + * repeated option. This may consume QemuOpt itself + * and return to LM_IN_PROGRESS. + * + * Parsing a value into the list link will store the + * next element of the signed interval. + */ + + LM_UNSIGNED_INTERVAL, /* Same as above, only for an unsigned interval. */ + + LM_TRAVERSED /* + * opts_next_list() has been called. + * + * No more QemuOpt instance in the list. + * The traversal has been completed. + */ +}; + +typedef enum ListMode ListMode; + +struct OptsVisitor +{ + Visitor visitor; + + /* Ownership remains with opts_visitor_new()'s caller. */ + const QemuOpts *opts_root; + + unsigned depth; + + /* Non-null iff depth is positive. Each key is a QemuOpt name. Each value + * is a non-empty GQueue, enumerating all QemuOpt occurrences with that + * name. */ + GHashTable *unprocessed_opts; + + /* The list currently being traversed with opts_start_list() / + * opts_next_list(). The list must have a struct element type in the + * schema, with a single mandatory scalar member. */ + ListMode list_mode; + GQueue *repeated_opts; + + /* When parsing a list of repeating options as integers, values of the form + * "a-b", representing a closed interval, are allowed. Elements in the + * range are generated individually. + */ + union { + int64_t s; + uint64_t u; + } range_next, range_limit; + + /* If "opts_root->id" is set, reinstantiate it as a fake QemuOpt for + * uniformity. Only its "name" and "str" fields are set. "fake_id_opt" does + * not survive or escape the OptsVisitor object. + */ + QemuOpt *fake_id_opt; +}; + + +static OptsVisitor *to_ov(Visitor *v) +{ + return container_of(v, OptsVisitor, visitor); +} + + +static void +destroy_list(gpointer list) +{ + g_queue_free(list); +} + + +static void +opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) +{ + GQueue *list; + + list = g_hash_table_lookup(unprocessed_opts, opt->name); + if (list == NULL) { + list = g_queue_new(); + + /* GHashTable will never try to free the keys -- we supply NULL as + * "key_destroy_func" in opts_start_struct(). Thus cast away key + * const-ness in order to suppress gcc's warning. + */ + g_hash_table_insert(unprocessed_opts, (gpointer)opt->name, list); + } + + /* Similarly, destroy_list() doesn't call g_queue_free_full(). */ + g_queue_push_tail(list, (gpointer)opt); +} + + +static bool +opts_start_struct(Visitor *v, const char *name, void **obj, + size_t size, Error **errp) +{ + OptsVisitor *ov = to_ov(v); + const QemuOpt *opt; + + if (obj) { + *obj = g_malloc0(size); + } + if (ov->depth++ > 0) { + return true; + } + + ov->unprocessed_opts = g_hash_table_new_full(&g_str_hash, &g_str_equal, + NULL, &destroy_list); + QTAILQ_FOREACH(opt, &ov->opts_root->head, next) { + /* ensured by qemu-option.c::opts_do_parse() */ + assert(strcmp(opt->name, "id") != 0); + + opts_visitor_insert(ov->unprocessed_opts, opt); + } + + if (ov->opts_root->id != NULL) { + ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt); + + ov->fake_id_opt->name = g_strdup("id"); + ov->fake_id_opt->str = g_strdup(ov->opts_root->id); + opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt); + } + return true; +} + + +static bool +opts_check_struct(Visitor *v, Error **errp) +{ + OptsVisitor *ov = to_ov(v); + GHashTableIter iter; + GQueue *any; + + if (ov->depth > 1) { + return true; + } + + /* we should have processed all (distinct) QemuOpt instances */ + g_hash_table_iter_init(&iter, ov->unprocessed_opts); + if (g_hash_table_iter_next(&iter, NULL, (void **)&any)) { + const QemuOpt *first; + + first = g_queue_peek_head(any); + error_setg(errp, QERR_INVALID_PARAMETER, first->name); + return false; + } + return true; +} + + +static void +opts_end_struct(Visitor *v, void **obj) +{ + OptsVisitor *ov = to_ov(v); + + if (--ov->depth > 0) { + return; + } + + g_hash_table_destroy(ov->unprocessed_opts); + ov->unprocessed_opts = NULL; + if (ov->fake_id_opt) { + g_free(ov->fake_id_opt->name); + g_free(ov->fake_id_opt->str); + g_free(ov->fake_id_opt); + } + ov->fake_id_opt = NULL; +} + + +static GQueue * +lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) +{ + GQueue *list; + + list = g_hash_table_lookup(ov->unprocessed_opts, name); + if (!list) { + error_setg(errp, QERR_MISSING_PARAMETER, name); + } + return list; +} + + +static bool +opts_start_list(Visitor *v, const char *name, GenericList **list, size_t size, + Error **errp) +{ + OptsVisitor *ov = to_ov(v); + + /* we can't traverse a list in a list */ + assert(ov->list_mode == LM_NONE); + /* we don't support visits without a list */ + assert(list); + ov->repeated_opts = lookup_distinct(ov, name, errp); + if (!ov->repeated_opts) { + *list = NULL; + return false; + } + ov->list_mode = LM_IN_PROGRESS; + *list = g_malloc0(size); + return true; +} + + +static GenericList * +opts_next_list(Visitor *v, GenericList *tail, size_t size) +{ + OptsVisitor *ov = to_ov(v); + + switch (ov->list_mode) { + case LM_TRAVERSED: + return NULL; + case LM_SIGNED_INTERVAL: + case LM_UNSIGNED_INTERVAL: + if (ov->list_mode == LM_SIGNED_INTERVAL) { + if (ov->range_next.s < ov->range_limit.s) { + ++ov->range_next.s; + break; + } + } else if (ov->range_next.u < ov->range_limit.u) { + ++ov->range_next.u; + break; + } + ov->list_mode = LM_IN_PROGRESS; + /* range has been completed, fall through in order to pop option */ + + case LM_IN_PROGRESS: { + const QemuOpt *opt; + + opt = g_queue_pop_head(ov->repeated_opts); + if (g_queue_is_empty(ov->repeated_opts)) { + g_hash_table_remove(ov->unprocessed_opts, opt->name); + ov->repeated_opts = NULL; + ov->list_mode = LM_TRAVERSED; + return NULL; + } + break; + } + + default: + abort(); + } + + tail->next = g_malloc0(size); + return tail->next; +} + + +static bool +opts_check_list(Visitor *v, Error **errp) +{ + /* + * Unvisited list elements will be reported later when checking + * whether unvisited struct members remain. + */ + return true; +} + + +static void +opts_end_list(Visitor *v, void **obj) +{ + OptsVisitor *ov = to_ov(v); + + assert(ov->list_mode == LM_IN_PROGRESS || + ov->list_mode == LM_SIGNED_INTERVAL || + ov->list_mode == LM_UNSIGNED_INTERVAL || + ov->list_mode == LM_TRAVERSED); + ov->repeated_opts = NULL; + ov->list_mode = LM_NONE; +} + + +static const QemuOpt * +lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp) +{ + if (ov->list_mode == LM_NONE) { + GQueue *list; + + /* the last occurrence of any QemuOpt takes effect when queried by name + */ + list = lookup_distinct(ov, name, errp); + return list ? g_queue_peek_tail(list) : NULL; + } + if (ov->list_mode == LM_TRAVERSED) { + error_setg(errp, "Fewer list elements than expected"); + return NULL; + } + assert(ov->list_mode == LM_IN_PROGRESS); + return g_queue_peek_head(ov->repeated_opts); +} + + +static void +processed(OptsVisitor *ov, const char *name) +{ + if (ov->list_mode == LM_NONE) { + g_hash_table_remove(ov->unprocessed_opts, name); + return; + } + assert(ov->list_mode == LM_IN_PROGRESS); + /* do nothing */ +} + + +static bool +opts_type_str(Visitor *v, const char *name, char **obj, Error **errp) +{ + OptsVisitor *ov = to_ov(v); + const QemuOpt *opt; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + *obj = NULL; + return false; + } + *obj = g_strdup(opt->str ? opt->str : ""); + /* Note that we consume a string even if this is called as part of + * an enum visit that later fails because the string is not a + * valid enum value; this is harmless because tracking what gets + * consumed only matters to visit_end_struct() as the final error + * check if there were no other failures during the visit. */ + processed(ov, name); + return true; +} + + +static bool +opts_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) +{ + OptsVisitor *ov = to_ov(v); + const QemuOpt *opt; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return false; + } + if (opt->str) { + if (!qapi_bool_parse(opt->name, opt->str, obj, errp)) { + return false; + } + } else { + *obj = true; + } + + processed(ov, name); + return true; +} + + +static bool +opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) +{ + OptsVisitor *ov = to_ov(v); + const QemuOpt *opt; + const char *str; + long long val; + char *endptr; + + if (ov->list_mode == LM_SIGNED_INTERVAL) { + *obj = ov->range_next.s; + return true; + } + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return false; + } + str = opt->str ? opt->str : ""; + + /* we've gotten past lookup_scalar() */ + assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS); + + errno = 0; + val = strtoll(str, &endptr, 0); + if (errno == 0 && endptr > str && INT64_MIN <= val && val <= INT64_MAX) { + if (*endptr == '\0') { + *obj = val; + processed(ov, name); + return true; + } + if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) { + long long val2; + + str = endptr + 1; + val2 = strtoll(str, &endptr, 0); + if (errno == 0 && endptr > str && *endptr == '\0' && + INT64_MIN <= val2 && val2 <= INT64_MAX && val <= val2 && + (val > INT64_MAX - OPTS_VISITOR_RANGE_MAX || + val2 < val + OPTS_VISITOR_RANGE_MAX)) { + ov->range_next.s = val; + ov->range_limit.s = val2; + ov->list_mode = LM_SIGNED_INTERVAL; + + /* as if entering on the top */ + *obj = ov->range_next.s; + return true; + } + } + } + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, + (ov->list_mode == LM_NONE) ? "an int64 value" : + "an int64 value or range"); + return false; +} + + +static bool +opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) +{ + OptsVisitor *ov = to_ov(v); + const QemuOpt *opt; + const char *str; + unsigned long long val; + char *endptr; + + if (ov->list_mode == LM_UNSIGNED_INTERVAL) { + *obj = ov->range_next.u; + return true; + } + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return false; + } + str = opt->str; + + /* we've gotten past lookup_scalar() */ + assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS); + + if (parse_uint(str, &val, &endptr, 0) == 0 && val <= UINT64_MAX) { + if (*endptr == '\0') { + *obj = val; + processed(ov, name); + return true; + } + if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) { + unsigned long long val2; + + str = endptr + 1; + if (parse_uint_full(str, &val2, 0) == 0 && + val2 <= UINT64_MAX && val <= val2 && + val2 - val < OPTS_VISITOR_RANGE_MAX) { + ov->range_next.u = val; + ov->range_limit.u = val2; + ov->list_mode = LM_UNSIGNED_INTERVAL; + + /* as if entering on the top */ + *obj = ov->range_next.u; + return true; + } + } + } + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, + (ov->list_mode == LM_NONE) ? "a uint64 value" : + "a uint64 value or range"); + return false; +} + + +static bool +opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp) +{ + OptsVisitor *ov = to_ov(v); + const QemuOpt *opt; + int err; + + opt = lookup_scalar(ov, name, errp); + if (!opt) { + return false; + } + + err = qemu_strtosz(opt->str ? opt->str : "", NULL, obj); + if (err < 0) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, + "a size value"); + return false; + } + + processed(ov, name); + return true; +} + + +static void +opts_optional(Visitor *v, const char *name, bool *present) +{ + OptsVisitor *ov = to_ov(v); + + /* we only support a single mandatory scalar field in a list node */ + assert(ov->list_mode == LM_NONE); + *present = (lookup_distinct(ov, name, NULL) != NULL); +} + + +static void +opts_free(Visitor *v) +{ + OptsVisitor *ov = to_ov(v); + + if (ov->unprocessed_opts != NULL) { + g_hash_table_destroy(ov->unprocessed_opts); + } + g_free(ov->fake_id_opt); + g_free(ov); +} + + +Visitor * +opts_visitor_new(const QemuOpts *opts) +{ + OptsVisitor *ov; + + assert(opts); + ov = g_malloc0(sizeof *ov); + + ov->visitor.type = VISITOR_INPUT; + + ov->visitor.start_struct = &opts_start_struct; + ov->visitor.check_struct = &opts_check_struct; + ov->visitor.end_struct = &opts_end_struct; + + ov->visitor.start_list = &opts_start_list; + ov->visitor.next_list = &opts_next_list; + ov->visitor.check_list = &opts_check_list; + ov->visitor.end_list = &opts_end_list; + + ov->visitor.type_int64 = &opts_type_int64; + ov->visitor.type_uint64 = &opts_type_uint64; + ov->visitor.type_size = &opts_type_size; + ov->visitor.type_bool = &opts_type_bool; + ov->visitor.type_str = &opts_type_str; + + /* type_number() is not filled in, but this is not the first visitor to + * skip some mandatory methods... */ + + ov->visitor.optional = &opts_optional; + ov->visitor.free = opts_free; + + ov->opts_root = opts; + + return &ov->visitor; +} diff --git a/qapi/pci.json b/qapi/pci.json new file mode 100644 index 000000000..ee7c659fe --- /dev/null +++ b/qapi/pci.json @@ -0,0 +1,316 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# SPDX-License-Identifier: GPL-2.0-or-later + +## +# = PCI +## + +## +# @PciMemoryRange: +# +# A PCI device memory region +# +# @base: the starting address (guest physical) +# +# @limit: the ending address (guest physical) +# +# Since: 0.14 +## +{ 'struct': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} } + +## +# @PciMemoryRegion: +# +# Information about a PCI device I/O region. +# +# @bar: the index of the Base Address Register for this region +# +# @type: - 'io' if the region is a PIO region +# - 'memory' if the region is a MMIO region +# +# @size: memory size +# +# @prefetch: if @type is 'memory', true if the memory is prefetchable +# +# @mem_type_64: if @type is 'memory', true if the BAR is 64-bit +# +# Since: 0.14 +## +{ 'struct': 'PciMemoryRegion', + 'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int', + '*prefetch': 'bool', '*mem_type_64': 'bool' } } + +## +# @PciBusInfo: +# +# Information about a bus of a PCI Bridge device +# +# @number: primary bus interface number. This should be the number of the +# bus the device resides on. +# +# @secondary: secondary bus interface number. This is the number of the +# main bus for the bridge +# +# @subordinate: This is the highest number bus that resides below the +# bridge. +# +# @io_range: The PIO range for all devices on this bridge +# +# @memory_range: The MMIO range for all devices on this bridge +# +# @prefetchable_range: The range of prefetchable MMIO for all devices on +# this bridge +# +# Since: 2.4 +## +{ 'struct': 'PciBusInfo', + 'data': {'number': 'int', 'secondary': 'int', 'subordinate': 'int', + 'io_range': 'PciMemoryRange', + 'memory_range': 'PciMemoryRange', + 'prefetchable_range': 'PciMemoryRange' } } + +## +# @PciBridgeInfo: +# +# Information about a PCI Bridge device +# +# @bus: information about the bus the device resides on +# +# @devices: a list of @PciDeviceInfo for each device on this bridge +# +# Since: 0.14 +## +{ 'struct': 'PciBridgeInfo', + 'data': {'bus': 'PciBusInfo', '*devices': ['PciDeviceInfo']} } + +## +# @PciDeviceClass: +# +# Information about the Class of a PCI device +# +# @desc: a string description of the device's class +# +# @class: the class code of the device +# +# Since: 2.4 +## +{ 'struct': 'PciDeviceClass', + 'data': {'*desc': 'str', 'class': 'int'} } + +## +# @PciDeviceId: +# +# Information about the Id of a PCI device +# +# @device: the PCI device id +# +# @vendor: the PCI vendor id +# +# @subsystem: the PCI subsystem id (since 3.1) +# +# @subsystem-vendor: the PCI subsystem vendor id (since 3.1) +# +# Since: 2.4 +## +{ 'struct': 'PciDeviceId', + 'data': {'device': 'int', 'vendor': 'int', '*subsystem': 'int', + '*subsystem-vendor': 'int'} } + +## +# @PciDeviceInfo: +# +# Information about a PCI device +# +# @bus: the bus number of the device +# +# @slot: the slot the device is located in +# +# @function: the function of the slot used by the device +# +# @class_info: the class of the device +# +# @id: the PCI device id +# +# @irq: if an IRQ is assigned to the device, the IRQ number +# +# @irq_pin: the IRQ pin, zero means no IRQ (since 5.1) +# +# @qdev_id: the device name of the PCI device +# +# @pci_bridge: if the device is a PCI bridge, the bridge information +# +# @regions: a list of the PCI I/O regions associated with the device +# +# Notes: the contents of @class_info.desc are not stable and should only be +# treated as informational. +# +# Since: 0.14 +## +{ 'struct': 'PciDeviceInfo', + 'data': {'bus': 'int', 'slot': 'int', 'function': 'int', + 'class_info': 'PciDeviceClass', 'id': 'PciDeviceId', + '*irq': 'int', 'irq_pin': 'int', 'qdev_id': 'str', + '*pci_bridge': 'PciBridgeInfo', 'regions': ['PciMemoryRegion'] }} + +## +# @PciInfo: +# +# Information about a PCI bus +# +# @bus: the bus index +# +# @devices: a list of devices on this bus +# +# Since: 0.14 +## +{ 'struct': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} } + +## +# @query-pci: +# +# Return information about the PCI bus topology of the guest. +# +# Returns: a list of @PciInfo for each PCI bus. Each bus is +# represented by a json-object, which has a key with a json-array of +# all PCI devices attached to it. Each device is represented by a +# json-object. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-pci" } +# <- { "return": [ +# { +# "bus": 0, +# "devices": [ +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 0, +# "class_info": { +# "class": 1536, +# "desc": "Host bridge" +# }, +# "id": { +# "device": 32902, +# "vendor": 4663 +# }, +# "function": 0, +# "regions": [ +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 1, +# "class_info": { +# "class": 1537, +# "desc": "ISA bridge" +# }, +# "id": { +# "device": 32902, +# "vendor": 28672 +# }, +# "function": 0, +# "regions": [ +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 1, +# "class_info": { +# "class": 257, +# "desc": "IDE controller" +# }, +# "id": { +# "device": 32902, +# "vendor": 28688 +# }, +# "function": 1, +# "regions": [ +# { +# "bar": 4, +# "size": 16, +# "address": 49152, +# "type": "io" +# } +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "slot": 2, +# "class_info": { +# "class": 768, +# "desc": "VGA controller" +# }, +# "id": { +# "device": 4115, +# "vendor": 184 +# }, +# "function": 0, +# "regions": [ +# { +# "prefetch": true, +# "mem_type_64": false, +# "bar": 0, +# "size": 33554432, +# "address": 4026531840, +# "type": "memory" +# }, +# { +# "prefetch": false, +# "mem_type_64": false, +# "bar": 1, +# "size": 4096, +# "address": 4060086272, +# "type": "memory" +# }, +# { +# "prefetch": false, +# "mem_type_64": false, +# "bar": 6, +# "size": 65536, +# "address": -1, +# "type": "memory" +# } +# ] +# }, +# { +# "bus": 0, +# "qdev_id": "", +# "irq": 11, +# "slot": 4, +# "class_info": { +# "class": 1280, +# "desc": "RAM controller" +# }, +# "id": { +# "device": 6900, +# "vendor": 4098 +# }, +# "function": 0, +# "regions": [ +# { +# "bar": 0, +# "size": 32, +# "address": 49280, +# "type": "io" +# } +# ] +# } +# ] +# } +# ] +# } +# +# Note: This example has been shortened as the real response is too long. +# +## +{ 'command': 'query-pci', 'returns': ['PciInfo'] } diff --git a/qapi/pragma.json b/qapi/pragma.json new file mode 100644 index 000000000..3bc0335d1 --- /dev/null +++ b/qapi/pragma.json @@ -0,0 +1,64 @@ +{ 'pragma': { 'doc-required': true } } + +# Whitelists to permit QAPI rule violations; think twice before you +# add to them! +{ 'pragma': { + # Commands allowed to return a non-dictionary: + 'command-name-exceptions': [ + 'add_client', + 'block_resize', + 'block_set_io_throttle', + 'client_migrate_info', + 'device_add', + 'device_del', + 'expire_password', + 'migrate_cancel', + 'netdev_add', + 'netdev_del', + 'qmp_capabilities', + 'set_link', + 'set_password', + 'system_powerdown', + 'system_reset', + 'system_wakeup' ], + 'command-returns-exceptions': [ + 'human-monitor-command', + 'qom-get', + 'query-tpm-models', + 'query-tpm-types', + 'ringbuf-read' ], + # Externally visible types whose member names may use uppercase + 'member-name-exceptions': [ # visible in: + 'ACPISlotType', # query-acpi-ospm-status + 'AcpiTableOptions', # -acpitable + 'BlkdebugEvent', # blockdev-add, -blockdev + 'BlkdebugSetStateOptions', # blockdev-add, -blockdev + 'BlockDeviceInfo', # query-block + 'BlockDeviceStats', # query-blockstats + 'BlockDeviceTimedStats', # query-blockstats + 'BlockIOThrottle', # block_set_io_throttle + 'BlockInfo', # query-block + 'BlockdevAioOptions', # blockdev-add, -blockdev + 'BlockdevDriver', # blockdev-add, query-blockstats, ... + 'BlockdevVmdkAdapterType', # blockdev-create (to match VMDK spec) + 'BlockdevVmdkSubformat', # blockdev-create (to match VMDK spec) + 'ColoCompareProperties', # object_add, -object + 'FilterMirrorProperties', # object_add, -object + 'FilterRedirectorProperties', # object_add, -object + 'FilterRewriterProperties', # object_add, -object + 'InputLinuxProperties', # object_add, -object + 'NetdevTapOptions', # netdev_add, query-netdev, -netdev + 'ObjectType', # object-add, -object + 'PCIELinkSpeed', # internal only + 'PciBusInfo', # query-pci + 'PciDeviceInfo', # query-pci + 'PciMemoryRegion', # query-pci + 'QKeyCode', # send-key, input-sent-event + 'QapiErrorClass', # QMP error replies + 'SshHostKeyCheckMode', # blockdev-add, -blockdev + 'SysEmuTarget', # query-cpu-fast, query-target + 'UuidInfo', # query-uuid + 'VncClientInfo', # query-vnc, query-vnc-servers, ... + 'X86CPURegister32' # qom-get of x86 CPU properties + # feature-words, filtered-features + ] } } diff --git a/qapi/qapi-clone-visitor.c b/qapi/qapi-clone-visitor.c new file mode 100644 index 000000000..c45c5caa3 --- /dev/null +++ b/qapi/qapi-clone-visitor.c @@ -0,0 +1,204 @@ +/* + * Copy one QAPI object to another + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/clone-visitor.h" +#include "qapi/visitor-impl.h" +#include "qapi/error.h" +#include "qapi/qmp/qnull.h" + +struct QapiCloneVisitor { + Visitor visitor; + size_t depth; +}; + +static QapiCloneVisitor *to_qcv(Visitor *v) +{ + return container_of(v, QapiCloneVisitor, visitor); +} + +static bool qapi_clone_start_struct(Visitor *v, const char *name, void **obj, + size_t size, Error **errp) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + if (!obj) { + assert(qcv->depth); + /* Only possible when visiting an alternate's object + * branch. Nothing further to do here, since the earlier + * visit_start_alternate() already copied memory. */ + return true; + } + + *obj = g_memdup(*obj, size); + qcv->depth++; + return true; +} + +static void qapi_clone_end(Visitor *v, void **obj) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + if (obj) { + qcv->depth--; + } +} + +static bool qapi_clone_start_list(Visitor *v, const char *name, + GenericList **listp, size_t size, + Error **errp) +{ + return qapi_clone_start_struct(v, name, (void **)listp, size, errp); +} + +static GenericList *qapi_clone_next_list(Visitor *v, GenericList *tail, + size_t size) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + /* Unshare the tail of the list cloned by g_memdup() */ + tail->next = g_memdup(tail->next, size); + return tail->next; +} + +static bool qapi_clone_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + Error **errp) +{ + return qapi_clone_start_struct(v, name, (void **)obj, size, errp); +} + +static bool qapi_clone_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + /* Value was already cloned by g_memdup() */ + return true; +} + +static bool qapi_clone_type_uint64(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + /* Value was already cloned by g_memdup() */ + return true; +} + +static bool qapi_clone_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + /* Value was already cloned by g_memdup() */ + return true; +} + +static bool qapi_clone_type_str(Visitor *v, const char *name, char **obj, + Error **errp) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + /* + * Pointer was already cloned by g_memdup; create fresh copy. + * Note that as long as qobject-output-visitor accepts NULL instead of + * "", then we must do likewise. However, we want to obey the + * input visitor semantics of never producing NULL when the empty + * string is intended. + */ + *obj = g_strdup(*obj ?: ""); + return true; +} + +static bool qapi_clone_type_number(Visitor *v, const char *name, double *obj, + Error **errp) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + /* Value was already cloned by g_memdup() */ + return true; +} + +static bool qapi_clone_type_null(Visitor *v, const char *name, QNull **obj, + Error **errp) +{ + QapiCloneVisitor *qcv = to_qcv(v); + + assert(qcv->depth); + *obj = qnull(); + return true; +} + +static void qapi_clone_free(Visitor *v) +{ + g_free(v); +} + +static Visitor *qapi_clone_visitor_new(void) +{ + QapiCloneVisitor *v; + + v = g_malloc0(sizeof(*v)); + + v->visitor.type = VISITOR_CLONE; + v->visitor.start_struct = qapi_clone_start_struct; + v->visitor.end_struct = qapi_clone_end; + v->visitor.start_list = qapi_clone_start_list; + v->visitor.next_list = qapi_clone_next_list; + v->visitor.end_list = qapi_clone_end; + v->visitor.start_alternate = qapi_clone_start_alternate; + v->visitor.end_alternate = qapi_clone_end; + v->visitor.type_int64 = qapi_clone_type_int64; + v->visitor.type_uint64 = qapi_clone_type_uint64; + v->visitor.type_bool = qapi_clone_type_bool; + v->visitor.type_str = qapi_clone_type_str; + v->visitor.type_number = qapi_clone_type_number; + v->visitor.type_null = qapi_clone_type_null; + v->visitor.free = qapi_clone_free; + + return &v->visitor; +} + +void *qapi_clone(const void *src, bool (*visit_type)(Visitor *, const char *, + void **, Error **)) +{ + Visitor *v; + void *dst = (void *) src; /* Cast away const */ + + if (!src) { + return NULL; + } + + v = qapi_clone_visitor_new(); + visit_type(v, NULL, &dst, &error_abort); + visit_free(v); + return dst; +} + +void qapi_clone_members(void *dst, const void *src, size_t sz, + bool (*visit_type_members)(Visitor *, void *, + Error **)) +{ + Visitor *v; + + v = qapi_clone_visitor_new(); + memcpy(dst, src, sz); + to_qcv(v)->depth++; + visit_type_members(v, dst, &error_abort); + visit_free(v); +} diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c new file mode 100644 index 000000000..ef283f296 --- /dev/null +++ b/qapi/qapi-dealloc-visitor.c @@ -0,0 +1,143 @@ +/* + * Dealloc Visitor + * + * Copyright (C) 2012-2016 Red Hat, Inc. + * Copyright IBM, Corp. 2011 + * + * Authors: + * Michael Roth <mdroth@linux.vnet.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/dealloc-visitor.h" +#include "qapi/qmp/qnull.h" +#include "qapi/visitor-impl.h" + +struct QapiDeallocVisitor +{ + Visitor visitor; +}; + +static bool qapi_dealloc_start_struct(Visitor *v, const char *name, void **obj, + size_t unused, Error **errp) +{ + return true; +} + +static void qapi_dealloc_end_struct(Visitor *v, void **obj) +{ + if (obj) { + g_free(*obj); + } +} + +static void qapi_dealloc_end_alternate(Visitor *v, void **obj) +{ + if (obj) { + g_free(*obj); + } +} + +static bool qapi_dealloc_start_list(Visitor *v, const char *name, + GenericList **list, size_t size, + Error **errp) +{ + return true; +} + +static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList *tail, + size_t size) +{ + GenericList *next = tail->next; + g_free(tail); + return next; +} + +static void qapi_dealloc_end_list(Visitor *v, void **obj) +{ +} + +static bool qapi_dealloc_type_str(Visitor *v, const char *name, char **obj, + Error **errp) +{ + if (obj) { + g_free(*obj); + } + return true; +} + +static bool qapi_dealloc_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) +{ + return true; +} + +static bool qapi_dealloc_type_uint64(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + return true; +} + +static bool qapi_dealloc_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) +{ + return true; +} + +static bool qapi_dealloc_type_number(Visitor *v, const char *name, double *obj, + Error **errp) +{ + return true; +} + +static bool qapi_dealloc_type_anything(Visitor *v, const char *name, + QObject **obj, Error **errp) +{ + if (obj) { + qobject_unref(*obj); + } + return true; +} + +static bool qapi_dealloc_type_null(Visitor *v, const char *name, + QNull **obj, Error **errp) +{ + if (obj) { + qobject_unref(*obj); + } + return true; +} + +static void qapi_dealloc_free(Visitor *v) +{ + g_free(container_of(v, QapiDeallocVisitor, visitor)); +} + +Visitor *qapi_dealloc_visitor_new(void) +{ + QapiDeallocVisitor *v; + + v = g_malloc0(sizeof(*v)); + + v->visitor.type = VISITOR_DEALLOC; + v->visitor.start_struct = qapi_dealloc_start_struct; + v->visitor.end_struct = qapi_dealloc_end_struct; + v->visitor.end_alternate = qapi_dealloc_end_alternate; + v->visitor.start_list = qapi_dealloc_start_list; + v->visitor.next_list = qapi_dealloc_next_list; + v->visitor.end_list = qapi_dealloc_end_list; + v->visitor.type_int64 = qapi_dealloc_type_int64; + v->visitor.type_uint64 = qapi_dealloc_type_uint64; + v->visitor.type_bool = qapi_dealloc_type_bool; + v->visitor.type_str = qapi_dealloc_type_str; + v->visitor.type_number = qapi_dealloc_type_number; + v->visitor.type_any = qapi_dealloc_type_anything; + v->visitor.type_null = qapi_dealloc_type_null; + v->visitor.free = qapi_dealloc_free; + + return &v->visitor; +} diff --git a/qapi/qapi-forward-visitor.c b/qapi/qapi-forward-visitor.c new file mode 100644 index 000000000..4ea7e0bec --- /dev/null +++ b/qapi/qapi-forward-visitor.c @@ -0,0 +1,328 @@ +/* + * Forward Visitor + * + * Copyright (C) 2021 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/compat-policy.h" +#include "qapi/error.h" +#include "qapi/forward-visitor.h" +#include "qapi/visitor-impl.h" +#include "qemu/queue.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnull.h" +#include "qapi/qmp/qnum.h" +#include "qapi/qmp/qstring.h" +#include "qemu/cutils.h" +#include "qemu/option.h" + +struct ForwardFieldVisitor { + Visitor visitor; + + Visitor *target; + char *from; + char *to; + + int depth; +}; + +static ForwardFieldVisitor *to_ffv(Visitor *v) +{ + return container_of(v, ForwardFieldVisitor, visitor); +} + +static bool forward_field_translate_name(ForwardFieldVisitor *v, const char **name, + Error **errp) +{ + if (v->depth) { + return true; + } + if (g_str_equal(*name, v->from)) { + *name = v->to; + return true; + } + error_setg(errp, QERR_MISSING_PARAMETER, *name); + return false; +} + +static bool forward_field_check_struct(Visitor *v, Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + return visit_check_struct(ffv->target, errp); +} + +static bool forward_field_start_struct(Visitor *v, const char *name, void **obj, + size_t size, Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + if (!visit_start_struct(ffv->target, name, obj, size, errp)) { + return false; + } + ffv->depth++; + return true; +} + +static void forward_field_end_struct(Visitor *v, void **obj) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + assert(ffv->depth); + ffv->depth--; + visit_end_struct(ffv->target, obj); +} + +static bool forward_field_start_list(Visitor *v, const char *name, + GenericList **list, size_t size, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + ffv->depth++; + return visit_start_list(ffv->target, name, list, size, errp); +} + +static GenericList *forward_field_next_list(Visitor *v, GenericList *tail, + size_t size) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + assert(ffv->depth); + return visit_next_list(ffv->target, tail, size); +} + +static bool forward_field_check_list(Visitor *v, Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + assert(ffv->depth); + return visit_check_list(ffv->target, errp); +} + +static void forward_field_end_list(Visitor *v, void **obj) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + assert(ffv->depth); + ffv->depth--; + visit_end_list(ffv->target, obj); +} + +static bool forward_field_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + /* + * The name passed to start_alternate is used also in the visit_type_* calls + * that retrieve the alternate's content; so, do not increase depth here. + */ + return visit_start_alternate(ffv->target, name, obj, size, errp); +} + +static void forward_field_end_alternate(Visitor *v, void **obj) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + visit_end_alternate(ffv->target, obj); +} + +static bool forward_field_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_int64(ffv->target, name, obj, errp); +} + +static bool forward_field_type_uint64(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_uint64(ffv->target, name, obj, errp); +} + +static bool forward_field_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_bool(ffv->target, name, obj, errp); +} + +static bool forward_field_type_str(Visitor *v, const char *name, char **obj, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_str(ffv->target, name, obj, errp); +} + +static bool forward_field_type_size(Visitor *v, const char *name, uint64_t *obj, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_size(ffv->target, name, obj, errp); +} + +static bool forward_field_type_number(Visitor *v, const char *name, double *obj, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_number(ffv->target, name, obj, errp); +} + +static bool forward_field_type_any(Visitor *v, const char *name, QObject **obj, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_any(ffv->target, name, obj, errp); +} + +static bool forward_field_type_null(Visitor *v, const char *name, + QNull **obj, Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return false; + } + return visit_type_null(ffv->target, name, obj, errp); +} + +static void forward_field_optional(Visitor *v, const char *name, bool *present) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, NULL)) { + *present = false; + return; + } + visit_optional(ffv->target, name, present); +} + +static bool forward_field_policy_reject(Visitor *v, const char *name, + unsigned special_features, + Error **errp) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, errp)) { + return true; + } + return visit_policy_reject(ffv->target, name, special_features, errp); +} + +static bool forward_field_policy_skip(Visitor *v, const char *name, + unsigned special_features) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + if (!forward_field_translate_name(ffv, &name, NULL)) { + return true; + } + return visit_policy_skip(ffv->target, name, special_features); +} + +static void forward_field_complete(Visitor *v, void *opaque) +{ + /* + * Do nothing, the complete method will be called in due time + * on the target visitor. + */ +} + +static void forward_field_free(Visitor *v) +{ + ForwardFieldVisitor *ffv = to_ffv(v); + + g_free(ffv->from); + g_free(ffv->to); + g_free(ffv); +} + +Visitor *visitor_forward_field(Visitor *target, const char *from, const char *to) +{ + ForwardFieldVisitor *v = g_new0(ForwardFieldVisitor, 1); + + /* + * Clone and dealloc visitors don't use a name for the toplevel + * visit, so they make no sense here. + */ + assert(target->type == VISITOR_OUTPUT || target->type == VISITOR_INPUT); + + v->visitor.type = target->type; + v->visitor.start_struct = forward_field_start_struct; + v->visitor.check_struct = forward_field_check_struct; + v->visitor.end_struct = forward_field_end_struct; + v->visitor.start_list = forward_field_start_list; + v->visitor.next_list = forward_field_next_list; + v->visitor.check_list = forward_field_check_list; + v->visitor.end_list = forward_field_end_list; + v->visitor.start_alternate = forward_field_start_alternate; + v->visitor.end_alternate = forward_field_end_alternate; + v->visitor.type_int64 = forward_field_type_int64; + v->visitor.type_uint64 = forward_field_type_uint64; + v->visitor.type_size = forward_field_type_size; + v->visitor.type_bool = forward_field_type_bool; + v->visitor.type_str = forward_field_type_str; + v->visitor.type_number = forward_field_type_number; + v->visitor.type_any = forward_field_type_any; + v->visitor.type_null = forward_field_type_null; + v->visitor.optional = forward_field_optional; + v->visitor.policy_reject = forward_field_policy_reject; + v->visitor.policy_skip = forward_field_policy_skip; + v->visitor.complete = forward_field_complete; + v->visitor.free = forward_field_free; + + v->target = target; + v->from = g_strdup(from); + v->to = g_strdup(to); + + return &v->visitor; +} diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json new file mode 100644 index 000000000..4912b9744 --- /dev/null +++ b/qapi/qapi-schema.json @@ -0,0 +1,95 @@ +# -*- Mode: Python -*- +# vim: filetype=python +## +# = Introduction +# +# This document describes all commands currently supported by QMP. +# +# Most of the time their usage is exactly the same as in the user Monitor, this +# means that any other document which also describe commands (the manpage, +# QEMU's manual, etc) can and should be consulted. +# +# QMP has two types of commands: regular and query commands. Regular commands +# usually change the Virtual Machine's state someway, while query commands just +# return information. The sections below are divided accordingly. +# +# It's important to observe that all communication examples are formatted in +# a reader-friendly way, so that they're easier to understand. However, in real +# protocol usage, they're emitted as a single line. +# +# Also, the following notation is used to denote data flow: +# +# Example: +# +# :: +# +# -> data issued by the Client +# <- Server data response +# +# Please, refer to the QMP specification (docs/interop/qmp-spec.txt) for +# detailed information on the Server command and response formats. +# +# = Stability Considerations +# +# The current QMP command set (described in this file) may be useful for a +# number of use cases, however it's limited and several commands have bad +# defined semantics, specially with regard to command completion. +# +# These problems are going to be solved incrementally in the next QEMU releases +# and we're going to establish a deprecation policy for badly defined commands. +# +# If you're planning to adopt QMP, please observe the following: +# +# 1. The deprecation policy will take effect and be documented soon, please +# check the documentation of each used command as soon as a new release of +# QEMU is available +# +# 2. DO NOT rely on anything which is not explicit documented +# +# 3. Errors, in special, are not documented. Applications should NOT check +# for specific errors classes or data (it's strongly recommended to only +# check for the "error" key) +# +## + +{ 'include': 'pragma.json' } + +# Documentation generated with qapi-gen.py is in source order, with +# included sub-schemas inserted at the first include directive +# (subsequent include directives have no effect). To get a sane and +# stable order, it's best to include each sub-schema just once, or +# include it first right here. + +{ 'include': 'error.json' } +{ 'include': 'common.json' } +{ 'include': 'sockets.json' } +{ 'include': 'run-state.json' } +{ 'include': 'crypto.json' } +{ 'include': 'block.json' } +{ 'include': 'block-export.json' } +{ 'include': 'char.json' } +{ 'include': 'dump.json' } +{ 'include': 'job.json' } +{ 'include': 'net.json' } +{ 'include': 'rdma.json' } +{ 'include': 'rocker.json' } +{ 'include': 'tpm.json' } +{ 'include': 'ui.json' } +{ 'include': 'authz.json' } +{ 'include': 'migration.json' } +{ 'include': 'transaction.json' } +{ 'include': 'trace.json' } +{ 'include': 'compat.json' } +{ 'include': 'control.json' } +{ 'include': 'introspect.json' } +{ 'include': 'qom.json' } +{ 'include': 'qdev.json' } +{ 'include': 'machine.json' } +{ 'include': 'machine-target.json' } +{ 'include': 'replay.json' } +{ 'include': 'yank.json' } +{ 'include': 'misc.json' } +{ 'include': 'misc-target.json' } +{ 'include': 'audio.json' } +{ 'include': 'acpi.json' } +{ 'include': 'pci.json' } diff --git a/qapi/qapi-type-helpers.c b/qapi/qapi-type-helpers.c new file mode 100644 index 000000000..f76b34f64 --- /dev/null +++ b/qapi/qapi-type-helpers.c @@ -0,0 +1,23 @@ +/* + * QAPI common helper functions + * + * This file provides helper functions related to types defined + * in the QAPI schema. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/type-helpers.h" + +HumanReadableText *human_readable_text_from_str(GString *str) +{ + HumanReadableText *ret = g_new0(HumanReadableText, 1); + + ret->human_readable_text = g_steal_pointer(&str->str); + + return ret; +} diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c new file mode 100644 index 000000000..fda704453 --- /dev/null +++ b/qapi/qapi-util.c @@ -0,0 +1,154 @@ +/* + * QAPI util functions + * + * Authors: + * Hu Tao <hutao@cn.fujitsu.com> + * Peter Lieven <pl@kamp.de> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/compat-policy.h" +#include "qapi/error.h" +#include "qemu/ctype.h" +#include "qapi/qmp/qerror.h" + +CompatPolicy compat_policy; + +static bool compat_policy_input_ok1(const char *adjective, + CompatPolicyInput policy, + ErrorClass error_class, + const char *kind, const char *name, + Error **errp) +{ + switch (policy) { + case COMPAT_POLICY_INPUT_ACCEPT: + return true; + case COMPAT_POLICY_INPUT_REJECT: + error_set(errp, error_class, "%s %s %s disabled by policy", + adjective, kind, name); + return false; + case COMPAT_POLICY_INPUT_CRASH: + default: + abort(); + } +} + +bool compat_policy_input_ok(unsigned special_features, + const CompatPolicy *policy, + ErrorClass error_class, + const char *kind, const char *name, + Error **errp) +{ + if ((special_features & 1u << QAPI_DEPRECATED) + && !compat_policy_input_ok1("Deprecated", + policy->deprecated_input, + error_class, kind, name, errp)) { + return false; + } + if ((special_features & (1u << QAPI_UNSTABLE)) + && !compat_policy_input_ok1("Unstable", + policy->unstable_input, + error_class, kind, name, errp)) { + return false; + } + return true; +} + +const char *qapi_enum_lookup(const QEnumLookup *lookup, int val) +{ + assert(val >= 0 && val < lookup->size); + + return lookup->array[val]; +} + +int qapi_enum_parse(const QEnumLookup *lookup, const char *buf, + int def, Error **errp) +{ + int i; + + if (!buf) { + return def; + } + + for (i = 0; i < lookup->size; i++) { + if (!strcmp(buf, lookup->array[i])) { + return i; + } + } + + error_setg(errp, "invalid parameter value: %s", buf); + return def; +} + +bool qapi_bool_parse(const char *name, const char *value, bool *obj, Error **errp) +{ + if (g_str_equal(value, "on") || + g_str_equal(value, "yes") || + g_str_equal(value, "true") || + g_str_equal(value, "y")) { + *obj = true; + return true; + } + if (g_str_equal(value, "off") || + g_str_equal(value, "no") || + g_str_equal(value, "false") || + g_str_equal(value, "n")) { + *obj = false; + return true; + } + + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, + "'on' or 'off'"); + return false; +} + +/* + * Parse a valid QAPI name from @str. + * A valid name consists of letters, digits, hyphen and underscore. + * It may be prefixed by __RFQDN_ (downstream extension), where RFQDN + * may contain only letters, digits, hyphen and period. + * The special exception for enumeration names is not implemented. + * See docs/devel/qapi-code-gen.txt for more on QAPI naming rules. + * Keep this consistent with scripts/qapi.py! + * If @complete, the parse fails unless it consumes @str completely. + * Return its length on success, -1 on failure. + */ +int parse_qapi_name(const char *str, bool complete) +{ + const char *p = str; + + if (*p == '_') { /* Downstream __RFQDN_ */ + p++; + if (*p != '_') { + return -1; + } + while (*++p) { + if (!qemu_isalnum(*p) && *p != '-' && *p != '.') { + break; + } + } + + if (*p != '_') { + return -1; + } + p++; + } + + if (!qemu_isalpha(*p)) { + return -1; + } + while (*++p) { + if (!qemu_isalnum(*p) && *p != '-' && *p != '_') { + break; + } + } + + if (complete && *p) { + return -1; + } + return p - str; +} diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c new file mode 100644 index 000000000..6c13510a2 --- /dev/null +++ b/qapi/qapi-visit-core.c @@ -0,0 +1,444 @@ +/* + * Core Definitions for QAPI Visitor Classes + * + * Copyright (C) 2012-2016 Red Hat, Inc. + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/compat-policy.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" +#include "qapi/visitor.h" +#include "qapi/visitor-impl.h" +#include "trace.h" + +/* Zero-initialization must result in default policy */ +QEMU_BUILD_BUG_ON(COMPAT_POLICY_INPUT_ACCEPT || COMPAT_POLICY_OUTPUT_ACCEPT); + + +void visit_complete(Visitor *v, void *opaque) +{ + assert(v->type != VISITOR_OUTPUT || v->complete); + trace_visit_complete(v, opaque); + if (v->complete) { + v->complete(v, opaque); + } +} + +void visit_free(Visitor *v) +{ + trace_visit_free(v); + if (v) { + v->free(v); + } +} + +bool visit_start_struct(Visitor *v, const char *name, void **obj, + size_t size, Error **errp) +{ + bool ok; + + trace_visit_start_struct(v, name, obj, size); + if (obj) { + assert(size); + assert(!(v->type & VISITOR_OUTPUT) || *obj); + } + ok = v->start_struct(v, name, obj, size, errp); + if (obj && (v->type & VISITOR_INPUT)) { + assert(ok != !*obj); + } + return ok; +} + +bool visit_check_struct(Visitor *v, Error **errp) +{ + trace_visit_check_struct(v); + return v->check_struct ? v->check_struct(v, errp) : true; +} + +void visit_end_struct(Visitor *v, void **obj) +{ + trace_visit_end_struct(v, obj); + v->end_struct(v, obj); +} + +bool visit_start_list(Visitor *v, const char *name, GenericList **list, + size_t size, Error **errp) +{ + bool ok; + + assert(!list || size >= sizeof(GenericList)); + trace_visit_start_list(v, name, list, size); + ok = v->start_list(v, name, list, size, errp); + if (list && (v->type & VISITOR_INPUT)) { + assert(ok || !*list); + } + return ok; +} + +GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size) +{ + assert(tail && size >= sizeof(GenericList)); + trace_visit_next_list(v, tail, size); + return v->next_list(v, tail, size); +} + +bool visit_check_list(Visitor *v, Error **errp) +{ + trace_visit_check_list(v); + return v->check_list ? v->check_list(v, errp) : true; +} + +void visit_end_list(Visitor *v, void **obj) +{ + trace_visit_end_list(v, obj); + v->end_list(v, obj); +} + +bool visit_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + Error **errp) +{ + bool ok; + + assert(obj && size >= sizeof(GenericAlternate)); + assert(!(v->type & VISITOR_OUTPUT) || *obj); + trace_visit_start_alternate(v, name, obj, size); + if (!v->start_alternate) { + assert(!(v->type & VISITOR_INPUT)); + return true; + } + ok = v->start_alternate(v, name, obj, size, errp); + if (v->type & VISITOR_INPUT) { + assert(ok != !*obj); + } + return ok; +} + +void visit_end_alternate(Visitor *v, void **obj) +{ + trace_visit_end_alternate(v, obj); + if (v->end_alternate) { + v->end_alternate(v, obj); + } +} + +bool visit_optional(Visitor *v, const char *name, bool *present) +{ + trace_visit_optional(v, name, present); + if (v->optional) { + v->optional(v, name, present); + } + return *present; +} + +bool visit_policy_reject(Visitor *v, const char *name, + unsigned special_features, Error **errp) +{ + trace_visit_policy_reject(v, name); + if (v->policy_reject) { + return v->policy_reject(v, name, special_features, errp); + } + return false; +} + +bool visit_policy_skip(Visitor *v, const char *name, + unsigned special_features) +{ + trace_visit_policy_skip(v, name); + if (v->policy_skip) { + return v->policy_skip(v, name, special_features); + } + return false; +} + +void visit_set_policy(Visitor *v, CompatPolicy *policy) +{ + v->compat_policy = *policy; +} + +bool visit_is_input(Visitor *v) +{ + return v->type == VISITOR_INPUT; +} + +bool visit_is_dealloc(Visitor *v) +{ + return v->type == VISITOR_DEALLOC; +} + +bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) +{ + assert(obj); + trace_visit_type_int(v, name, obj); + return v->type_int64(v, name, obj, errp); +} + +static bool visit_type_uintN(Visitor *v, uint64_t *obj, const char *name, + uint64_t max, const char *type, Error **errp) +{ + uint64_t value = *obj; + + assert(v->type == VISITOR_INPUT || value <= max); + + if (!v->type_uint64(v, name, &value, errp)) { + return false; + } + if (value > max) { + assert(v->type == VISITOR_INPUT); + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", type); + return false; + } + *obj = value; + return true; +} + +bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, + Error **errp) +{ + uint64_t value; + bool ok; + + trace_visit_type_uint8(v, name, obj); + value = *obj; + ok = visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp); + *obj = value; + return ok; +} + +bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, + Error **errp) +{ + uint64_t value; + bool ok; + + trace_visit_type_uint16(v, name, obj); + value = *obj; + ok = visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp); + *obj = value; + return ok; +} + +bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, + Error **errp) +{ + uint64_t value; + bool ok; + + trace_visit_type_uint32(v, name, obj); + value = *obj; + ok = visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp); + *obj = value; + return ok; +} + +bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, + Error **errp) +{ + assert(obj); + trace_visit_type_uint64(v, name, obj); + return v->type_uint64(v, name, obj, errp); +} + +static bool visit_type_intN(Visitor *v, int64_t *obj, const char *name, + int64_t min, int64_t max, const char *type, + Error **errp) +{ + int64_t value = *obj; + + assert(v->type == VISITOR_INPUT || (value >= min && value <= max)); + + if (!v->type_int64(v, name, &value, errp)) { + return false; + } + if (value < min || value > max) { + assert(v->type == VISITOR_INPUT); + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", type); + return false; + } + *obj = value; + return true; +} + +bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp) +{ + int64_t value; + bool ok; + + trace_visit_type_int8(v, name, obj); + value = *obj; + ok = visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp); + *obj = value; + return ok; +} + +bool visit_type_int16(Visitor *v, const char *name, int16_t *obj, + Error **errp) +{ + int64_t value; + bool ok; + + trace_visit_type_int16(v, name, obj); + value = *obj; + ok = visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", + errp); + *obj = value; + return ok; +} + +bool visit_type_int32(Visitor *v, const char *name, int32_t *obj, + Error **errp) +{ + int64_t value; + bool ok; + + trace_visit_type_int32(v, name, obj); + value = *obj; + ok = visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", + errp); + *obj = value; + return ok; +} + +bool visit_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) +{ + assert(obj); + trace_visit_type_int64(v, name, obj); + return v->type_int64(v, name, obj, errp); +} + +bool visit_type_size(Visitor *v, const char *name, uint64_t *obj, + Error **errp) +{ + assert(obj); + trace_visit_type_size(v, name, obj); + if (v->type_size) { + return v->type_size(v, name, obj, errp); + } + return v->type_uint64(v, name, obj, errp); +} + +bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) +{ + assert(obj); + trace_visit_type_bool(v, name, obj); + return v->type_bool(v, name, obj, errp); +} + +bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp) +{ + bool ok; + + assert(obj); + /* TODO: Fix callers to not pass NULL when they mean "", so that we + * can enable: + assert(!(v->type & VISITOR_OUTPUT) || *obj); + */ + trace_visit_type_str(v, name, obj); + ok = v->type_str(v, name, obj, errp); + if (v->type & VISITOR_INPUT) { + assert(ok != !*obj); + } + return ok; +} + +bool visit_type_number(Visitor *v, const char *name, double *obj, + Error **errp) +{ + assert(obj); + trace_visit_type_number(v, name, obj); + return v->type_number(v, name, obj, errp); +} + +bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) +{ + bool ok; + + assert(obj); + assert(v->type != VISITOR_OUTPUT || *obj); + trace_visit_type_any(v, name, obj); + ok = v->type_any(v, name, obj, errp); + if (v->type == VISITOR_INPUT) { + assert(ok != !*obj); + } + return ok; +} + +bool visit_type_null(Visitor *v, const char *name, QNull **obj, + Error **errp) +{ + trace_visit_type_null(v, name, obj); + return v->type_null(v, name, obj, errp); +} + +static bool output_type_enum(Visitor *v, const char *name, int *obj, + const QEnumLookup *lookup, Error **errp) +{ + int value = *obj; + char *enum_str; + + enum_str = (char *)qapi_enum_lookup(lookup, value); + return visit_type_str(v, name, &enum_str, errp); +} + +static bool input_type_enum(Visitor *v, const char *name, int *obj, + const QEnumLookup *lookup, Error **errp) +{ + int64_t value; + g_autofree char *enum_str = NULL; + + if (!visit_type_str(v, name, &enum_str, errp)) { + return false; + } + + value = qapi_enum_parse(lookup, enum_str, -1, NULL); + if (value < 0) { + error_setg(errp, "Parameter '%s' does not accept value '%s'", + name ? name : "null", enum_str); + return false; + } + + if (lookup->special_features + && !compat_policy_input_ok(lookup->special_features[value], + &v->compat_policy, + ERROR_CLASS_GENERIC_ERROR, + "value", enum_str, errp)) { + return false; + } + + *obj = value; + return true; +} + +bool visit_type_enum(Visitor *v, const char *name, int *obj, + const QEnumLookup *lookup, Error **errp) +{ + assert(obj && lookup); + trace_visit_type_enum(v, name, obj); + switch (v->type) { + case VISITOR_INPUT: + return input_type_enum(v, name, obj, lookup, errp); + case VISITOR_OUTPUT: + return output_type_enum(v, name, obj, lookup, errp); + case VISITOR_CLONE: + /* nothing further to do, scalar value was already copied by + * g_memdup() during visit_start_*() */ + return true; + case VISITOR_DEALLOC: + /* nothing to deallocate for a scalar */ + return true; + default: + abort(); + } +} diff --git a/qapi/qdev.json b/qapi/qdev.json new file mode 100644 index 000000000..69656b14d --- /dev/null +++ b/qapi/qdev.json @@ -0,0 +1,158 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Device infrastructure (qdev) +## + +{ 'include': 'qom.json' } + +## +# @device-list-properties: +# +# List properties associated with a device. +# +# @typename: the type name of a device +# +# Returns: a list of ObjectPropertyInfo describing a devices properties +# +# Note: objects can create properties at runtime, for example to describe +# links between different devices and/or objects. These properties +# are not included in the output of this command. +# +# Since: 1.2 +## +{ 'command': 'device-list-properties', + 'data': { 'typename': 'str'}, + 'returns': [ 'ObjectPropertyInfo' ] } + +## +# @device_add: +# +# Add a device. +# +# @driver: the name of the new device's driver +# +# @bus: the device's parent bus (device tree path) +# +# @id: the device's ID, must be unique +# +# Features: +# @json-cli: If present, the "-device" command line option supports JSON +# syntax with a structure identical to the arguments of this +# command. +# +# Notes: +# +# Additional arguments depend on the type. +# +# 1. For detailed information about this command, please refer to the +# 'docs/qdev-device-use.txt' file. +# +# 2. It's possible to list device properties by running QEMU with the +# "-device DEVICE,help" command-line argument, where DEVICE is the +# device's name +# +# Example: +# +# -> { "execute": "device_add", +# "arguments": { "driver": "e1000", "id": "net1", +# "bus": "pci.0", +# "mac": "52:54:00:12:34:56" } } +# <- { "return": {} } +# +# TODO: This command effectively bypasses QAPI completely due to its +# "additional arguments" business. It shouldn't have been added to +# the schema in this form. It should be qapified properly, or +# replaced by a properly qapified command. +# +# Since: 0.13 +## +{ 'command': 'device_add', + 'data': {'driver': 'str', '*bus': 'str', '*id': 'str'}, + 'gen': false, # so we can get the additional arguments + 'features': ['json-cli'] } + +## +# @device_del: +# +# Remove a device from a guest +# +# @id: the device's ID or QOM path +# +# Returns: Nothing on success +# If @id is not a valid device, DeviceNotFound +# +# Notes: When this command completes, the device may not be removed from the +# guest. Hot removal is an operation that requires guest cooperation. +# This command merely requests that the guest begin the hot removal +# process. Completion of the device removal process is signaled with a +# DEVICE_DELETED event. Guest reset will automatically complete removal +# for all devices. If a guest-side error in the hot removal process is +# detected, the device will not be removed and a DEVICE_UNPLUG_GUEST_ERROR +# event is sent. Some errors cannot be detected. +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "device_del", +# "arguments": { "id": "net1" } } +# <- { "return": {} } +# +# -> { "execute": "device_del", +# "arguments": { "id": "/machine/peripheral-anon/device[0]" } } +# <- { "return": {} } +# +## +{ 'command': 'device_del', 'data': {'id': 'str'} } + +## +# @DEVICE_DELETED: +# +# Emitted whenever the device removal completion is acknowledged by the guest. +# At this point, it's safe to reuse the specified device ID. Device removal can +# be initiated by the guest or by HMP/QMP commands. +# +# @device: the device's ID if it has one +# +# @path: the device's QOM path +# +# Since: 1.5 +# +# Example: +# +# <- { "event": "DEVICE_DELETED", +# "data": { "device": "virtio-net-pci-0", +# "path": "/machine/peripheral/virtio-net-pci-0" }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'DEVICE_DELETED', + 'data': { '*device': 'str', 'path': 'str' } } + +## +# @DEVICE_UNPLUG_GUEST_ERROR: +# +# Emitted when a device hot unplug fails due to a guest reported error. +# +# @device: the device's ID if it has one +# +# @path: the device's QOM path +# +# Since: 6.2 +# +# Example: +# +# <- { "event": "DEVICE_UNPLUG_GUEST_ERROR" +# "data": { "device": "core1", +# "path": "/machine/peripheral/core1" }, +# }, +# "timestamp": { "seconds": 1615570772, "microseconds": 202844 } } +# +## +{ 'event': 'DEVICE_UNPLUG_GUEST_ERROR', + 'data': { '*device': 'str', 'path': 'str' } } diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c new file mode 100644 index 000000000..d378bccac --- /dev/null +++ b/qapi/qmp-dispatch.c @@ -0,0 +1,275 @@ +/* + * Core Definitions for QAPI/QMP Dispatch + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" + +#include "block/aio.h" +#include "qapi/compat-policy.h" +#include "qapi/error.h" +#include "qapi/qmp/dispatch.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qobject-output-visitor.h" +#include "sysemu/runstate.h" +#include "qapi/qmp/qbool.h" +#include "qemu/coroutine.h" +#include "qemu/main-loop.h" + +Visitor *qobject_input_visitor_new_qmp(QObject *obj) +{ + Visitor *v = qobject_input_visitor_new(obj); + + visit_set_policy(v, &compat_policy); + return v; +} + +Visitor *qobject_output_visitor_new_qmp(QObject **result) +{ + Visitor *v = qobject_output_visitor_new(result); + + visit_set_policy(v, &compat_policy); + return v; +} + +static QDict *qmp_dispatch_check_obj(QDict *dict, bool allow_oob, + Error **errp) +{ + const char *exec_key = NULL; + const QDictEntry *ent; + const char *arg_name; + const QObject *arg_obj; + + for (ent = qdict_first(dict); ent; + ent = qdict_next(dict, ent)) { + arg_name = qdict_entry_key(ent); + arg_obj = qdict_entry_value(ent); + + if (!strcmp(arg_name, "execute") + || (!strcmp(arg_name, "exec-oob") && allow_oob)) { + if (qobject_type(arg_obj) != QTYPE_QSTRING) { + error_setg(errp, "QMP input member '%s' must be a string", + arg_name); + return NULL; + } + if (exec_key) { + error_setg(errp, "QMP input member '%s' clashes with '%s'", + arg_name, exec_key); + return NULL; + } + exec_key = arg_name; + } else if (!strcmp(arg_name, "arguments")) { + if (qobject_type(arg_obj) != QTYPE_QDICT) { + error_setg(errp, + "QMP input member 'arguments' must be an object"); + return NULL; + } + } else if (!strcmp(arg_name, "id")) { + continue; + } else { + error_setg(errp, "QMP input member '%s' is unexpected", + arg_name); + return NULL; + } + } + + if (!exec_key) { + error_setg(errp, "QMP input lacks member 'execute'"); + return NULL; + } + + return dict; +} + +QDict *qmp_error_response(Error *err) +{ + QDict *rsp; + + rsp = qdict_from_jsonf_nofail("{ 'error': { 'class': %s, 'desc': %s } }", + QapiErrorClass_str(error_get_class(err)), + error_get_pretty(err)); + error_free(err); + return rsp; +} + +/* + * Does @qdict look like a command to be run out-of-band? + */ +bool qmp_is_oob(const QDict *dict) +{ + return qdict_haskey(dict, "exec-oob") + && !qdict_haskey(dict, "execute"); +} + +typedef struct QmpDispatchBH { + const QmpCommand *cmd; + Monitor *cur_mon; + QDict *args; + QObject **ret; + Error **errp; + Coroutine *co; +} QmpDispatchBH; + +static void do_qmp_dispatch_bh(void *opaque) +{ + QmpDispatchBH *data = opaque; + + assert(monitor_cur() == NULL); + monitor_set_cur(qemu_coroutine_self(), data->cur_mon); + data->cmd->fn(data->args, data->ret, data->errp); + monitor_set_cur(qemu_coroutine_self(), NULL); + aio_co_wake(data->co); +} + +/* + * Runs outside of coroutine context for OOB commands, but in coroutine + * context for everything else. + */ +QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, + bool allow_oob, Monitor *cur_mon) +{ + Error *err = NULL; + bool oob; + const char *command; + QDict *args; + const QmpCommand *cmd; + QDict *dict; + QObject *id; + QObject *ret = NULL; + QDict *rsp = NULL; + + dict = qobject_to(QDict, request); + if (!dict) { + id = NULL; + error_setg(&err, "QMP input must be a JSON object"); + goto out; + } + + id = qdict_get(dict, "id"); + + if (!qmp_dispatch_check_obj(dict, allow_oob, &err)) { + goto out; + } + + command = qdict_get_try_str(dict, "execute"); + oob = false; + if (!command) { + assert(allow_oob); + command = qdict_get_str(dict, "exec-oob"); + oob = true; + } + cmd = qmp_find_command(cmds, command); + if (cmd == NULL) { + error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND, + "The command %s has not been found", command); + goto out; + } + if (!compat_policy_input_ok(cmd->special_features, &compat_policy, + ERROR_CLASS_COMMAND_NOT_FOUND, + "command", command, &err)) { + goto out; + } + if (!cmd->enabled) { + error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND, + "Command %s has been disabled%s%s", + command, + cmd->disable_reason ? ": " : "", + cmd->disable_reason ?: ""); + goto out; + } + if (oob && !(cmd->options & QCO_ALLOW_OOB)) { + error_setg(&err, "The command %s does not support OOB", + command); + goto out; + } + + if (!qmp_command_available(cmd, &err)) { + goto out; + } + + if (!qdict_haskey(dict, "arguments")) { + args = qdict_new(); + } else { + args = qdict_get_qdict(dict, "arguments"); + qobject_ref(args); + } + + assert(!(oob && qemu_in_coroutine())); + assert(monitor_cur() == NULL); + if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) { + monitor_set_cur(qemu_coroutine_self(), cur_mon); + cmd->fn(args, &ret, &err); + monitor_set_cur(qemu_coroutine_self(), NULL); + } else { + /* + * Actual context doesn't match the one the command needs. + * + * Case 1: we are in coroutine context, but command does not + * have QCO_COROUTINE. We need to drop out of coroutine + * context for executing it. + * + * Case 2: we are outside coroutine context, but command has + * QCO_COROUTINE. Can't actually happen, because we get here + * outside coroutine context only when executing a command + * out of band, and OOB commands never have QCO_COROUTINE. + */ + assert(!oob && qemu_in_coroutine() && !(cmd->options & QCO_COROUTINE)); + + QmpDispatchBH data = { + .cur_mon = cur_mon, + .cmd = cmd, + .args = args, + .ret = &ret, + .errp = &err, + .co = qemu_coroutine_self(), + }; + aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh, + &data); + qemu_coroutine_yield(); + } + qobject_unref(args); + if (err) { + /* or assert(!ret) after reviewing all handlers: */ + qobject_unref(ret); + goto out; + } + + if (cmd->options & QCO_NO_SUCCESS_RESP) { + g_assert(!ret); + return NULL; + } else if (!ret) { + /* + * When the command's schema has no 'returns', cmd->fn() + * leaves @ret null. The QMP spec calls for an empty object + * then; supply it. + */ + ret = QOBJECT(qdict_new()); + } + + rsp = qdict_new(); + qdict_put_obj(rsp, "return", ret); + +out: + if (err) { + assert(!rsp); + rsp = qmp_error_response(err); + } + + assert(rsp); + + if (id) { + qdict_put_obj(rsp, "id", qobject_ref(id)); + } + + return rsp; +} diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c new file mode 100644 index 000000000..19d3cd003 --- /dev/null +++ b/qapi/qmp-event.c @@ -0,0 +1,45 @@ +/* + * QMP Event related + * + * Copyright (c) 2014 Wenchao Xia + * + * Authors: + * Wenchao Xia <wenchaoqemu@gmail.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" + +#include "qapi/qmp-event.h" +#include "qapi/qmp/qstring.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qjson.h" + +static void timestamp_put(QDict *qdict) +{ + int err; + QDict *ts; + qemu_timeval tv; + + err = qemu_gettimeofday(&tv); + /* Put -1 to indicate failure of getting host time */ + ts = qdict_from_jsonf_nofail("{ 'seconds': %lld, 'microseconds': %lld }", + err < 0 ? -1LL : (long long)tv.tv_sec, + err < 0 ? -1LL : (long long)tv.tv_usec); + qdict_put(qdict, "timestamp", ts); +} + +/* + * Build a QDict, then fill event name and time stamp, caller should free the + * QDict after usage. + */ +QDict *qmp_event_build_dict(const char *event_name) +{ + QDict *dict = qdict_new(); + qdict_put_str(dict, "event", event_name); + timestamp_put(dict); + return dict; +} diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c new file mode 100644 index 000000000..485bc5e6f --- /dev/null +++ b/qapi/qmp-registry.c @@ -0,0 +1,95 @@ +/* + * Core Definitions for QAPI/QMP Dispatch + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * Michael Roth <mdroth@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/qmp/dispatch.h" + +void qmp_register_command(QmpCommandList *cmds, const char *name, + QmpCommandFunc *fn, QmpCommandOptions options, + unsigned special_features) +{ + QmpCommand *cmd = g_malloc0(sizeof(*cmd)); + + /* QCO_COROUTINE and QCO_ALLOW_OOB are incompatible for now */ + assert(!((options & QCO_COROUTINE) && (options & QCO_ALLOW_OOB))); + + cmd->name = name; + cmd->fn = fn; + cmd->enabled = true; + cmd->options = options; + cmd->special_features = special_features; + QTAILQ_INSERT_TAIL(cmds, cmd, node); +} + +const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char *name) +{ + QmpCommand *cmd; + + QTAILQ_FOREACH(cmd, cmds, node) { + if (strcmp(cmd->name, name) == 0) { + return cmd; + } + } + return NULL; +} + +static void qmp_toggle_command(QmpCommandList *cmds, const char *name, + bool enabled, const char *disable_reason) +{ + QmpCommand *cmd; + + QTAILQ_FOREACH(cmd, cmds, node) { + if (strcmp(cmd->name, name) == 0) { + cmd->enabled = enabled; + cmd->disable_reason = disable_reason; + return; + } + } +} + +void qmp_disable_command(QmpCommandList *cmds, const char *name, + const char *disable_reason) +{ + qmp_toggle_command(cmds, name, false, disable_reason); +} + +void qmp_enable_command(QmpCommandList *cmds, const char *name) +{ + qmp_toggle_command(cmds, name, true, NULL); +} + +bool qmp_command_is_enabled(const QmpCommand *cmd) +{ + return cmd->enabled; +} + +const char *qmp_command_name(const QmpCommand *cmd) +{ + return cmd->name; +} + +bool qmp_has_success_response(const QmpCommand *cmd) +{ + return !(cmd->options & QCO_NO_SUCCESS_RESP); +} + +void qmp_for_each_command(const QmpCommandList *cmds, qmp_cmd_callback_fn fn, + void *opaque) +{ + const QmpCommand *cmd; + + QTAILQ_FOREACH(cmd, cmds, node) { + fn(cmd, opaque); + } +} diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c new file mode 100644 index 000000000..f0b4c7ca9 --- /dev/null +++ b/qapi/qobject-input-visitor.c @@ -0,0 +1,776 @@ +/* + * Input Visitor + * + * Copyright (C) 2012-2017 Red Hat, Inc. + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include <math.h> +#include "qapi/compat-policy.h" +#include "qapi/error.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/visitor-impl.h" +#include "qemu/queue.h" +#include "qapi/qmp/qjson.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnull.h" +#include "qapi/qmp/qnum.h" +#include "qapi/qmp/qstring.h" +#include "qemu/cutils.h" +#include "qemu/option.h" + +typedef struct StackObject { + const char *name; /* Name of @obj in its parent, if any */ + QObject *obj; /* QDict or QList being visited */ + void *qapi; /* sanity check that caller uses same pointer */ + + GHashTable *h; /* If @obj is QDict: unvisited keys */ + const QListEntry *entry; /* If @obj is QList: unvisited tail */ + unsigned index; /* If @obj is QList: list index of @entry */ + + QSLIST_ENTRY(StackObject) node; /* parent */ +} StackObject; + +struct QObjectInputVisitor { + Visitor visitor; + + /* Root of visit at visitor creation. */ + QObject *root; + bool keyval; /* Assume @root made with keyval_parse() */ + + /* Stack of objects being visited (all entries will be either + * QDict or QList). */ + QSLIST_HEAD(, StackObject) stack; + + GString *errname; /* Accumulator for full_name() */ +}; + +static QObjectInputVisitor *to_qiv(Visitor *v) +{ + return container_of(v, QObjectInputVisitor, visitor); +} + +/* + * Find the full name of something @qiv is currently visiting. + * @qiv is visiting something named @name in the stack of containers + * @qiv->stack. + * If @n is zero, return its full name. + * If @n is positive, return the full name of the @n-th container + * counting from the top. The stack of containers must have at least + * @n elements. + * The returned string is valid until the next full_name_nth(@v) or + * destruction of @v. + */ +static const char *full_name_nth(QObjectInputVisitor *qiv, const char *name, + int n) +{ + StackObject *so; + char buf[32]; + + if (qiv->errname) { + g_string_truncate(qiv->errname, 0); + } else { + qiv->errname = g_string_new(""); + } + + QSLIST_FOREACH(so , &qiv->stack, node) { + if (n) { + n--; + } else if (qobject_type(so->obj) == QTYPE_QDICT) { + g_string_prepend(qiv->errname, name ?: "<anonymous>"); + g_string_prepend_c(qiv->errname, '.'); + } else { + snprintf(buf, sizeof(buf), + qiv->keyval ? ".%u" : "[%u]", + so->index); + g_string_prepend(qiv->errname, buf); + } + name = so->name; + } + assert(!n); + + if (name) { + g_string_prepend(qiv->errname, name); + } else if (qiv->errname->str[0] == '.') { + g_string_erase(qiv->errname, 0, 1); + } else if (!qiv->errname->str[0]) { + return "<anonymous>"; + } + + return qiv->errname->str; +} + +static const char *full_name(QObjectInputVisitor *qiv, const char *name) +{ + return full_name_nth(qiv, name, 0); +} + +static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv, + const char *name, + bool consume) +{ + StackObject *tos; + QObject *qobj; + QObject *ret; + + if (QSLIST_EMPTY(&qiv->stack)) { + /* Starting at root, name is ignored. */ + assert(qiv->root); + return qiv->root; + } + + /* We are in a container; find the next element. */ + tos = QSLIST_FIRST(&qiv->stack); + qobj = tos->obj; + assert(qobj); + + if (qobject_type(qobj) == QTYPE_QDICT) { + assert(name); + ret = qdict_get(qobject_to(QDict, qobj), name); + if (tos->h && consume && ret) { + bool removed = g_hash_table_remove(tos->h, name); + assert(removed); + } + } else { + assert(qobject_type(qobj) == QTYPE_QLIST); + assert(!name); + if (tos->entry) { + ret = qlist_entry_obj(tos->entry); + if (consume) { + tos->entry = qlist_next(tos->entry); + } + } else { + ret = NULL; + } + if (consume) { + tos->index++; + } + } + + return ret; +} + +static QObject *qobject_input_get_object(QObjectInputVisitor *qiv, + const char *name, + bool consume, Error **errp) +{ + QObject *obj = qobject_input_try_get_object(qiv, name, consume); + + if (!obj) { + error_setg(errp, QERR_MISSING_PARAMETER, full_name(qiv, name)); + } + return obj; +} + +static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv, + const char *name, + Error **errp) +{ + QObject *qobj; + QString *qstr; + + qobj = qobject_input_get_object(qiv, name, true, errp); + if (!qobj) { + return NULL; + } + + qstr = qobject_to(QString, qobj); + if (!qstr) { + switch (qobject_type(qobj)) { + case QTYPE_QDICT: + case QTYPE_QLIST: + error_setg(errp, "Parameters '%s.*' are unexpected", + full_name(qiv, name)); + return NULL; + default: + /* Non-string scalar (should this be an assertion?) */ + error_setg(errp, "Internal error: parameter %s invalid", + full_name(qiv, name)); + return NULL; + } + } + + return qstring_get_str(qstr); +} + +static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv, + const char *name, + QObject *obj, void *qapi) +{ + GHashTable *h; + StackObject *tos = g_new0(StackObject, 1); + QDict *qdict = qobject_to(QDict, obj); + QList *qlist = qobject_to(QList, obj); + const QDictEntry *entry; + + assert(obj); + tos->name = name; + tos->obj = obj; + tos->qapi = qapi; + + if (qdict) { + h = g_hash_table_new(g_str_hash, g_str_equal); + for (entry = qdict_first(qdict); + entry; + entry = qdict_next(qdict, entry)) { + g_hash_table_insert(h, (void *)qdict_entry_key(entry), NULL); + } + tos->h = h; + } else { + assert(qlist); + tos->entry = qlist_first(qlist); + tos->index = -1; + } + + QSLIST_INSERT_HEAD(&qiv->stack, tos, node); + return tos->entry; +} + + +static bool qobject_input_check_struct(Visitor *v, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + StackObject *tos = QSLIST_FIRST(&qiv->stack); + GHashTableIter iter; + const char *key; + + assert(tos && !tos->entry); + + g_hash_table_iter_init(&iter, tos->h); + if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) { + error_setg(errp, "Parameter '%s' is unexpected", + full_name(qiv, key)); + return false; + } + return true; +} + +static void qobject_input_stack_object_free(StackObject *tos) +{ + if (tos->h) { + g_hash_table_unref(tos->h); + } + + g_free(tos); +} + +static void qobject_input_pop(Visitor *v, void **obj) +{ + QObjectInputVisitor *qiv = to_qiv(v); + StackObject *tos = QSLIST_FIRST(&qiv->stack); + + assert(tos && tos->qapi == obj); + QSLIST_REMOVE_HEAD(&qiv->stack, node); + qobject_input_stack_object_free(tos); +} + +static bool qobject_input_start_struct(Visitor *v, const char *name, void **obj, + size_t size, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + + if (obj) { + *obj = NULL; + } + if (!qobj) { + return false; + } + if (qobject_type(qobj) != QTYPE_QDICT) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "object"); + return false; + } + + qobject_input_push(qiv, name, qobj, obj); + + if (obj) { + *obj = g_malloc0(size); + } + return true; +} + +static void qobject_input_end_struct(Visitor *v, void **obj) +{ + QObjectInputVisitor *qiv = to_qiv(v); + StackObject *tos = QSLIST_FIRST(&qiv->stack); + + assert(qobject_type(tos->obj) == QTYPE_QDICT && tos->h); + qobject_input_pop(v, obj); +} + + +static bool qobject_input_start_list(Visitor *v, const char *name, + GenericList **list, size_t size, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + const QListEntry *entry; + + if (list) { + *list = NULL; + } + if (!qobj) { + return false; + } + if (qobject_type(qobj) != QTYPE_QLIST) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "array"); + return false; + } + + entry = qobject_input_push(qiv, name, qobj, list); + if (entry && list) { + *list = g_malloc0(size); + } + return true; +} + +static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail, + size_t size) +{ + QObjectInputVisitor *qiv = to_qiv(v); + StackObject *tos = QSLIST_FIRST(&qiv->stack); + + assert(tos && qobject_to(QList, tos->obj)); + + if (!tos->entry) { + return NULL; + } + tail->next = g_malloc0(size); + return tail->next; +} + +static bool qobject_input_check_list(Visitor *v, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + StackObject *tos = QSLIST_FIRST(&qiv->stack); + + assert(tos && qobject_to(QList, tos->obj)); + + if (tos->entry) { + error_setg(errp, "Only %u list elements expected in %s", + tos->index + 1, full_name_nth(qiv, NULL, 1)); + return false; + } + return true; +} + +static void qobject_input_end_list(Visitor *v, void **obj) +{ + QObjectInputVisitor *qiv = to_qiv(v); + StackObject *tos = QSLIST_FIRST(&qiv->stack); + + assert(qobject_type(tos->obj) == QTYPE_QLIST && !tos->h); + qobject_input_pop(v, obj); +} + +static bool qobject_input_start_alternate(Visitor *v, const char *name, + GenericAlternate **obj, size_t size, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, false, errp); + + if (!qobj) { + *obj = NULL; + return false; + } + *obj = g_malloc0(size); + (*obj)->type = qobject_type(qobj); + return true; +} + +static bool qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + QNum *qnum; + + if (!qobj) { + return false; + } + qnum = qobject_to(QNum, qobj); + if (!qnum || !qnum_get_try_int(qnum, obj)) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "integer"); + return false; + } + return true; +} + +static bool qobject_input_type_int64_keyval(Visitor *v, const char *name, + int64_t *obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + const char *str = qobject_input_get_keyval(qiv, name, errp); + + if (!str) { + return false; + } + + if (qemu_strtoi64(str, NULL, 0, obj) < 0) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "integer"); + return false; + } + return true; +} + +static bool qobject_input_type_uint64(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + QNum *qnum; + int64_t val; + + if (!qobj) { + return false; + } + qnum = qobject_to(QNum, qobj); + if (!qnum) { + goto err; + } + + if (qnum_get_try_uint(qnum, obj)) { + return true; + } + + /* Need to accept negative values for backward compatibility */ + if (qnum_get_try_int(qnum, &val)) { + *obj = val; + return true; + } + +err: + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "uint64"); + return false; +} + +static bool qobject_input_type_uint64_keyval(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + const char *str = qobject_input_get_keyval(qiv, name, errp); + + if (!str) { + return false; + } + + if (qemu_strtou64(str, NULL, 0, obj) < 0) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "integer"); + return false; + } + return true; +} + +static bool qobject_input_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + QBool *qbool; + + if (!qobj) { + return false; + } + qbool = qobject_to(QBool, qobj); + if (!qbool) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "boolean"); + return false; + } + + *obj = qbool_get_bool(qbool); + return true; +} + +static bool qobject_input_type_bool_keyval(Visitor *v, const char *name, + bool *obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + const char *str = qobject_input_get_keyval(qiv, name, errp); + + if (!str) { + return false; + } + + if (!qapi_bool_parse(name, str, obj, NULL)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "'on' or 'off'"); + return false; + } + return true; +} + +static bool qobject_input_type_str(Visitor *v, const char *name, char **obj, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + QString *qstr; + + *obj = NULL; + if (!qobj) { + return false; + } + qstr = qobject_to(QString, qobj); + if (!qstr) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "string"); + return false; + } + + *obj = g_strdup(qstring_get_str(qstr)); + return true; +} + +static bool qobject_input_type_str_keyval(Visitor *v, const char *name, + char **obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + const char *str = qobject_input_get_keyval(qiv, name, errp); + + *obj = g_strdup(str); + return !!str; +} + +static bool qobject_input_type_number(Visitor *v, const char *name, double *obj, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + QNum *qnum; + + if (!qobj) { + return false; + } + qnum = qobject_to(QNum, qobj); + if (!qnum) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "number"); + return false; + } + + *obj = qnum_get_double(qnum); + return true; +} + +static bool qobject_input_type_number_keyval(Visitor *v, const char *name, + double *obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + const char *str = qobject_input_get_keyval(qiv, name, errp); + double val; + + if (!str) { + return false; + } + + if (qemu_strtod_finite(str, NULL, &val)) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "number"); + return false; + } + + *obj = val; + return true; +} + +static bool qobject_input_type_any(Visitor *v, const char *name, QObject **obj, + Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + + *obj = NULL; + if (!qobj) { + return false; + } + + *obj = qobject_ref(qobj); + return true; +} + +static bool qobject_input_type_null(Visitor *v, const char *name, + QNull **obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_get_object(qiv, name, true, errp); + + *obj = NULL; + if (!qobj) { + return false; + } + + if (qobject_type(qobj) != QTYPE_QNULL) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, + full_name(qiv, name), "null"); + return false; + } + *obj = qnull(); + return true; +} + +static bool qobject_input_type_size_keyval(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + QObjectInputVisitor *qiv = to_qiv(v); + const char *str = qobject_input_get_keyval(qiv, name, errp); + + if (!str) { + return false; + } + + if (qemu_strtosz(str, NULL, obj) < 0) { + /* TODO report -ERANGE more nicely */ + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + full_name(qiv, name), "size"); + return false; + } + return true; +} + +static void qobject_input_optional(Visitor *v, const char *name, bool *present) +{ + QObjectInputVisitor *qiv = to_qiv(v); + QObject *qobj = qobject_input_try_get_object(qiv, name, false); + + if (!qobj) { + *present = false; + return; + } + + *present = true; +} + +static bool qobject_input_policy_reject(Visitor *v, const char *name, + unsigned special_features, + Error **errp) +{ + return !compat_policy_input_ok(special_features, &v->compat_policy, + ERROR_CLASS_GENERIC_ERROR, + "parameter", name, errp); +} + +static void qobject_input_free(Visitor *v) +{ + QObjectInputVisitor *qiv = to_qiv(v); + + while (!QSLIST_EMPTY(&qiv->stack)) { + StackObject *tos = QSLIST_FIRST(&qiv->stack); + + QSLIST_REMOVE_HEAD(&qiv->stack, node); + qobject_input_stack_object_free(tos); + } + + qobject_unref(qiv->root); + if (qiv->errname) { + g_string_free(qiv->errname, TRUE); + } + g_free(qiv); +} + +static QObjectInputVisitor *qobject_input_visitor_base_new(QObject *obj) +{ + QObjectInputVisitor *v = g_malloc0(sizeof(*v)); + + assert(obj); + + v->visitor.type = VISITOR_INPUT; + v->visitor.start_struct = qobject_input_start_struct; + v->visitor.check_struct = qobject_input_check_struct; + v->visitor.end_struct = qobject_input_end_struct; + v->visitor.start_list = qobject_input_start_list; + v->visitor.next_list = qobject_input_next_list; + v->visitor.check_list = qobject_input_check_list; + v->visitor.end_list = qobject_input_end_list; + v->visitor.start_alternate = qobject_input_start_alternate; + v->visitor.optional = qobject_input_optional; + v->visitor.policy_reject = qobject_input_policy_reject; + v->visitor.free = qobject_input_free; + + v->root = qobject_ref(obj); + + return v; +} + +Visitor *qobject_input_visitor_new(QObject *obj) +{ + QObjectInputVisitor *v = qobject_input_visitor_base_new(obj); + + v->visitor.type_int64 = qobject_input_type_int64; + v->visitor.type_uint64 = qobject_input_type_uint64; + v->visitor.type_bool = qobject_input_type_bool; + v->visitor.type_str = qobject_input_type_str; + v->visitor.type_number = qobject_input_type_number; + v->visitor.type_any = qobject_input_type_any; + v->visitor.type_null = qobject_input_type_null; + + return &v->visitor; +} + +Visitor *qobject_input_visitor_new_keyval(QObject *obj) +{ + QObjectInputVisitor *v = qobject_input_visitor_base_new(obj); + + v->visitor.type_int64 = qobject_input_type_int64_keyval; + v->visitor.type_uint64 = qobject_input_type_uint64_keyval; + v->visitor.type_bool = qobject_input_type_bool_keyval; + v->visitor.type_str = qobject_input_type_str_keyval; + v->visitor.type_number = qobject_input_type_number_keyval; + v->visitor.type_any = qobject_input_type_any; + v->visitor.type_null = qobject_input_type_null; + v->visitor.type_size = qobject_input_type_size_keyval; + v->keyval = true; + + return &v->visitor; +} + +Visitor *qobject_input_visitor_new_str(const char *str, + const char *implied_key, + Error **errp) +{ + bool is_json = str[0] == '{'; + QObject *obj; + QDict *args; + Visitor *v; + + if (is_json) { + obj = qobject_from_json(str, errp); + if (!obj) { + return NULL; + } + args = qobject_to(QDict, obj); + assert(args); + v = qobject_input_visitor_new(QOBJECT(args)); + } else { + args = keyval_parse(str, implied_key, NULL, errp); + if (!args) { + return NULL; + } + v = qobject_input_visitor_new_keyval(QOBJECT(args)); + } + qobject_unref(args); + + return v; +} diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c new file mode 100644 index 000000000..74770edd7 --- /dev/null +++ b/qapi/qobject-output-visitor.c @@ -0,0 +1,280 @@ +/* + * Core Definitions for QAPI/QMP Command Registry + * + * Copyright (C) 2012-2016 Red Hat, Inc. + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/compat-policy.h" +#include "qapi/qobject-output-visitor.h" +#include "qapi/visitor-impl.h" +#include "qemu/queue.h" +#include "qapi/qmp/qbool.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnull.h" +#include "qapi/qmp/qnum.h" +#include "qapi/qmp/qstring.h" + +typedef struct QStackEntry { + QObject *value; + void *qapi; /* sanity check that caller uses same pointer */ + QSLIST_ENTRY(QStackEntry) node; +} QStackEntry; + +struct QObjectOutputVisitor { + Visitor visitor; + + QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */ + QObject *root; /* Root of the output visit */ + QObject **result; /* User's storage location for result */ +}; + +#define qobject_output_add(qov, name, value) \ + qobject_output_add_obj(qov, name, QOBJECT(value)) +#define qobject_output_push(qov, value, qapi) \ + qobject_output_push_obj(qov, QOBJECT(value), qapi) + +static QObjectOutputVisitor *to_qov(Visitor *v) +{ + return container_of(v, QObjectOutputVisitor, visitor); +} + +/* Push @value onto the stack of current QObjects being built */ +static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value, + void *qapi) +{ + QStackEntry *e = g_malloc0(sizeof(*e)); + + assert(qov->root); + assert(value); + e->value = value; + e->qapi = qapi; + QSLIST_INSERT_HEAD(&qov->stack, e, node); +} + +/* Pop a value off the stack of QObjects being built, and return it. */ +static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi) +{ + QStackEntry *e = QSLIST_FIRST(&qov->stack); + QObject *value; + + assert(e); + assert(e->qapi == qapi); + QSLIST_REMOVE_HEAD(&qov->stack, node); + value = e->value; + assert(value); + g_free(e); + return value; +} + +/* Add @value to the current QObject being built. + * If the stack is visiting a dictionary or list, @value is now owned + * by that container. Otherwise, @value is now the root. */ +static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name, + QObject *value) +{ + QStackEntry *e = QSLIST_FIRST(&qov->stack); + QObject *cur = e ? e->value : NULL; + + if (!cur) { + /* Don't allow reuse of visitor on more than one root */ + assert(!qov->root); + qov->root = value; + } else { + switch (qobject_type(cur)) { + case QTYPE_QDICT: + assert(name); + qdict_put_obj(qobject_to(QDict, cur), name, value); + break; + case QTYPE_QLIST: + assert(!name); + qlist_append_obj(qobject_to(QList, cur), value); + break; + default: + g_assert_not_reached(); + } + } +} + +static bool qobject_output_start_struct(Visitor *v, const char *name, + void **obj, size_t unused, Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + QDict *dict = qdict_new(); + + qobject_output_add(qov, name, dict); + qobject_output_push(qov, dict, obj); + return true; +} + +static void qobject_output_end_struct(Visitor *v, void **obj) +{ + QObjectOutputVisitor *qov = to_qov(v); + QObject *value = qobject_output_pop(qov, obj); + assert(qobject_type(value) == QTYPE_QDICT); +} + +static bool qobject_output_start_list(Visitor *v, const char *name, + GenericList **listp, size_t size, + Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + QList *list = qlist_new(); + + qobject_output_add(qov, name, list); + qobject_output_push(qov, list, listp); + return true; +} + +static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail, + size_t size) +{ + return tail->next; +} + +static void qobject_output_end_list(Visitor *v, void **obj) +{ + QObjectOutputVisitor *qov = to_qov(v); + QObject *value = qobject_output_pop(qov, obj); + assert(qobject_type(value) == QTYPE_QLIST); +} + +static bool qobject_output_type_int64(Visitor *v, const char *name, + int64_t *obj, Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + qobject_output_add(qov, name, qnum_from_int(*obj)); + return true; +} + +static bool qobject_output_type_uint64(Visitor *v, const char *name, + uint64_t *obj, Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + qobject_output_add(qov, name, qnum_from_uint(*obj)); + return true; +} + +static bool qobject_output_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + qobject_output_add(qov, name, qbool_from_bool(*obj)); + return true; +} + +static bool qobject_output_type_str(Visitor *v, const char *name, char **obj, + Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + if (*obj) { + qobject_output_add(qov, name, qstring_from_str(*obj)); + } else { + qobject_output_add(qov, name, qstring_from_str("")); + } + return true; +} + +static bool qobject_output_type_number(Visitor *v, const char *name, + double *obj, Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + qobject_output_add(qov, name, qnum_from_double(*obj)); + return true; +} + +static bool qobject_output_type_any(Visitor *v, const char *name, + QObject **obj, Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + + qobject_output_add_obj(qov, name, qobject_ref(*obj)); + return true; +} + +static bool qobject_output_type_null(Visitor *v, const char *name, + QNull **obj, Error **errp) +{ + QObjectOutputVisitor *qov = to_qov(v); + qobject_output_add(qov, name, qnull()); + return true; +} + +static bool qobject_output_policy_skip(Visitor *v, const char *name, + unsigned special_features) +{ + CompatPolicy *pol = &v->compat_policy; + + return ((special_features & 1u << QAPI_DEPRECATED) + && pol->deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) + || ((special_features & 1u << QAPI_UNSTABLE) + && pol->unstable_output == COMPAT_POLICY_OUTPUT_HIDE); +} + +/* Finish building, and return the root object. + * The root object is never null. The caller becomes the object's + * owner, and should use qobject_unref() when done with it. */ +static void qobject_output_complete(Visitor *v, void *opaque) +{ + QObjectOutputVisitor *qov = to_qov(v); + + /* A visit must have occurred, with each start paired with end. */ + assert(qov->root && QSLIST_EMPTY(&qov->stack)); + assert(opaque == qov->result); + + *qov->result = qobject_ref(qov->root); + qov->result = NULL; +} + +static void qobject_output_free(Visitor *v) +{ + QObjectOutputVisitor *qov = to_qov(v); + QStackEntry *e; + + while (!QSLIST_EMPTY(&qov->stack)) { + e = QSLIST_FIRST(&qov->stack); + QSLIST_REMOVE_HEAD(&qov->stack, node); + g_free(e); + } + + qobject_unref(qov->root); + g_free(qov); +} + +Visitor *qobject_output_visitor_new(QObject **result) +{ + QObjectOutputVisitor *v; + + v = g_malloc0(sizeof(*v)); + + v->visitor.type = VISITOR_OUTPUT; + v->visitor.start_struct = qobject_output_start_struct; + v->visitor.end_struct = qobject_output_end_struct; + v->visitor.start_list = qobject_output_start_list; + v->visitor.next_list = qobject_output_next_list; + v->visitor.end_list = qobject_output_end_list; + v->visitor.type_int64 = qobject_output_type_int64; + v->visitor.type_uint64 = qobject_output_type_uint64; + v->visitor.type_bool = qobject_output_type_bool; + v->visitor.type_str = qobject_output_type_str; + v->visitor.type_number = qobject_output_type_number; + v->visitor.type_any = qobject_output_type_any; + v->visitor.type_null = qobject_output_type_null; + v->visitor.policy_skip = qobject_output_policy_skip; + v->visitor.complete = qobject_output_complete; + v->visitor.free = qobject_output_free; + + *result = NULL; + v->result = result; + + return &v->visitor; +} diff --git a/qapi/qom.json b/qapi/qom.json new file mode 100644 index 000000000..eeb5395ff --- /dev/null +++ b/qapi/qom.json @@ -0,0 +1,951 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +{ 'include': 'authz.json' } +{ 'include': 'block-core.json' } +{ 'include': 'common.json' } +{ 'include': 'crypto.json' } + +## +# = QEMU Object Model (QOM) +## + +## +# @ObjectPropertyInfo: +# +# @name: the name of the property +# +# @type: the type of the property. This will typically come in one of four +# forms: +# +# 1) A primitive type such as 'u8', 'u16', 'bool', 'str', or 'double'. +# These types are mapped to the appropriate JSON type. +# +# 2) A child type in the form 'child<subtype>' where subtype is a qdev +# device type name. Child properties create the composition tree. +# +# 3) A link type in the form 'link<subtype>' where subtype is a qdev +# device type name. Link properties form the device model graph. +# +# @description: if specified, the description of the property. +# +# @default-value: the default value, if any (since 5.0) +# +# Since: 1.2 +## +{ 'struct': 'ObjectPropertyInfo', + 'data': { 'name': 'str', + 'type': 'str', + '*description': 'str', + '*default-value': 'any' } } + +## +# @qom-list: +# +# This command will list any properties of a object given a path in the object +# model. +# +# @path: the path within the object model. See @qom-get for a description of +# this parameter. +# +# Returns: a list of @ObjectPropertyInfo that describe the properties of the +# object. +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "qom-list", +# "arguments": { "path": "/chardevs" } } +# <- { "return": [ { "name": "type", "type": "string" }, +# { "name": "parallel0", "type": "child<chardev-vc>" }, +# { "name": "serial0", "type": "child<chardev-vc>" }, +# { "name": "mon0", "type": "child<chardev-stdio>" } ] } +# +## +{ 'command': 'qom-list', + 'data': { 'path': 'str' }, + 'returns': [ 'ObjectPropertyInfo' ], + 'allow-preconfig': true } + +## +# @qom-get: +# +# This command will get a property from a object model path and return the +# value. +# +# @path: The path within the object model. There are two forms of supported +# paths--absolute and partial paths. +# +# Absolute paths are derived from the root object and can follow child<> +# or link<> properties. Since they can follow link<> properties, they +# can be arbitrarily long. Absolute paths look like absolute filenames +# and are prefixed with a leading slash. +# +# Partial paths look like relative filenames. They do not begin +# with a prefix. The matching rules for partial paths are subtle but +# designed to make specifying objects easy. At each level of the +# composition tree, the partial path is matched as an absolute path. +# The first match is not returned. At least two matches are searched +# for. A successful result is only returned if only one match is +# found. If more than one match is found, a flag is return to +# indicate that the match was ambiguous. +# +# @property: The property name to read +# +# Returns: The property value. The type depends on the property +# type. child<> and link<> properties are returned as #str +# pathnames. All integer property types (u8, u16, etc) are +# returned as #int. +# +# Since: 1.2 +# +# Example: +# +# 1. Use absolute path +# +# -> { "execute": "qom-get", +# "arguments": { "path": "/machine/unattached/device[0]", +# "property": "hotplugged" } } +# <- { "return": false } +# +# 2. Use partial path +# +# -> { "execute": "qom-get", +# "arguments": { "path": "unattached/sysbus", +# "property": "type" } } +# <- { "return": "System" } +# +## +{ 'command': 'qom-get', + 'data': { 'path': 'str', 'property': 'str' }, + 'returns': 'any', + 'allow-preconfig': true } + +## +# @qom-set: +# +# This command will set a property from a object model path. +# +# @path: see @qom-get for a description of this parameter +# +# @property: the property name to set +# +# @value: a value who's type is appropriate for the property type. See @qom-get +# for a description of type mapping. +# +# Since: 1.2 +# +# Example: +# +# -> { "execute": "qom-set", +# "arguments": { "path": "/machine", +# "property": "graphics", +# "value": false } } +# <- { "return": {} } +# +## +{ 'command': 'qom-set', + 'data': { 'path': 'str', 'property': 'str', 'value': 'any' }, + 'allow-preconfig': true } + +## +# @ObjectTypeInfo: +# +# This structure describes a search result from @qom-list-types +# +# @name: the type name found in the search +# +# @abstract: the type is abstract and can't be directly instantiated. +# Omitted if false. (since 2.10) +# +# @parent: Name of parent type, if any (since 2.10) +# +# Since: 1.1 +## +{ 'struct': 'ObjectTypeInfo', + 'data': { 'name': 'str', '*abstract': 'bool', '*parent': 'str' } } + +## +# @qom-list-types: +# +# This command will return a list of types given search parameters +# +# @implements: if specified, only return types that implement this type name +# +# @abstract: if true, include abstract types in the results +# +# Returns: a list of @ObjectTypeInfo or an empty list if no results are found +# +# Since: 1.1 +## +{ 'command': 'qom-list-types', + 'data': { '*implements': 'str', '*abstract': 'bool' }, + 'returns': [ 'ObjectTypeInfo' ], + 'allow-preconfig': true } + +## +# @qom-list-properties: +# +# List properties associated with a QOM object. +# +# @typename: the type name of an object +# +# Note: objects can create properties at runtime, for example to describe +# links between different devices and/or objects. These properties +# are not included in the output of this command. +# +# Returns: a list of ObjectPropertyInfo describing object properties +# +# Since: 2.12 +## +{ 'command': 'qom-list-properties', + 'data': { 'typename': 'str'}, + 'returns': [ 'ObjectPropertyInfo' ], + 'allow-preconfig': true } + +## +# @CanHostSocketcanProperties: +# +# Properties for can-host-socketcan objects. +# +# @if: interface name of the host system CAN bus to connect to +# +# @canbus: object ID of the can-bus object to connect to the host interface +# +# Since: 2.12 +## +{ 'struct': 'CanHostSocketcanProperties', + 'data': { 'if': 'str', + 'canbus': 'str' } } + +## +# @ColoCompareProperties: +# +# Properties for colo-compare objects. +# +# @primary_in: name of the character device backend to use for the primary +# input (incoming packets are redirected to @outdev) +# +# @secondary_in: name of the character device backend to use for secondary +# input (incoming packets are only compared to the input on +# @primary_in and then dropped) +# +# @outdev: name of the character device backend to use for output +# +# @iothread: name of the iothread to run in +# +# @notify_dev: name of the character device backend to be used to communicate +# with the remote colo-frame (only for Xen COLO) +# +# @compare_timeout: the maximum time to hold a packet from @primary_in for +# comparison with an incoming packet on @secondary_in in +# milliseconds (default: 3000) +# +# @expired_scan_cycle: the interval at which colo-compare checks whether +# packets from @primary have timed out, in milliseconds +# (default: 3000) +# +# @max_queue_size: the maximum number of packets to keep in the queue for +# comparing with incoming packets from @secondary_in. If the +# queue is full and additional packets are received, the +# additional packets are dropped. (default: 1024) +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.8 +## +{ 'struct': 'ColoCompareProperties', + 'data': { 'primary_in': 'str', + 'secondary_in': 'str', + 'outdev': 'str', + 'iothread': 'str', + '*notify_dev': 'str', + '*compare_timeout': 'uint64', + '*expired_scan_cycle': 'uint32', + '*max_queue_size': 'uint32', + '*vnet_hdr_support': 'bool' } } + +## +# @CryptodevBackendProperties: +# +# Properties for cryptodev-backend and cryptodev-backend-builtin objects. +# +# @queues: the number of queues for the cryptodev backend. Ignored for +# cryptodev-backend and must be 1 for cryptodev-backend-builtin. +# (default: 1) +# +# Since: 2.8 +## +{ 'struct': 'CryptodevBackendProperties', + 'data': { '*queues': 'uint32' } } + +## +# @CryptodevVhostUserProperties: +# +# Properties for cryptodev-vhost-user objects. +# +# @chardev: the name of a Unix domain socket character device that connects to +# the vhost-user server +# +# Since: 2.12 +## +{ 'struct': 'CryptodevVhostUserProperties', + 'base': 'CryptodevBackendProperties', + 'data': { 'chardev': 'str' } } + +## +# @DBusVMStateProperties: +# +# Properties for dbus-vmstate objects. +# +# @addr: the name of the DBus bus to connect to +# +# @id-list: a comma separated list of DBus IDs of helpers whose data should be +# included in the VM state on migration +# +# Since: 5.0 +## +{ 'struct': 'DBusVMStateProperties', + 'data': { 'addr': 'str' , + '*id-list': 'str' } } + +## +# @NetfilterInsert: +# +# Indicates where to insert a netfilter relative to a given other filter. +# +# @before: insert before the specified filter +# +# @behind: insert behind the specified filter +# +# Since: 5.0 +## +{ 'enum': 'NetfilterInsert', + 'data': [ 'before', 'behind' ] } + +## +# @NetfilterProperties: +# +# Properties for objects of classes derived from netfilter. +# +# @netdev: id of the network device backend to filter +# +# @queue: indicates which queue(s) to filter (default: all) +# +# @status: indicates whether the filter is enabled ("on") or disabled ("off") +# (default: "on") +# +# @position: specifies where the filter should be inserted in the filter list. +# "head" means the filter is inserted at the head of the filter list, +# before any existing filters. +# "tail" means the filter is inserted at the tail of the filter list, +# behind any existing filters (default). +# "id=<id>" means the filter is inserted before or behind the filter +# specified by <id>, depending on the @insert property. +# (default: "tail") +# +# @insert: where to insert the filter relative to the filter given in @position. +# Ignored if @position is "head" or "tail". (default: behind) +# +# Since: 2.5 +## +{ 'struct': 'NetfilterProperties', + 'data': { 'netdev': 'str', + '*queue': 'NetFilterDirection', + '*status': 'str', + '*position': 'str', + '*insert': 'NetfilterInsert' } } + +## +# @FilterBufferProperties: +# +# Properties for filter-buffer objects. +# +# @interval: a non-zero interval in microseconds. All packets arriving in the +# given interval are delayed until the end of the interval. +# +# Since: 2.5 +## +{ 'struct': 'FilterBufferProperties', + 'base': 'NetfilterProperties', + 'data': { 'interval': 'uint32' } } + +## +# @FilterDumpProperties: +# +# Properties for filter-dump objects. +# +# @file: the filename where the dumped packets should be stored +# +# @maxlen: maximum number of bytes in a packet that are stored (default: 65536) +# +# Since: 2.5 +## +{ 'struct': 'FilterDumpProperties', + 'base': 'NetfilterProperties', + 'data': { 'file': 'str', + '*maxlen': 'uint32' } } + +## +# @FilterMirrorProperties: +# +# Properties for filter-mirror objects. +# +# @outdev: the name of a character device backend to which all incoming packets +# are mirrored +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.6 +## +{ 'struct': 'FilterMirrorProperties', + 'base': 'NetfilterProperties', + 'data': { 'outdev': 'str', + '*vnet_hdr_support': 'bool' } } + +## +# @FilterRedirectorProperties: +# +# Properties for filter-redirector objects. +# +# At least one of @indev or @outdev must be present. If both are present, they +# must not refer to the same character device backend. +# +# @indev: the name of a character device backend from which packets are +# received and redirected to the filtered network device +# +# @outdev: the name of a character device backend to which all incoming packets +# are redirected +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.6 +## +{ 'struct': 'FilterRedirectorProperties', + 'base': 'NetfilterProperties', + 'data': { '*indev': 'str', + '*outdev': 'str', + '*vnet_hdr_support': 'bool' } } + +## +# @FilterRewriterProperties: +# +# Properties for filter-rewriter objects. +# +# @vnet_hdr_support: if true, vnet header support is enabled (default: false) +# +# Since: 2.8 +## +{ 'struct': 'FilterRewriterProperties', + 'base': 'NetfilterProperties', + 'data': { '*vnet_hdr_support': 'bool' } } + +## +# @InputBarrierProperties: +# +# Properties for input-barrier objects. +# +# @name: the screen name as declared in the screens section of barrier.conf +# +# @server: hostname of the Barrier server (default: "localhost") +# +# @port: TCP port of the Barrier server (default: "24800") +# +# @x-origin: x coordinate of the leftmost pixel on the guest screen +# (default: "0") +# +# @y-origin: y coordinate of the topmost pixel on the guest screen +# (default: "0") +# +# @width: the width of secondary screen in pixels (default: "1920") +# +# @height: the height of secondary screen in pixels (default: "1080") +# +# Since: 4.2 +## +{ 'struct': 'InputBarrierProperties', + 'data': { 'name': 'str', + '*server': 'str', + '*port': 'str', + '*x-origin': 'str', + '*y-origin': 'str', + '*width': 'str', + '*height': 'str' } } + +## +# @InputLinuxProperties: +# +# Properties for input-linux objects. +# +# @evdev: the path of the host evdev device to use +# +# @grab_all: if true, grab is toggled for all devices (e.g. both keyboard and +# mouse) instead of just one device (default: false) +# +# @repeat: enables auto-repeat events (default: false) +# +# @grab-toggle: the key or key combination that toggles device grab +# (default: ctrl-ctrl) +# +# Since: 2.6 +## +{ 'struct': 'InputLinuxProperties', + 'data': { 'evdev': 'str', + '*grab_all': 'bool', + '*repeat': 'bool', + '*grab-toggle': 'GrabToggleKeys' } } + +## +# @IothreadProperties: +# +# Properties for iothread objects. +# +# @poll-max-ns: the maximum number of nanoseconds to busy wait for events. +# 0 means polling is disabled (default: 32768 on POSIX hosts, +# 0 otherwise) +# +# @poll-grow: the multiplier used to increase the polling time when the +# algorithm detects it is missing events due to not polling long +# enough. 0 selects a default behaviour (default: 0) +# +# @poll-shrink: the divisor used to decrease the polling time when the +# algorithm detects it is spending too long polling without +# encountering events. 0 selects a default behaviour (default: 0) +# +# @aio-max-batch: maximum number of requests in a batch for the AIO engine, +# 0 means that the engine will use its default +# (default:0, since 6.1) +# +# Since: 2.0 +## +{ 'struct': 'IothreadProperties', + 'data': { '*poll-max-ns': 'int', + '*poll-grow': 'int', + '*poll-shrink': 'int', + '*aio-max-batch': 'int' } } + +## +# @MemoryBackendProperties: +# +# Properties for objects of classes derived from memory-backend. +# +# @merge: if true, mark the memory as mergeable (default depends on the machine +# type) +# +# @dump: if true, include the memory in core dumps (default depends on the +# machine type) +# +# @host-nodes: the list of NUMA host nodes to bind the memory to +# +# @policy: the NUMA policy (default: 'default') +# +# @prealloc: if true, preallocate memory (default: false) +# +# @prealloc-threads: number of CPU threads to use for prealloc (default: 1) +# +# @share: if false, the memory is private to QEMU; if true, it is shared +# (default: false) +# +# @reserve: if true, reserve swap space (or huge pages) if applicable +# (default: true) (since 6.1) +# +# @size: size of the memory region in bytes +# +# @x-use-canonical-path-for-ramblock-id: if true, the canoncial path is used +# for ramblock-id. Disable this for 4.0 +# machine types or older to allow +# migration with newer QEMU versions. +# (default: false generally, +# but true for machine types <= 4.0) +# +# Note: prealloc=true and reserve=false cannot be set at the same time. With +# reserve=true, the behavior depends on the operating system: for example, +# Linux will not reserve swap space for shared file mappings -- +# "not applicable". In contrast, reserve=false will bail out if it cannot +# be configured accordingly. +# +# Since: 2.1 +## +{ 'struct': 'MemoryBackendProperties', + 'data': { '*dump': 'bool', + '*host-nodes': ['uint16'], + '*merge': 'bool', + '*policy': 'HostMemPolicy', + '*prealloc': 'bool', + '*prealloc-threads': 'uint32', + '*share': 'bool', + '*reserve': 'bool', + 'size': 'size', + '*x-use-canonical-path-for-ramblock-id': 'bool' } } + +## +# @MemoryBackendFileProperties: +# +# Properties for memory-backend-file objects. +# +# @align: the base address alignment when QEMU mmap(2)s @mem-path. Some +# backend stores specified by @mem-path require an alignment different +# than the default one used by QEMU, e.g. the device DAX /dev/dax0.0 +# requires 2M alignment rather than 4K. In such cases, users can +# specify the required alignment via this option. +# 0 selects a default alignment (currently the page size). (default: 0) +# +# @discard-data: if true, the file contents can be destroyed when QEMU exits, +# to avoid unnecessarily flushing data to the backing file. Note +# that ``discard-data`` is only an optimization, and QEMU might +# not discard file contents if it aborts unexpectedly or is +# terminated using SIGKILL. (default: false) +# +# @mem-path: the path to either a shared memory or huge page filesystem mount +# +# @pmem: specifies whether the backing file specified by @mem-path is in +# host persistent memory that can be accessed using the SNIA NVM +# programming model (e.g. Intel NVDIMM). +# +# @readonly: if true, the backing file is opened read-only; if false, it is +# opened read-write. (default: false) +# +# Since: 2.1 +## +{ 'struct': 'MemoryBackendFileProperties', + 'base': 'MemoryBackendProperties', + 'data': { '*align': 'size', + '*discard-data': 'bool', + 'mem-path': 'str', + '*pmem': { 'type': 'bool', 'if': 'CONFIG_LIBPMEM' }, + '*readonly': 'bool' } } + +## +# @MemoryBackendMemfdProperties: +# +# Properties for memory-backend-memfd objects. +# +# The @share boolean option is true by default with memfd. +# +# @hugetlb: if true, the file to be created resides in the hugetlbfs filesystem +# (default: false) +# +# @hugetlbsize: the hugetlb page size on systems that support multiple hugetlb +# page sizes (it must be a power of 2 value supported by the +# system). 0 selects a default page size. This option is ignored +# if @hugetlb is false. (default: 0) +# +# @seal: if true, create a sealed-file, which will block further resizing of +# the memory (default: true) +# +# Since: 2.12 +## +{ 'struct': 'MemoryBackendMemfdProperties', + 'base': 'MemoryBackendProperties', + 'data': { '*hugetlb': 'bool', + '*hugetlbsize': 'size', + '*seal': 'bool' } } + +## +# @MemoryBackendEpcProperties: +# +# Properties for memory-backend-epc objects. +# +# The @share boolean option is true by default with epc +# +# The @merge boolean option is false by default with epc +# +# The @dump boolean option is false by default with epc +# +# Since: 6.2 +## +{ 'struct': 'MemoryBackendEpcProperties', + 'base': 'MemoryBackendProperties', + 'data': {} } + +## +# @PrManagerHelperProperties: +# +# Properties for pr-manager-helper objects. +# +# @path: the path to a Unix domain socket for connecting to the external helper +# +# Since: 2.11 +## +{ 'struct': 'PrManagerHelperProperties', + 'data': { 'path': 'str' } } + +## +# @QtestProperties: +# +# Properties for qtest objects. +# +# @chardev: the chardev to be used to receive qtest commands on. +# +# @log: the path to a log file +# +# Since: 6.0 +## +{ 'struct': 'QtestProperties', + 'data': { 'chardev': 'str', + '*log': 'str' } } + +## +# @RemoteObjectProperties: +# +# Properties for x-remote-object objects. +# +# @fd: file descriptor name previously passed via 'getfd' command +# +# @devid: the id of the device to be associated with the file descriptor +# +# Since: 6.0 +## +{ 'struct': 'RemoteObjectProperties', + 'data': { 'fd': 'str', 'devid': 'str' } } + +## +# @RngProperties: +# +# Properties for objects of classes derived from rng. +# +# @opened: if true, the device is opened immediately when applying this option +# and will probably fail when processing the next option. Don't use; +# only provided for compatibility. (default: false) +# +# Features: +# @deprecated: Member @opened is deprecated. Setting true doesn't make sense, +# and false is already the default. +# +# Since: 1.3 +## +{ 'struct': 'RngProperties', + 'data': { '*opened': { 'type': 'bool', 'features': ['deprecated'] } } } + +## +# @RngEgdProperties: +# +# Properties for rng-egd objects. +# +# @chardev: the name of a character device backend that provides the connection +# to the RNG daemon +# +# Since: 1.3 +## +{ 'struct': 'RngEgdProperties', + 'base': 'RngProperties', + 'data': { 'chardev': 'str' } } + +## +# @RngRandomProperties: +# +# Properties for rng-random objects. +# +# @filename: the filename of the device on the host to obtain entropy from +# (default: "/dev/urandom") +# +# Since: 1.3 +## +{ 'struct': 'RngRandomProperties', + 'base': 'RngProperties', + 'data': { '*filename': 'str' } } + +## +# @SevGuestProperties: +# +# Properties for sev-guest objects. +# +# @sev-device: SEV device to use (default: "/dev/sev") +# +# @dh-cert-file: guest owners DH certificate (encoded with base64) +# +# @session-file: guest owners session parameters (encoded with base64) +# +# @policy: SEV policy value (default: 0x1) +# +# @handle: SEV firmware handle (default: 0) +# +# @cbitpos: C-bit location in page table entry (default: 0) +# +# @reduced-phys-bits: number of bits in physical addresses that become +# unavailable when SEV is enabled +# +# @kernel-hashes: if true, add hashes of kernel/initrd/cmdline to a +# designated guest firmware page for measured boot +# with -kernel (default: false) (since 6.2) +# +# Since: 2.12 +## +{ 'struct': 'SevGuestProperties', + 'data': { '*sev-device': 'str', + '*dh-cert-file': 'str', + '*session-file': 'str', + '*policy': 'uint32', + '*handle': 'uint32', + '*cbitpos': 'uint32', + 'reduced-phys-bits': 'uint32', + '*kernel-hashes': 'bool' } } + +## +# @ObjectType: +# +# Features: +# @unstable: Member @x-remote-object is experimental. +# +# Since: 6.0 +## +{ 'enum': 'ObjectType', + 'data': [ + 'authz-list', + 'authz-listfile', + 'authz-pam', + 'authz-simple', + 'can-bus', + { 'name': 'can-host-socketcan', + 'if': 'CONFIG_LINUX' }, + 'colo-compare', + 'cryptodev-backend', + 'cryptodev-backend-builtin', + { 'name': 'cryptodev-vhost-user', + 'if': 'CONFIG_VHOST_CRYPTO' }, + 'dbus-vmstate', + 'filter-buffer', + 'filter-dump', + 'filter-mirror', + 'filter-redirector', + 'filter-replay', + 'filter-rewriter', + 'input-barrier', + { 'name': 'input-linux', + 'if': 'CONFIG_LINUX' }, + 'iothread', + { 'name': 'memory-backend-epc', + 'if': 'CONFIG_LINUX' }, + 'memory-backend-file', + { 'name': 'memory-backend-memfd', + 'if': 'CONFIG_LINUX' }, + 'memory-backend-ram', + 'pef-guest', + { 'name': 'pr-manager-helper', + 'if': 'CONFIG_LINUX' }, + 'qtest', + 'rng-builtin', + 'rng-egd', + { 'name': 'rng-random', + 'if': 'CONFIG_POSIX' }, + 'secret', + { 'name': 'secret_keyring', + 'if': 'CONFIG_SECRET_KEYRING' }, + 'sev-guest', + 's390-pv-guest', + 'throttle-group', + 'tls-creds-anon', + 'tls-creds-psk', + 'tls-creds-x509', + 'tls-cipher-suites', + { 'name': 'x-remote-object', 'features': [ 'unstable' ] } + ] } + +## +# @ObjectOptions: +# +# Describes the options of a user creatable QOM object. +# +# @qom-type: the class name for the object to be created +# +# @id: the name of the new object +# +# Since: 6.0 +## +{ 'union': 'ObjectOptions', + 'base': { 'qom-type': 'ObjectType', + 'id': 'str' }, + 'discriminator': 'qom-type', + 'data': { + 'authz-list': 'AuthZListProperties', + 'authz-listfile': 'AuthZListFileProperties', + 'authz-pam': 'AuthZPAMProperties', + 'authz-simple': 'AuthZSimpleProperties', + 'can-host-socketcan': { 'type': 'CanHostSocketcanProperties', + 'if': 'CONFIG_LINUX' }, + 'colo-compare': 'ColoCompareProperties', + 'cryptodev-backend': 'CryptodevBackendProperties', + 'cryptodev-backend-builtin': 'CryptodevBackendProperties', + 'cryptodev-vhost-user': { 'type': 'CryptodevVhostUserProperties', + 'if': 'CONFIG_VHOST_CRYPTO' }, + 'dbus-vmstate': 'DBusVMStateProperties', + 'filter-buffer': 'FilterBufferProperties', + 'filter-dump': 'FilterDumpProperties', + 'filter-mirror': 'FilterMirrorProperties', + 'filter-redirector': 'FilterRedirectorProperties', + 'filter-replay': 'NetfilterProperties', + 'filter-rewriter': 'FilterRewriterProperties', + 'input-barrier': 'InputBarrierProperties', + 'input-linux': { 'type': 'InputLinuxProperties', + 'if': 'CONFIG_LINUX' }, + 'iothread': 'IothreadProperties', + 'memory-backend-epc': { 'type': 'MemoryBackendEpcProperties', + 'if': 'CONFIG_LINUX' }, + 'memory-backend-file': 'MemoryBackendFileProperties', + 'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties', + 'if': 'CONFIG_LINUX' }, + 'memory-backend-ram': 'MemoryBackendProperties', + 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', + 'if': 'CONFIG_LINUX' }, + 'qtest': 'QtestProperties', + 'rng-builtin': 'RngProperties', + 'rng-egd': 'RngEgdProperties', + 'rng-random': { 'type': 'RngRandomProperties', + 'if': 'CONFIG_POSIX' }, + 'secret': 'SecretProperties', + 'secret_keyring': { 'type': 'SecretKeyringProperties', + 'if': 'CONFIG_SECRET_KEYRING' }, + 'sev-guest': 'SevGuestProperties', + 'throttle-group': 'ThrottleGroupProperties', + 'tls-creds-anon': 'TlsCredsAnonProperties', + 'tls-creds-psk': 'TlsCredsPskProperties', + 'tls-creds-x509': 'TlsCredsX509Properties', + 'tls-cipher-suites': 'TlsCredsProperties', + 'x-remote-object': 'RemoteObjectProperties' + } } + +## +# @object-add: +# +# Create a QOM object. +# +# Returns: Nothing on success +# Error if @qom-type is not a valid class name +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "object-add", +# "arguments": { "qom-type": "rng-random", "id": "rng1", +# "filename": "/dev/hwrng" } } +# <- { "return": {} } +# +## +{ 'command': 'object-add', 'data': 'ObjectOptions', 'boxed': true, + 'allow-preconfig': true } + +## +# @object-del: +# +# Remove a QOM object. +# +# @id: the name of the QOM object to remove +# +# Returns: Nothing on success +# Error if @id is not a valid id for a QOM object +# +# Since: 2.0 +# +# Example: +# +# -> { "execute": "object-del", "arguments": { "id": "rng1" } } +# <- { "return": {} } +# +## +{ 'command': 'object-del', 'data': {'id': 'str'}, + 'allow-preconfig': true } diff --git a/qapi/rdma.json b/qapi/rdma.json new file mode 100644 index 000000000..a1d2175a8 --- /dev/null +++ b/qapi/rdma.json @@ -0,0 +1,39 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = RDMA device +## + +## +# @RDMA_GID_STATUS_CHANGED: +# +# Emitted when guest driver adds/deletes GID to/from device +# +# @netdev: RoCE Network Device name +# +# @gid-status: Add or delete indication +# +# @subnet-prefix: Subnet Prefix +# +# @interface-id : Interface ID +# +# Since: 4.0 +# +# Example: +# +# <- {"timestamp": {"seconds": 1541579657, "microseconds": 986760}, +# "event": "RDMA_GID_STATUS_CHANGED", +# "data": +# {"netdev": "bridge0", +# "interface-id": 15880512517475447892, +# "gid-status": true, +# "subnet-prefix": 33022}} +# +## +{ 'event': 'RDMA_GID_STATUS_CHANGED', + 'data': { 'netdev' : 'str', + 'gid-status' : 'bool', + 'subnet-prefix' : 'uint64', + 'interface-id' : 'uint64' } } diff --git a/qapi/replay.json b/qapi/replay.json new file mode 100644 index 000000000..bfd83d759 --- /dev/null +++ b/qapi/replay.json @@ -0,0 +1,121 @@ +# -*- Mode: Python -*- +# + +## +# = Record/replay +## + +{ 'include': 'common.json' } + +## +# @ReplayMode: +# +# Mode of the replay subsystem. +# +# @none: normal execution mode. Replay or record are not enabled. +# +# @record: record mode. All non-deterministic data is written into the +# replay log. +# +# @play: replay mode. Non-deterministic data required for system execution +# is read from the log. +# +# Since: 2.5 +## +{ 'enum': 'ReplayMode', + 'data': [ 'none', 'record', 'play' ] } + +## +# @ReplayInfo: +# +# Record/replay information. +# +# @mode: current mode. +# +# @filename: name of the record/replay log file. +# It is present only in record or replay modes, when the log +# is recorded or replayed. +# +# @icount: current number of executed instructions. +# +# Since: 5.2 +# +## +{ 'struct': 'ReplayInfo', + 'data': { 'mode': 'ReplayMode', '*filename': 'str', 'icount': 'int' } } + +## +# @query-replay: +# +# Retrieve the record/replay information. +# It includes current instruction count which may be used for +# @replay-break and @replay-seek commands. +# +# Returns: record/replay information. +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "query-replay" } +# <- { "return": { "mode": "play", "filename": "log.rr", "icount": 220414 } } +# +## +{ 'command': 'query-replay', + 'returns': 'ReplayInfo' } + +## +# @replay-break: +# +# Set replay breakpoint at instruction count @icount. +# Execution stops when the specified instruction is reached. +# There can be at most one breakpoint. When breakpoint is set, any prior +# one is removed. The breakpoint may be set only in replay mode and only +# "in the future", i.e. at instruction counts greater than the current one. +# The current instruction count can be observed with @query-replay. +# +# @icount: instruction count to stop at +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "replay-break", "data": { "icount": 220414 } } +# +## +{ 'command': 'replay-break', 'data': { 'icount': 'int' } } + +## +# @replay-delete-break: +# +# Remove replay breakpoint which was set with @replay-break. +# The command is ignored when there are no replay breakpoints. +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "replay-delete-break" } +# +## +{ 'command': 'replay-delete-break' } + +## +# @replay-seek: +# +# Automatically proceed to the instruction count @icount, when +# replaying the execution. The command automatically loads nearest +# snapshot and replays the execution to find the desired instruction. +# When there is no preceding snapshot or the execution is not replayed, +# then the command fails. +# icount for the reference may be obtained with @query-replay command. +# +# @icount: target instruction count +# +# Since: 5.2 +# +# Example: +# +# -> { "execute": "replay-seek", "data": { "icount": 220414 } } +## +{ 'command': 'replay-seek', 'data': { 'icount': 'int' } } diff --git a/qapi/rocker.json b/qapi/rocker.json new file mode 100644 index 000000000..b48e49a89 --- /dev/null +++ b/qapi/rocker.json @@ -0,0 +1,342 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# = Rocker switch device +## + +## +# @RockerSwitch: +# +# Rocker switch information. +# +# @name: switch name +# +# @id: switch ID +# +# @ports: number of front-panel ports +# +# Since: 2.4 +## +{ 'struct': 'RockerSwitch', + 'data': { 'name': 'str', 'id': 'uint64', 'ports': 'uint32' } } + +## +# @query-rocker: +# +# Return rocker switch information. +# +# Returns: @Rocker information +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "query-rocker", "arguments": { "name": "sw1" } } +# <- { "return": {"name": "sw1", "ports": 2, "id": 1327446905938}} +# +## +{ 'command': 'query-rocker', + 'data': { 'name': 'str' }, + 'returns': 'RockerSwitch' } + +## +# @RockerPortDuplex: +# +# An eumeration of port duplex states. +# +# @half: half duplex +# +# @full: full duplex +# +# Since: 2.4 +## +{ 'enum': 'RockerPortDuplex', 'data': [ 'half', 'full' ] } + +## +# @RockerPortAutoneg: +# +# An eumeration of port autoneg states. +# +# @off: autoneg is off +# +# @on: autoneg is on +# +# Since: 2.4 +## +{ 'enum': 'RockerPortAutoneg', 'data': [ 'off', 'on' ] } + +## +# @RockerPort: +# +# Rocker switch port information. +# +# @name: port name +# +# @enabled: port is enabled for I/O +# +# @link-up: physical link is UP on port +# +# @speed: port link speed in Mbps +# +# @duplex: port link duplex +# +# @autoneg: port link autoneg +# +# Since: 2.4 +## +{ 'struct': 'RockerPort', + 'data': { 'name': 'str', 'enabled': 'bool', 'link-up': 'bool', + 'speed': 'uint32', 'duplex': 'RockerPortDuplex', + 'autoneg': 'RockerPortAutoneg' } } + +## +# @query-rocker-ports: +# +# Return rocker switch port information. +# +# Returns: a list of @RockerPort information +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "query-rocker-ports", "arguments": { "name": "sw1" } } +# <- { "return": [ {"duplex": "full", "enabled": true, "name": "sw1.1", +# "autoneg": "off", "link-up": true, "speed": 10000}, +# {"duplex": "full", "enabled": true, "name": "sw1.2", +# "autoneg": "off", "link-up": true, "speed": 10000} +# ]} +# +## +{ 'command': 'query-rocker-ports', + 'data': { 'name': 'str' }, + 'returns': ['RockerPort'] } + +## +# @RockerOfDpaFlowKey: +# +# Rocker switch OF-DPA flow key +# +# @priority: key priority, 0 being lowest priority +# +# @tbl-id: flow table ID +# +# @in-pport: physical input port +# +# @tunnel-id: tunnel ID +# +# @vlan-id: VLAN ID +# +# @eth-type: Ethernet header type +# +# @eth-src: Ethernet header source MAC address +# +# @eth-dst: Ethernet header destination MAC address +# +# @ip-proto: IP Header protocol field +# +# @ip-tos: IP header TOS field +# +# @ip-dst: IP header destination address +# +# Note: optional members may or may not appear in the flow key +# depending if they're relevant to the flow key. +# +# Since: 2.4 +## +{ 'struct': 'RockerOfDpaFlowKey', + 'data' : { 'priority': 'uint32', 'tbl-id': 'uint32', '*in-pport': 'uint32', + '*tunnel-id': 'uint32', '*vlan-id': 'uint16', + '*eth-type': 'uint16', '*eth-src': 'str', '*eth-dst': 'str', + '*ip-proto': 'uint8', '*ip-tos': 'uint8', '*ip-dst': 'str' } } + +## +# @RockerOfDpaFlowMask: +# +# Rocker switch OF-DPA flow mask +# +# @in-pport: physical input port +# +# @tunnel-id: tunnel ID +# +# @vlan-id: VLAN ID +# +# @eth-src: Ethernet header source MAC address +# +# @eth-dst: Ethernet header destination MAC address +# +# @ip-proto: IP Header protocol field +# +# @ip-tos: IP header TOS field +# +# Note: optional members may or may not appear in the flow mask +# depending if they're relevant to the flow mask. +# +# Since: 2.4 +## +{ 'struct': 'RockerOfDpaFlowMask', + 'data' : { '*in-pport': 'uint32', '*tunnel-id': 'uint32', + '*vlan-id': 'uint16', '*eth-src': 'str', '*eth-dst': 'str', + '*ip-proto': 'uint8', '*ip-tos': 'uint8' } } + +## +# @RockerOfDpaFlowAction: +# +# Rocker switch OF-DPA flow action +# +# @goto-tbl: next table ID +# +# @group-id: group ID +# +# @tunnel-lport: tunnel logical port ID +# +# @vlan-id: VLAN ID +# +# @new-vlan-id: new VLAN ID +# +# @out-pport: physical output port +# +# Note: optional members may or may not appear in the flow action +# depending if they're relevant to the flow action. +# +# Since: 2.4 +## +{ 'struct': 'RockerOfDpaFlowAction', + 'data' : { '*goto-tbl': 'uint32', '*group-id': 'uint32', + '*tunnel-lport': 'uint32', '*vlan-id': 'uint16', + '*new-vlan-id': 'uint16', '*out-pport': 'uint32' } } + +## +# @RockerOfDpaFlow: +# +# Rocker switch OF-DPA flow +# +# @cookie: flow unique cookie ID +# +# @hits: count of matches (hits) on flow +# +# @key: flow key +# +# @mask: flow mask +# +# @action: flow action +# +# Since: 2.4 +## +{ 'struct': 'RockerOfDpaFlow', + 'data': { 'cookie': 'uint64', 'hits': 'uint64', 'key': 'RockerOfDpaFlowKey', + 'mask': 'RockerOfDpaFlowMask', 'action': 'RockerOfDpaFlowAction' } } + +## +# @query-rocker-of-dpa-flows: +# +# Return rocker OF-DPA flow information. +# +# @name: switch name +# +# @tbl-id: flow table ID. If tbl-id is not specified, returns +# flow information for all tables. +# +# Returns: rocker OF-DPA flow information +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "query-rocker-of-dpa-flows", +# "arguments": { "name": "sw1" } } +# <- { "return": [ {"key": {"in-pport": 0, "priority": 1, "tbl-id": 0}, +# "hits": 138, +# "cookie": 0, +# "action": {"goto-tbl": 10}, +# "mask": {"in-pport": 4294901760} +# }, +# {...more...}, +# ]} +# +## +{ 'command': 'query-rocker-of-dpa-flows', + 'data': { 'name': 'str', '*tbl-id': 'uint32' }, + 'returns': ['RockerOfDpaFlow'] } + +## +# @RockerOfDpaGroup: +# +# Rocker switch OF-DPA group +# +# @id: group unique ID +# +# @type: group type +# +# @vlan-id: VLAN ID +# +# @pport: physical port number +# +# @index: group index, unique with group type +# +# @out-pport: output physical port number +# +# @group-id: next group ID +# +# @set-vlan-id: VLAN ID to set +# +# @pop-vlan: pop VLAN headr from packet +# +# @group-ids: list of next group IDs +# +# @set-eth-src: set source MAC address in Ethernet header +# +# @set-eth-dst: set destination MAC address in Ethernet header +# +# @ttl-check: perform TTL check +# +# Note: optional members may or may not appear in the group depending +# if they're relevant to the group type. +# +# Since: 2.4 +## +{ 'struct': 'RockerOfDpaGroup', + 'data': { 'id': 'uint32', 'type': 'uint8', '*vlan-id': 'uint16', + '*pport': 'uint32', '*index': 'uint32', '*out-pport': 'uint32', + '*group-id': 'uint32', '*set-vlan-id': 'uint16', + '*pop-vlan': 'uint8', '*group-ids': ['uint32'], + '*set-eth-src': 'str', '*set-eth-dst': 'str', + '*ttl-check': 'uint8' } } + +## +# @query-rocker-of-dpa-groups: +# +# Return rocker OF-DPA group information. +# +# @name: switch name +# +# @type: group type. If type is not specified, returns +# group information for all group types. +# +# Returns: rocker OF-DPA group information +# +# Since: 2.4 +# +# Example: +# +# -> { "execute": "query-rocker-of-dpa-groups", +# "arguments": { "name": "sw1" } } +# <- { "return": [ {"type": 0, "out-pport": 2, +# "pport": 2, "vlan-id": 3841, +# "pop-vlan": 1, "id": 251723778}, +# {"type": 0, "out-pport": 0, +# "pport": 0, "vlan-id": 3841, +# "pop-vlan": 1, "id": 251723776}, +# {"type": 0, "out-pport": 1, +# "pport": 1, "vlan-id": 3840, +# "pop-vlan": 1, "id": 251658241}, +# {"type": 0, "out-pport": 0, +# "pport": 0, "vlan-id": 3840, +# "pop-vlan": 1, "id": 251658240} +# ]} +# +## +{ 'command': 'query-rocker-of-dpa-groups', + 'data': { 'name': 'str', '*type': 'uint8' }, + 'returns': ['RockerOfDpaGroup'] } diff --git a/qapi/run-state.json b/qapi/run-state.json new file mode 100644 index 000000000..43d66d700 --- /dev/null +++ b/qapi/run-state.json @@ -0,0 +1,640 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = VM run state +## + +## +# @RunState: +# +# An enumeration of VM run states. +# +# @debug: QEMU is running on a debugger +# +# @finish-migrate: guest is paused to finish the migration process +# +# @inmigrate: guest is paused waiting for an incoming migration. Note +# that this state does not tell whether the machine will start at the +# end of the migration. This depends on the command-line -S option and +# any invocation of 'stop' or 'cont' that has happened since QEMU was +# started. +# +# @internal-error: An internal error that prevents further guest execution +# has occurred +# +# @io-error: the last IOP has failed and the device is configured to pause +# on I/O errors +# +# @paused: guest has been paused via the 'stop' command +# +# @postmigrate: guest is paused following a successful 'migrate' +# +# @prelaunch: QEMU was started with -S and guest has not started +# +# @restore-vm: guest is paused to restore VM state +# +# @running: guest is actively running +# +# @save-vm: guest is paused to save the VM state +# +# @shutdown: guest is shut down (and -no-shutdown is in use) +# +# @suspended: guest is suspended (ACPI S3) +# +# @watchdog: the watchdog action is configured to pause and has been triggered +# +# @guest-panicked: guest has been panicked as a result of guest OS panic +# +# @colo: guest is paused to save/restore VM state under colo checkpoint, +# VM can not get into this state unless colo capability is enabled +# for migration. (since 2.8) +## +{ 'enum': 'RunState', + 'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused', + 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm', + 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog', + 'guest-panicked', 'colo' ] } + +## +# @ShutdownCause: +# +# An enumeration of reasons for a Shutdown. +# +# @none: No shutdown request pending +# +# @host-error: An error prevents further use of guest +# +# @host-qmp-quit: Reaction to the QMP command 'quit' +# +# @host-qmp-system-reset: Reaction to the QMP command 'system_reset' +# +# @host-signal: Reaction to a signal, such as SIGINT +# +# @host-ui: Reaction to a UI event, like window close +# +# @guest-shutdown: Guest shutdown/suspend request, via ACPI or other +# hardware-specific means +# +# @guest-reset: Guest reset request, and command line turns that into +# a shutdown +# +# @guest-panic: Guest panicked, and command line turns that into a shutdown +# +# @subsystem-reset: Partial guest reset that does not trigger QMP events and +# ignores --no-reboot. This is useful for sanitizing +# hypercalls on s390 that are used during kexec/kdump/boot +# +## +{ 'enum': 'ShutdownCause', + # Beware, shutdown_caused_by_guest() depends on enumeration order + 'data': [ 'none', 'host-error', 'host-qmp-quit', 'host-qmp-system-reset', + 'host-signal', 'host-ui', 'guest-shutdown', 'guest-reset', + 'guest-panic', 'subsystem-reset'] } + +## +# @StatusInfo: +# +# Information about VCPU run state +# +# @running: true if all VCPUs are runnable, false if not runnable +# +# @singlestep: true if VCPUs are in single-step mode +# +# @status: the virtual machine @RunState +# +# Since: 0.14 +# +# Notes: @singlestep is enabled through the GDB stub +## +{ 'struct': 'StatusInfo', + 'data': {'running': 'bool', 'singlestep': 'bool', 'status': 'RunState'} } + +## +# @query-status: +# +# Query the run status of all VCPUs +# +# Returns: @StatusInfo reflecting all VCPUs +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-status" } +# <- { "return": { "running": true, +# "singlestep": false, +# "status": "running" } } +# +## +{ 'command': 'query-status', 'returns': 'StatusInfo', + 'allow-preconfig': true } + +## +# @SHUTDOWN: +# +# Emitted when the virtual machine has shut down, indicating that qemu is +# about to exit. +# +# @guest: If true, the shutdown was triggered by a guest request (such as +# a guest-initiated ACPI shutdown request or other hardware-specific action) +# rather than a host request (such as sending qemu a SIGINT). (since 2.10) +# +# @reason: The @ShutdownCause which resulted in the SHUTDOWN. (since 4.0) +# +# Note: If the command-line option "-no-shutdown" has been specified, qemu will +# not exit, and a STOP event will eventually follow the SHUTDOWN event +# +# Since: 0.12 +# +# Example: +# +# <- { "event": "SHUTDOWN", "data": { "guest": true }, +# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } } +# +## +{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } } + +## +# @POWERDOWN: +# +# Emitted when the virtual machine is powered down through the power control +# system, such as via ACPI. +# +# Since: 0.12 +# +# Example: +# +# <- { "event": "POWERDOWN", +# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } } +# +## +{ 'event': 'POWERDOWN' } + +## +# @RESET: +# +# Emitted when the virtual machine is reset +# +# @guest: If true, the reset was triggered by a guest request (such as +# a guest-initiated ACPI reboot request or other hardware-specific action) +# rather than a host request (such as the QMP command system_reset). +# (since 2.10) +# +# @reason: The @ShutdownCause of the RESET. (since 4.0) +# +# Since: 0.12 +# +# Example: +# +# <- { "event": "RESET", "data": { "guest": false }, +# "timestamp": { "seconds": 1267041653, "microseconds": 9518 } } +# +## +{ 'event': 'RESET', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } } + +## +# @STOP: +# +# Emitted when the virtual machine is stopped +# +# Since: 0.12 +# +# Example: +# +# <- { "event": "STOP", +# "timestamp": { "seconds": 1267041730, "microseconds": 281295 } } +# +## +{ 'event': 'STOP' } + +## +# @RESUME: +# +# Emitted when the virtual machine resumes execution +# +# Since: 0.12 +# +# Example: +# +# <- { "event": "RESUME", +# "timestamp": { "seconds": 1271770767, "microseconds": 582542 } } +# +## +{ 'event': 'RESUME' } + +## +# @SUSPEND: +# +# Emitted when guest enters a hardware suspension state, for example, S3 state, +# which is sometimes called standby state +# +# Since: 1.1 +# +# Example: +# +# <- { "event": "SUSPEND", +# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } } +# +## +{ 'event': 'SUSPEND' } + +## +# @SUSPEND_DISK: +# +# Emitted when guest enters a hardware suspension state with data saved on +# disk, for example, S4 state, which is sometimes called hibernate state +# +# Note: QEMU shuts down (similar to event @SHUTDOWN) when entering this state +# +# Since: 1.2 +# +# Example: +# +# <- { "event": "SUSPEND_DISK", +# "timestamp": { "seconds": 1344456160, "microseconds": 309119 } } +# +## +{ 'event': 'SUSPEND_DISK' } + +## +# @WAKEUP: +# +# Emitted when the guest has woken up from suspend state and is running +# +# Since: 1.1 +# +# Example: +# +# <- { "event": "WAKEUP", +# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } } +# +## +{ 'event': 'WAKEUP' } + +## +# @WATCHDOG: +# +# Emitted when the watchdog device's timer is expired +# +# @action: action that has been taken +# +# Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is +# followed respectively by the RESET, SHUTDOWN, or STOP events +# +# Note: This event is rate-limited. +# +# Since: 0.13 +# +# Example: +# +# <- { "event": "WATCHDOG", +# "data": { "action": "reset" }, +# "timestamp": { "seconds": 1267061043, "microseconds": 959568 } } +# +## +{ 'event': 'WATCHDOG', + 'data': { 'action': 'WatchdogAction' } } + +## +# @WatchdogAction: +# +# An enumeration of the actions taken when the watchdog device's timer is +# expired +# +# @reset: system resets +# +# @shutdown: system shutdown, note that it is similar to @powerdown, which +# tries to set to system status and notify guest +# +# @poweroff: system poweroff, the emulator program exits +# +# @pause: system pauses, similar to @stop +# +# @debug: system enters debug state +# +# @none: nothing is done +# +# @inject-nmi: a non-maskable interrupt is injected into the first VCPU (all +# VCPUS on x86) (since 2.4) +# +# Since: 2.1 +## +{ 'enum': 'WatchdogAction', + 'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none', + 'inject-nmi' ] } + +## +# @RebootAction: +# +# Possible QEMU actions upon guest reboot +# +# @reset: Reset the VM +# +# @shutdown: Shutdown the VM and exit, according to the shutdown action +# +# Since: 6.0 +## +{ 'enum': 'RebootAction', + 'data': [ 'reset', 'shutdown' ] } + +## +# @ShutdownAction: +# +# Possible QEMU actions upon guest shutdown +# +# @poweroff: Shutdown the VM and exit +# +# @pause: pause the VM# +# +# Since: 6.0 +## +{ 'enum': 'ShutdownAction', + 'data': [ 'poweroff', 'pause' ] } + +## +# @PanicAction: +# +# @none: Continue VM execution +# +# @pause: Pause the VM +# +# @shutdown: Shutdown the VM and exit, according to the shutdown action +# +# Since: 6.0 +## +{ 'enum': 'PanicAction', + 'data': [ 'pause', 'shutdown', 'none' ] } + +## +# @watchdog-set-action: +# +# Set watchdog action +# +# Since: 2.11 +## +{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} } + +## +# @set-action: +# +# Set the actions that will be taken by the emulator in response to guest +# events. +# +# @reboot: @RebootAction action taken on guest reboot. +# +# @shutdown: @ShutdownAction action taken on guest shutdown. +# +# @panic: @PanicAction action taken on guest panic. +# +# @watchdog: @WatchdogAction action taken when watchdog timer expires . +# +# Returns: Nothing on success. +# +# Since: 6.0 +# +# Example: +# +# -> { "execute": "set-action", +# "arguments": { "reboot": "shutdown", +# "shutdown" : "pause", +# "panic": "pause", +# "watchdog": "inject-nmi" } } +# <- { "return": {} } +## +{ 'command': 'set-action', + 'data': { '*reboot': 'RebootAction', + '*shutdown': 'ShutdownAction', + '*panic': 'PanicAction', + '*watchdog': 'WatchdogAction' }, + 'allow-preconfig': true } + +## +# @GUEST_PANICKED: +# +# Emitted when guest OS panic is detected +# +# @action: action that has been taken, currently always "pause" +# +# @info: information about a panic (since 2.9) +# +# Since: 1.5 +# +# Example: +# +# <- { "event": "GUEST_PANICKED", +# "data": { "action": "pause" } } +# +## +{ 'event': 'GUEST_PANICKED', + 'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } } + +## +# @GUEST_CRASHLOADED: +# +# Emitted when guest OS crash loaded is detected +# +# @action: action that has been taken, currently always "run" +# +# @info: information about a panic +# +# Since: 5.0 +# +# Example: +# +# <- { "event": "GUEST_CRASHLOADED", +# "data": { "action": "run" } } +# +## +{ 'event': 'GUEST_CRASHLOADED', + 'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } } + +## +# @GuestPanicAction: +# +# An enumeration of the actions taken when guest OS panic is detected +# +# @pause: system pauses +# +# Since: 2.1 (poweroff since 2.8, run since 5.0) +## +{ 'enum': 'GuestPanicAction', + 'data': [ 'pause', 'poweroff', 'run' ] } + +## +# @GuestPanicInformationType: +# +# An enumeration of the guest panic information types +# +# @hyper-v: hyper-v guest panic information type +# +# @s390: s390 guest panic information type (Since: 2.12) +# +# Since: 2.9 +## +{ 'enum': 'GuestPanicInformationType', + 'data': [ 'hyper-v', 's390' ] } + +## +# @GuestPanicInformation: +# +# Information about a guest panic +# +# @type: Crash type that defines the hypervisor specific information +# +# Since: 2.9 +## +{'union': 'GuestPanicInformation', + 'base': {'type': 'GuestPanicInformationType'}, + 'discriminator': 'type', + 'data': { 'hyper-v': 'GuestPanicInformationHyperV', + 's390': 'GuestPanicInformationS390' } } + +## +# @GuestPanicInformationHyperV: +# +# Hyper-V specific guest panic information (HV crash MSRs) +# +# Since: 2.9 +## +{'struct': 'GuestPanicInformationHyperV', + 'data': { 'arg1': 'uint64', + 'arg2': 'uint64', + 'arg3': 'uint64', + 'arg4': 'uint64', + 'arg5': 'uint64' } } + +## +# @S390CrashReason: +# +# Reason why the CPU is in a crashed state. +# +# @unknown: no crash reason was set +# +# @disabled-wait: the CPU has entered a disabled wait state +# +# @extint-loop: clock comparator or cpu timer interrupt with new PSW enabled +# for external interrupts +# +# @pgmint-loop: program interrupt with BAD new PSW +# +# @opint-loop: operation exception interrupt with invalid code at the program +# interrupt new PSW +# +# Since: 2.12 +## +{ 'enum': 'S390CrashReason', + 'data': [ 'unknown', + 'disabled-wait', + 'extint-loop', + 'pgmint-loop', + 'opint-loop' ] } + +## +# @GuestPanicInformationS390: +# +# S390 specific guest panic information (PSW) +# +# @core: core id of the CPU that crashed +# @psw-mask: control fields of guest PSW +# @psw-addr: guest instruction address +# @reason: guest crash reason +# +# Since: 2.12 +## +{'struct': 'GuestPanicInformationS390', + 'data': { 'core': 'uint32', + 'psw-mask': 'uint64', + 'psw-addr': 'uint64', + 'reason': 'S390CrashReason' } } + +## +# @MEMORY_FAILURE: +# +# Emitted when a memory failure occurs on host side. +# +# @recipient: recipient is defined as @MemoryFailureRecipient. +# +# @action: action that has been taken. action is defined as @MemoryFailureAction. +# +# @flags: flags for MemoryFailureAction. action is defined as @MemoryFailureFlags. +# +# Since: 5.2 +# +# Example: +# +# <- { "event": "MEMORY_FAILURE", +# "data": { "recipient": "hypervisor", +# "action": "fatal", +# "flags": { 'action-required': false } } +# +## +{ 'event': 'MEMORY_FAILURE', + 'data': { 'recipient': 'MemoryFailureRecipient', + 'action': 'MemoryFailureAction', + 'flags': 'MemoryFailureFlags'} } + +## +# @MemoryFailureRecipient: +# +# Hardware memory failure occurs, handled by recipient. +# +# @hypervisor: memory failure at QEMU process address space. +# (none guest memory, but used by QEMU itself). +# +# @guest: memory failure at guest memory, +# +# Since: 5.2 +# +## +{ 'enum': 'MemoryFailureRecipient', + 'data': [ 'hypervisor', + 'guest' ] } + + +## +# @MemoryFailureAction: +# +# Actions taken by QEMU in response to a hardware memory failure. +# +# @ignore: the memory failure could be ignored. This will only be the case +# for action-optional failures. +# +# @inject: memory failure occurred in guest memory, the guest enabled MCE +# handling mechanism, and QEMU could inject the MCE into the guest +# successfully. +# +# @fatal: the failure is unrecoverable. This occurs for action-required +# failures if the recipient is the hypervisor; QEMU will exit. +# +# @reset: the failure is unrecoverable but confined to the guest. This +# occurs if the recipient is a guest guest which is not ready +# to handle memory failures. +# +# Since: 5.2 +# +## +{ 'enum': 'MemoryFailureAction', + 'data': [ 'ignore', + 'inject', + 'fatal', + 'reset' ] } + +## +# @MemoryFailureFlags: +# +# Additional information on memory failures. +# +# @action-required: whether a memory failure event is action-required +# or action-optional (e.g. a failure during memory scrub). +# +# @recursive: whether the failure occurred while the previous +# failure was still in progress. +# +# Since: 5.2 +# +## +{ 'struct': 'MemoryFailureFlags', + 'data': { 'action-required': 'bool', + 'recursive': 'bool'} } diff --git a/qapi/sockets.json b/qapi/sockets.json new file mode 100644 index 000000000..5773d9fcc --- /dev/null +++ b/qapi/sockets.json @@ -0,0 +1,202 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# = Socket data types +## + +{ 'include': 'common.json' } + +## +# @NetworkAddressFamily: +# +# The network address family +# +# @ipv4: IPV4 family +# +# @ipv6: IPV6 family +# +# @unix: unix socket +# +# @vsock: vsock family (since 2.8) +# +# @unknown: otherwise +# +# Since: 2.1 +## +{ 'enum': 'NetworkAddressFamily', + 'data': [ 'ipv4', 'ipv6', 'unix', 'vsock', 'unknown' ] } + +## +# @InetSocketAddressBase: +# +# @host: host part of the address +# @port: port part of the address +## +{ 'struct': 'InetSocketAddressBase', + 'data': { + 'host': 'str', + 'port': 'str' } } + +## +# @InetSocketAddress: +# +# Captures a socket address or address range in the Internet namespace. +# +# @numeric: true if the host/port are guaranteed to be numeric, +# false if name resolution should be attempted. Defaults to false. +# (Since 2.9) +# +# @to: If present, this is range of possible addresses, with port +# between @port and @to. +# +# @ipv4: whether to accept IPv4 addresses, default try both IPv4 and IPv6 +# +# @ipv6: whether to accept IPv6 addresses, default try both IPv4 and IPv6 +# +# @keep-alive: enable keep-alive when connecting to this socket. Not supported +# for passive sockets. (Since 4.2) +# +# @mptcp: enable multi-path TCP. (Since 6.1) +# +# Since: 1.3 +## +{ 'struct': 'InetSocketAddress', + 'base': 'InetSocketAddressBase', + 'data': { + '*numeric': 'bool', + '*to': 'uint16', + '*ipv4': 'bool', + '*ipv6': 'bool', + '*keep-alive': 'bool', + '*mptcp': { 'type': 'bool', 'if': 'HAVE_IPPROTO_MPTCP' } } } + +## +# @UnixSocketAddress: +# +# Captures a socket address in the local ("Unix socket") namespace. +# +# @path: filesystem path to use +# @abstract: if true, this is a Linux abstract socket address. @path +# will be prefixed by a null byte, and optionally padded +# with null bytes. Defaults to false. (Since 5.1) +# @tight: if false, pad an abstract socket address with enough null +# bytes to make it fill struct sockaddr_un member sun_path. +# Defaults to true. (Since 5.1) +# +# Since: 1.3 +## +{ 'struct': 'UnixSocketAddress', + 'data': { + 'path': 'str', + '*abstract': { 'type': 'bool', 'if': 'CONFIG_LINUX' }, + '*tight': { 'type': 'bool', 'if': 'CONFIG_LINUX' } } } + +## +# @VsockSocketAddress: +# +# Captures a socket address in the vsock namespace. +# +# @cid: unique host identifier +# @port: port +# +# Note: string types are used to allow for possible future hostname or +# service resolution support. +# +# Since: 2.8 +## +{ 'struct': 'VsockSocketAddress', + 'data': { + 'cid': 'str', + 'port': 'str' } } + +## +# @InetSocketAddressWrapper: +# +# Since: 1.3 +## +{ 'struct': 'InetSocketAddressWrapper', + 'data': { 'data': 'InetSocketAddress' } } + +## +# @UnixSocketAddressWrapper: +# +# Since: 1.3 +## +{ 'struct': 'UnixSocketAddressWrapper', + 'data': { 'data': 'UnixSocketAddress' } } + +## +# @VsockSocketAddressWrapper: +# +# Since: 2.8 +## +{ 'struct': 'VsockSocketAddressWrapper', + 'data': { 'data': 'VsockSocketAddress' } } + +## +# @StringWrapper: +# +# Since: 1.3 +## +{ 'struct': 'StringWrapper', + 'data': { 'data': 'String' } } + +## +# @SocketAddressLegacy: +# +# Captures the address of a socket, which could also be a named file descriptor +# +# Note: This type is deprecated in favor of SocketAddress. The +# difference between SocketAddressLegacy and SocketAddress is that the +# latter is has fewer {} on the wire. +# +# Since: 1.3 +## +{ 'union': 'SocketAddressLegacy', + 'base': { 'type': 'SocketAddressType' }, + 'discriminator': 'type', + 'data': { + 'inet': 'InetSocketAddressWrapper', + 'unix': 'UnixSocketAddressWrapper', + 'vsock': 'VsockSocketAddressWrapper', + 'fd': 'StringWrapper' } } + +## +# @SocketAddressType: +# +# Available SocketAddress types +# +# @inet: Internet address +# +# @unix: Unix domain socket +# +# @vsock: VMCI address +# +# @fd: decimal is for file descriptor number, otherwise a file descriptor name. +# Named file descriptors are permitted in monitor commands, in combination +# with the 'getfd' command. Decimal file descriptors are permitted at +# startup or other contexts where no monitor context is active. +# +# Since: 2.9 +## +{ 'enum': 'SocketAddressType', + 'data': [ 'inet', 'unix', 'vsock', 'fd' ] } + +## +# @SocketAddress: +# +# Captures the address of a socket, which could also be a named file +# descriptor +# +# @type: Transport type +# +# Since: 2.9 +## +{ 'union': 'SocketAddress', + 'base': { 'type': 'SocketAddressType' }, + 'discriminator': 'type', + 'data': { 'inet': 'InetSocketAddress', + 'unix': 'UnixSocketAddress', + 'vsock': 'VsockSocketAddress', + 'fd': 'String' } } diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c new file mode 100644 index 000000000..197139c1c --- /dev/null +++ b/qapi/string-input-visitor.c @@ -0,0 +1,414 @@ +/* + * String parsing visitor + * + * Copyright Red Hat, Inc. 2012-2016 + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * David Hildenbrand <david@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/string-input-visitor.h" +#include "qapi/visitor-impl.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qmp/qnull.h" +#include "qemu/option.h" +#include "qemu/cutils.h" + +typedef enum ListMode { + /* no list parsing active / no list expected */ + LM_NONE, + /* we have an unparsed string remaining */ + LM_UNPARSED, + /* we have an unfinished int64 range */ + LM_INT64_RANGE, + /* we have an unfinished uint64 range */ + LM_UINT64_RANGE, + /* we have parsed the string completely and no range is remaining */ + LM_END, +} ListMode; + +/* protect against DOS attacks, limit the amount of elements per range */ +#define RANGE_MAX_ELEMENTS 65536 + +typedef union RangeElement { + int64_t i64; + uint64_t u64; +} RangeElement; + +struct StringInputVisitor +{ + Visitor visitor; + + /* List parsing state */ + ListMode lm; + RangeElement rangeNext; + RangeElement rangeEnd; + const char *unparsed_string; + void *list; + + /* The original string to parse */ + const char *string; +}; + +static StringInputVisitor *to_siv(Visitor *v) +{ + return container_of(v, StringInputVisitor, visitor); +} + +static bool start_list(Visitor *v, const char *name, GenericList **list, + size_t size, Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + + assert(siv->lm == LM_NONE); + siv->list = list; + siv->unparsed_string = siv->string; + + if (!siv->string[0]) { + if (list) { + *list = NULL; + } + siv->lm = LM_END; + } else { + if (list) { + *list = g_malloc0(size); + } + siv->lm = LM_UNPARSED; + } + return true; +} + +static GenericList *next_list(Visitor *v, GenericList *tail, size_t size) +{ + StringInputVisitor *siv = to_siv(v); + + switch (siv->lm) { + case LM_END: + return NULL; + case LM_INT64_RANGE: + case LM_UINT64_RANGE: + case LM_UNPARSED: + /* we have an unparsed string or something left in a range */ + break; + default: + abort(); + } + + tail->next = g_malloc0(size); + return tail->next; +} + +static bool check_list(Visitor *v, Error **errp) +{ + const StringInputVisitor *siv = to_siv(v); + + switch (siv->lm) { + case LM_INT64_RANGE: + case LM_UINT64_RANGE: + case LM_UNPARSED: + error_setg(errp, "Fewer list elements expected"); + return false; + case LM_END: + return true; + default: + abort(); + } +} + +static void end_list(Visitor *v, void **obj) +{ + StringInputVisitor *siv = to_siv(v); + + assert(siv->lm != LM_NONE); + assert(siv->list == obj); + siv->list = NULL; + siv->unparsed_string = NULL; + siv->lm = LM_NONE; +} + +static int try_parse_int64_list_entry(StringInputVisitor *siv, int64_t *obj) +{ + const char *endptr; + int64_t start, end; + + /* parse a simple int64 or range */ + if (qemu_strtoi64(siv->unparsed_string, &endptr, 0, &start)) { + return -EINVAL; + } + end = start; + + switch (endptr[0]) { + case '\0': + siv->unparsed_string = endptr; + break; + case ',': + siv->unparsed_string = endptr + 1; + break; + case '-': + /* parse the end of the range */ + if (qemu_strtoi64(endptr + 1, &endptr, 0, &end)) { + return -EINVAL; + } + if (start > end || end - start >= RANGE_MAX_ELEMENTS) { + return -EINVAL; + } + switch (endptr[0]) { + case '\0': + siv->unparsed_string = endptr; + break; + case ',': + siv->unparsed_string = endptr + 1; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + /* we have a proper range (with maybe only one element) */ + siv->lm = LM_INT64_RANGE; + siv->rangeNext.i64 = start; + siv->rangeEnd.i64 = end; + return 0; +} + +static bool parse_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + int64_t val; + + switch (siv->lm) { + case LM_NONE: + /* just parse a simple int64, bail out if not completely consumed */ + if (qemu_strtoi64(siv->string, NULL, 0, &val)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", "int64"); + return false; + } + *obj = val; + return true; + case LM_UNPARSED: + if (try_parse_int64_list_entry(siv, obj)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", + "list of int64 values or ranges"); + return false; + } + assert(siv->lm == LM_INT64_RANGE); + /* fall through */ + case LM_INT64_RANGE: + /* return the next element in the range */ + assert(siv->rangeNext.i64 <= siv->rangeEnd.i64); + *obj = siv->rangeNext.i64++; + + if (siv->rangeNext.i64 > siv->rangeEnd.i64 || *obj == INT64_MAX) { + /* end of range, check if there is more to parse */ + siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END; + } + return true; + case LM_END: + error_setg(errp, "Fewer list elements expected"); + return false; + default: + abort(); + } +} + +static int try_parse_uint64_list_entry(StringInputVisitor *siv, uint64_t *obj) +{ + const char *endptr; + uint64_t start, end; + + /* parse a simple uint64 or range */ + if (qemu_strtou64(siv->unparsed_string, &endptr, 0, &start)) { + return -EINVAL; + } + end = start; + + switch (endptr[0]) { + case '\0': + siv->unparsed_string = endptr; + break; + case ',': + siv->unparsed_string = endptr + 1; + break; + case '-': + /* parse the end of the range */ + if (qemu_strtou64(endptr + 1, &endptr, 0, &end)) { + return -EINVAL; + } + if (start > end || end - start >= RANGE_MAX_ELEMENTS) { + return -EINVAL; + } + switch (endptr[0]) { + case '\0': + siv->unparsed_string = endptr; + break; + case ',': + siv->unparsed_string = endptr + 1; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + /* we have a proper range (with maybe only one element) */ + siv->lm = LM_UINT64_RANGE; + siv->rangeNext.u64 = start; + siv->rangeEnd.u64 = end; + return 0; +} + +static bool parse_type_uint64(Visitor *v, const char *name, uint64_t *obj, + Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + uint64_t val; + + switch (siv->lm) { + case LM_NONE: + /* just parse a simple uint64, bail out if not completely consumed */ + if (qemu_strtou64(siv->string, NULL, 0, &val)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", + "uint64"); + return false; + } + *obj = val; + return true; + case LM_UNPARSED: + if (try_parse_uint64_list_entry(siv, obj)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", + "list of uint64 values or ranges"); + return false; + } + assert(siv->lm == LM_UINT64_RANGE); + /* fall through */ + case LM_UINT64_RANGE: + /* return the next element in the range */ + assert(siv->rangeNext.u64 <= siv->rangeEnd.u64); + *obj = siv->rangeNext.u64++; + + if (siv->rangeNext.u64 > siv->rangeEnd.u64 || *obj == UINT64_MAX) { + /* end of range, check if there is more to parse */ + siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END; + } + return true; + case LM_END: + error_setg(errp, "Fewer list elements expected"); + return false; + default: + abort(); + } +} + +static bool parse_type_size(Visitor *v, const char *name, uint64_t *obj, + Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + uint64_t val; + + assert(siv->lm == LM_NONE); + if (!parse_option_size(name, siv->string, &val, errp)) { + return false; + } + + *obj = val; + return true; +} + +static bool parse_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + + assert(siv->lm == LM_NONE); + return qapi_bool_parse(name ? name : "null", siv->string, obj, errp); +} + +static bool parse_type_str(Visitor *v, const char *name, char **obj, + Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + + assert(siv->lm == LM_NONE); + *obj = g_strdup(siv->string); + return true; +} + +static bool parse_type_number(Visitor *v, const char *name, double *obj, + Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + double val; + + assert(siv->lm == LM_NONE); + if (qemu_strtod_finite(siv->string, NULL, &val)) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "number"); + return false; + } + + *obj = val; + return true; +} + +static bool parse_type_null(Visitor *v, const char *name, QNull **obj, + Error **errp) +{ + StringInputVisitor *siv = to_siv(v); + + assert(siv->lm == LM_NONE); + *obj = NULL; + + if (siv->string[0]) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "null"); + return false; + } + + *obj = qnull(); + return true; +} + +static void string_input_free(Visitor *v) +{ + StringInputVisitor *siv = to_siv(v); + + g_free(siv); +} + +Visitor *string_input_visitor_new(const char *str) +{ + StringInputVisitor *v; + + assert(str); + v = g_malloc0(sizeof(*v)); + + v->visitor.type = VISITOR_INPUT; + v->visitor.type_int64 = parse_type_int64; + v->visitor.type_uint64 = parse_type_uint64; + v->visitor.type_size = parse_type_size; + v->visitor.type_bool = parse_type_bool; + v->visitor.type_str = parse_type_str; + v->visitor.type_number = parse_type_number; + v->visitor.type_null = parse_type_null; + v->visitor.start_list = start_list; + v->visitor.next_list = next_list; + v->visitor.check_list = check_list; + v->visitor.end_list = end_list; + v->visitor.free = string_input_free; + + v->string = str; + v->lm = LM_NONE; + return &v->visitor; +} diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c new file mode 100644 index 000000000..5506c933d --- /dev/null +++ b/qapi/string-output-visitor.c @@ -0,0 +1,374 @@ +/* + * String printing Visitor + * + * Copyright Red Hat, Inc. 2012-2016 + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qapi/string-output-visitor.h" +#include "qapi/visitor-impl.h" +#include "qemu/host-utils.h" +#include <math.h> +#include "qemu/range.h" + +enum ListMode { + LM_NONE, /* not traversing a list of repeated options */ + LM_STARTED, /* next_list() ready to be called */ + + LM_IN_PROGRESS, /* next_list() has been called. + * + * Generating the next list link will consume the most + * recently parsed QemuOpt instance of the repeated + * option. + * + * Parsing a value into the list link will examine the + * next QemuOpt instance of the repeated option, and + * possibly enter LM_SIGNED_INTERVAL or + * LM_UNSIGNED_INTERVAL. + */ + + LM_SIGNED_INTERVAL, /* next_list() has been called. + * + * Generating the next list link will consume the most + * recently stored element from the signed interval, + * parsed from the most recent QemuOpt instance of the + * repeated option. This may consume QemuOpt itself + * and return to LM_IN_PROGRESS. + * + * Parsing a value into the list link will store the + * next element of the signed interval. + */ + + LM_UNSIGNED_INTERVAL,/* Same as above, only for an unsigned interval. */ + + LM_END, /* next_list() called, about to see last element. */ +}; + +typedef enum ListMode ListMode; + +struct StringOutputVisitor +{ + Visitor visitor; + bool human; + GString *string; + char **result; + ListMode list_mode; + union { + int64_t s; + uint64_t u; + } range_start, range_end; + GList *ranges; + void *list; /* Only needed for sanity checking the caller */ +}; + +static StringOutputVisitor *to_sov(Visitor *v) +{ + return container_of(v, StringOutputVisitor, visitor); +} + +static void string_output_set(StringOutputVisitor *sov, char *string) +{ + if (sov->string) { + g_string_free(sov->string, true); + } + sov->string = g_string_new(string); + g_free(string); +} + +static void string_output_append(StringOutputVisitor *sov, int64_t a) +{ + Range *r = g_malloc0(sizeof(*r)); + + range_set_bounds(r, a, a); + sov->ranges = range_list_insert(sov->ranges, r); +} + +static void string_output_append_range(StringOutputVisitor *sov, + int64_t s, int64_t e) +{ + Range *r = g_malloc0(sizeof(*r)); + + range_set_bounds(r, s, e); + sov->ranges = range_list_insert(sov->ranges, r); +} + +static void format_string(StringOutputVisitor *sov, Range *r, bool next, + bool human) +{ + if (range_lob(r) != range_upb(r)) { + if (human) { + g_string_append_printf(sov->string, "0x%" PRIx64 "-0x%" PRIx64, + range_lob(r), range_upb(r)); + + } else { + g_string_append_printf(sov->string, "%" PRId64 "-%" PRId64, + range_lob(r), range_upb(r)); + } + } else { + if (human) { + g_string_append_printf(sov->string, "0x%" PRIx64, range_lob(r)); + } else { + g_string_append_printf(sov->string, "%" PRId64, range_lob(r)); + } + } + if (next) { + g_string_append(sov->string, ","); + } +} + +static bool print_type_int64(Visitor *v, const char *name, int64_t *obj, + Error **errp) +{ + StringOutputVisitor *sov = to_sov(v); + GList *l; + + switch (sov->list_mode) { + case LM_NONE: + string_output_append(sov, *obj); + break; + + case LM_STARTED: + sov->range_start.s = *obj; + sov->range_end.s = *obj; + sov->list_mode = LM_IN_PROGRESS; + return true; + + case LM_IN_PROGRESS: + if (sov->range_end.s + 1 == *obj) { + sov->range_end.s++; + } else { + if (sov->range_start.s == sov->range_end.s) { + string_output_append(sov, sov->range_end.s); + } else { + assert(sov->range_start.s < sov->range_end.s); + string_output_append_range(sov, sov->range_start.s, + sov->range_end.s); + } + + sov->range_start.s = *obj; + sov->range_end.s = *obj; + } + return true; + + case LM_END: + if (sov->range_end.s + 1 == *obj) { + sov->range_end.s++; + assert(sov->range_start.s < sov->range_end.s); + string_output_append_range(sov, sov->range_start.s, + sov->range_end.s); + } else { + if (sov->range_start.s == sov->range_end.s) { + string_output_append(sov, sov->range_end.s); + } else { + assert(sov->range_start.s < sov->range_end.s); + + string_output_append_range(sov, sov->range_start.s, + sov->range_end.s); + } + string_output_append(sov, *obj); + } + break; + + default: + abort(); + } + + l = sov->ranges; + while (l) { + Range *r = l->data; + format_string(sov, r, l->next != NULL, false); + l = l->next; + } + + if (sov->human) { + l = sov->ranges; + g_string_append(sov->string, " ("); + while (l) { + Range *r = l->data; + format_string(sov, r, l->next != NULL, true); + l = l->next; + } + g_string_append(sov->string, ")"); + } + + return true; +} + +static bool print_type_uint64(Visitor *v, const char *name, uint64_t *obj, + Error **errp) +{ + /* FIXME: print_type_int64 mishandles values over INT64_MAX */ + int64_t i = *obj; + return print_type_int64(v, name, &i, errp); +} + +static bool print_type_size(Visitor *v, const char *name, uint64_t *obj, + Error **errp) +{ + StringOutputVisitor *sov = to_sov(v); + uint64_t val; + char *out, *psize; + + if (!sov->human) { + out = g_strdup_printf("%"PRIu64, *obj); + string_output_set(sov, out); + return true; + } + + val = *obj; + psize = size_to_str(val); + out = g_strdup_printf("%"PRIu64" (%s)", val, psize); + string_output_set(sov, out); + + g_free(psize); + return true; +} + +static bool print_type_bool(Visitor *v, const char *name, bool *obj, + Error **errp) +{ + StringOutputVisitor *sov = to_sov(v); + string_output_set(sov, g_strdup(*obj ? "true" : "false")); + return true; +} + +static bool print_type_str(Visitor *v, const char *name, char **obj, + Error **errp) +{ + StringOutputVisitor *sov = to_sov(v); + char *out; + + if (sov->human) { + out = *obj ? g_strdup_printf("\"%s\"", *obj) : g_strdup("<null>"); + } else { + out = g_strdup(*obj ? *obj : ""); + } + string_output_set(sov, out); + return true; +} + +static bool print_type_number(Visitor *v, const char *name, double *obj, + Error **errp) +{ + StringOutputVisitor *sov = to_sov(v); + string_output_set(sov, g_strdup_printf("%.17g", *obj)); + return true; +} + +static bool print_type_null(Visitor *v, const char *name, QNull **obj, + Error **errp) +{ + StringOutputVisitor *sov = to_sov(v); + char *out; + + if (sov->human) { + out = g_strdup("<null>"); + } else { + out = g_strdup(""); + } + string_output_set(sov, out); + return true; +} + +static bool +start_list(Visitor *v, const char *name, GenericList **list, size_t size, + Error **errp) +{ + StringOutputVisitor *sov = to_sov(v); + + /* we can't traverse a list in a list */ + assert(sov->list_mode == LM_NONE); + /* We don't support visits without a list */ + assert(list); + sov->list = list; + /* List handling is only needed if there are at least two elements */ + if (*list && (*list)->next) { + sov->list_mode = LM_STARTED; + } + return true; +} + +static GenericList *next_list(Visitor *v, GenericList *tail, size_t size) +{ + StringOutputVisitor *sov = to_sov(v); + GenericList *ret = tail->next; + + if (ret && !ret->next) { + sov->list_mode = LM_END; + } + return ret; +} + +static void end_list(Visitor *v, void **obj) +{ + StringOutputVisitor *sov = to_sov(v); + + assert(sov->list == obj); + assert(sov->list_mode == LM_STARTED || + sov->list_mode == LM_END || + sov->list_mode == LM_NONE || + sov->list_mode == LM_IN_PROGRESS); + sov->list_mode = LM_NONE; +} + +static void string_output_complete(Visitor *v, void *opaque) +{ + StringOutputVisitor *sov = to_sov(v); + + assert(opaque == sov->result); + *sov->result = g_string_free(sov->string, false); + sov->string = NULL; +} + +static void free_range(void *range, void *dummy) +{ + g_free(range); +} + +static void string_output_free(Visitor *v) +{ + StringOutputVisitor *sov = to_sov(v); + + if (sov->string) { + g_string_free(sov->string, true); + } + + g_list_foreach(sov->ranges, free_range, NULL); + g_list_free(sov->ranges); + g_free(sov); +} + +Visitor *string_output_visitor_new(bool human, char **result) +{ + StringOutputVisitor *v; + + v = g_malloc0(sizeof(*v)); + + v->string = g_string_new(NULL); + v->human = human; + v->result = result; + *result = NULL; + + v->visitor.type = VISITOR_OUTPUT; + v->visitor.type_int64 = print_type_int64; + v->visitor.type_uint64 = print_type_uint64; + v->visitor.type_size = print_type_size; + v->visitor.type_bool = print_type_bool; + v->visitor.type_str = print_type_str; + v->visitor.type_number = print_type_number; + v->visitor.type_null = print_type_null; + v->visitor.start_list = start_list; + v->visitor.next_list = next_list; + v->visitor.end_list = end_list; + v->visitor.complete = string_output_complete; + v->visitor.free = string_output_free; + + return &v->visitor; +} diff --git a/qapi/tpm.json b/qapi/tpm.json new file mode 100644 index 000000000..4e2ea9756 --- /dev/null +++ b/qapi/tpm.json @@ -0,0 +1,185 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = TPM (trusted platform module) devices +## + +## +# @TpmModel: +# +# An enumeration of TPM models +# +# @tpm-tis: TPM TIS model +# @tpm-crb: TPM CRB model (since 2.12) +# @tpm-spapr: TPM SPAPR model (since 5.0) +# +# Since: 1.5 +## +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ], + 'if': 'CONFIG_TPM' } + +## +# @query-tpm-models: +# +# Return a list of supported TPM models +# +# Returns: a list of TpmModel +# +# Since: 1.5 +# +# Example: +# +# -> { "execute": "query-tpm-models" } +# <- { "return": [ "tpm-tis", "tpm-crb", "tpm-spapr" ] } +# +## +{ 'command': 'query-tpm-models', 'returns': ['TpmModel'], + 'if': 'CONFIG_TPM' } + +## +# @TpmType: +# +# An enumeration of TPM types +# +# @passthrough: TPM passthrough type +# @emulator: Software Emulator TPM type +# Since: 2.11 +# +# Since: 1.5 +## +{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ], + 'if': 'CONFIG_TPM' } + +## +# @query-tpm-types: +# +# Return a list of supported TPM types +# +# Returns: a list of TpmType +# +# Since: 1.5 +# +# Example: +# +# -> { "execute": "query-tpm-types" } +# <- { "return": [ "passthrough", "emulator" ] } +# +## +{ 'command': 'query-tpm-types', 'returns': ['TpmType'], + 'if': 'CONFIG_TPM' } + +## +# @TPMPassthroughOptions: +# +# Information about the TPM passthrough type +# +# @path: string describing the path used for accessing the TPM device +# +# @cancel-path: string showing the TPM's sysfs cancel file +# for cancellation of TPM commands while they are executing +# +# Since: 1.5 +## +{ 'struct': 'TPMPassthroughOptions', + 'data': { '*path': 'str', + '*cancel-path': 'str' }, + 'if': 'CONFIG_TPM' } + +## +# @TPMEmulatorOptions: +# +# Information about the TPM emulator type +# +# @chardev: Name of a unix socket chardev +# +# Since: 2.11 +## +{ 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' }, + 'if': 'CONFIG_TPM' } + +## +# @TPMPassthroughOptionsWrapper: +# +# Since: 1.5 +## +{ 'struct': 'TPMPassthroughOptionsWrapper', + 'data': { 'data': 'TPMPassthroughOptions' }, + 'if': 'CONFIG_TPM' } + +## +# @TPMEmulatorOptionsWrapper: +# +# Since: 2.11 +## +{ 'struct': 'TPMEmulatorOptionsWrapper', + 'data': { 'data': 'TPMEmulatorOptions' }, + 'if': 'CONFIG_TPM' } + +## +# @TpmTypeOptions: +# +# A union referencing different TPM backend types' configuration options +# +# @type: - 'passthrough' The configuration options for the TPM passthrough type +# - 'emulator' The configuration options for TPM emulator backend type +# +# Since: 1.5 +## +{ 'union': 'TpmTypeOptions', + 'base': { 'type': 'TpmType' }, + 'discriminator': 'type', + 'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper', + 'emulator': 'TPMEmulatorOptionsWrapper' }, + 'if': 'CONFIG_TPM' } + +## +# @TPMInfo: +# +# Information about the TPM +# +# @id: The Id of the TPM +# +# @model: The TPM frontend model +# +# @options: The TPM (backend) type configuration options +# +# Since: 1.5 +## +{ 'struct': 'TPMInfo', + 'data': {'id': 'str', + 'model': 'TpmModel', + 'options': 'TpmTypeOptions' }, + 'if': 'CONFIG_TPM' } + +## +# @query-tpm: +# +# Return information about the TPM device +# +# Returns: @TPMInfo on success +# +# Since: 1.5 +# +# Example: +# +# -> { "execute": "query-tpm" } +# <- { "return": +# [ +# { "model": "tpm-tis", +# "options": +# { "type": "passthrough", +# "data": +# { "cancel-path": "/sys/class/misc/tpm0/device/cancel", +# "path": "/dev/tpm0" +# } +# }, +# "id": "tpm0" +# } +# ] +# } +# +## +{ 'command': 'query-tpm', 'returns': ['TPMInfo'], + 'if': 'CONFIG_TPM' } diff --git a/qapi/trace-events b/qapi/trace-events new file mode 100644 index 000000000..ab108c4f0 --- /dev/null +++ b/qapi/trace-events @@ -0,0 +1,38 @@ +# See docs/devel/tracing.rst for syntax documentation. + +# qapi-visit-core.c +visit_free(void *v) "v=%p" +visit_complete(void *v, void *opaque) "v=%p opaque=%p" + +visit_start_struct(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu" +visit_check_struct(void *v) "v=%p" +visit_end_struct(void *v, void *obj) "v=%p obj=%p" + +visit_start_list(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu" +visit_next_list(void *v, void *tail, size_t size) "v=%p tail=%p size=%zu" +visit_check_list(void *v) "v=%p" +visit_end_list(void *v, void *obj) "v=%p obj=%p" + +visit_start_alternate(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu" +visit_end_alternate(void *v, void *obj) "v=%p obj=%p" + +visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p" +visit_policy_reject(void *v, const char *name) "v=%p name=%s" +visit_policy_skip(void *v, const char *name) "v=%p name=%s" + +visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p" +visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p" +visit_type_uint8(void *v, const char *name, uint8_t *obj) "v=%p name=%s obj=%p" +visit_type_uint16(void *v, const char *name, uint16_t *obj) "v=%p name=%s obj=%p" +visit_type_uint32(void *v, const char *name, uint32_t *obj) "v=%p name=%s obj=%p" +visit_type_uint64(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p" +visit_type_int8(void *v, const char *name, int8_t *obj) "v=%p name=%s obj=%p" +visit_type_int16(void *v, const char *name, int16_t *obj) "v=%p name=%s obj=%p" +visit_type_int32(void *v, const char *name, int32_t *obj) "v=%p name=%s obj=%p" +visit_type_int64(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p" +visit_type_size(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p" +visit_type_bool(void *v, const char *name, bool *obj) "v=%p name=%s obj=%p" +visit_type_str(void *v, const char *name, char **obj) "v=%p name=%s obj=%p" +visit_type_number(void *v, const char *name, void *obj) "v=%p name=%s obj=%p" +visit_type_any(void *v, const char *name, void *obj) "v=%p name=%s obj=%p" +visit_type_null(void *v, const char *name, void *obj) "v=%p name=%s obj=%p" diff --git a/qapi/trace.h b/qapi/trace.h new file mode 100644 index 000000000..5c3fb674d --- /dev/null +++ b/qapi/trace.h @@ -0,0 +1 @@ +#include "trace/trace-qapi.h" diff --git a/qapi/trace.json b/qapi/trace.json new file mode 100644 index 000000000..eedfded51 --- /dev/null +++ b/qapi/trace.json @@ -0,0 +1,108 @@ +# -*- mode: python -*- +# +# Copyright (C) 2011-2016 Lluís Vilanova <vilanova@ac.upc.edu> +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + +## +# = Tracing +## + +## +# @TraceEventState: +# +# State of a tracing event. +# +# @unavailable: The event is statically disabled. +# +# @disabled: The event is dynamically disabled. +# +# @enabled: The event is dynamically enabled. +# +# Since: 2.2 +## +{ 'enum': 'TraceEventState', + 'data': ['unavailable', 'disabled', 'enabled'] } + +## +# @TraceEventInfo: +# +# Information of a tracing event. +# +# @name: Event name. +# @state: Tracing state. +# @vcpu: Whether this is a per-vCPU event (since 2.7). +# +# An event is per-vCPU if it has the "vcpu" property in the "trace-events" +# files. +# +# Since: 2.2 +## +{ 'struct': 'TraceEventInfo', + 'data': {'name': 'str', 'state': 'TraceEventState', 'vcpu': 'bool'} } + +## +# @trace-event-get-state: +# +# Query the state of events. +# +# @name: Event name pattern (case-sensitive glob). +# @vcpu: The vCPU to query (any by default; since 2.7). +# +# Returns: a list of @TraceEventInfo for the matching events +# +# An event is returned if: +# +# - its name matches the @name pattern, and +# - if @vcpu is given, the event has the "vcpu" property. +# +# Therefore, if @vcpu is given, the operation will only match per-vCPU events, +# returning their state on the specified vCPU. Special case: if @name is an +# exact match, @vcpu is given and the event does not have the "vcpu" property, +# an error is returned. +# +# Since: 2.2 +# +# Example: +# +# -> { "execute": "trace-event-get-state", +# "arguments": { "name": "qemu_memalign" } } +# <- { "return": [ { "name": "qemu_memalign", "state": "disabled" } ] } +# +## +{ 'command': 'trace-event-get-state', + 'data': {'name': 'str', '*vcpu': 'int'}, + 'returns': ['TraceEventInfo'] } + +## +# @trace-event-set-state: +# +# Set the dynamic tracing state of events. +# +# @name: Event name pattern (case-sensitive glob). +# @enable: Whether to enable tracing. +# @ignore-unavailable: Do not match unavailable events with @name. +# @vcpu: The vCPU to act upon (all by default; since 2.7). +# +# An event's state is modified if: +# - its name matches the @name pattern, and +# - if @vcpu is given, the event has the "vcpu" property. +# +# Therefore, if @vcpu is given, the operation will only match per-vCPU events, +# setting their state on the specified vCPU. Special case: if @name is an exact +# match, @vcpu is given and the event does not have the "vcpu" property, an +# error is returned. +# +# Since: 2.2 +# +# Example: +# +# -> { "execute": "trace-event-set-state", +# "arguments": { "name": "qemu_memalign", "enable": true } } +# <- { "return": {} } +# +## +{ 'command': 'trace-event-set-state', + 'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool', + '*vcpu': 'int'} } diff --git a/qapi/transaction.json b/qapi/transaction.json new file mode 100644 index 000000000..381a2df78 --- /dev/null +++ b/qapi/transaction.json @@ -0,0 +1,258 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Transactions +## + +{ 'include': 'block-core.json' } + +## +# @Abort: +# +# This action can be used to test transaction failure. +# +# Since: 1.6 +## +{ 'struct': 'Abort', + 'data': { } } + +## +# @ActionCompletionMode: +# +# An enumeration of Transactional completion modes. +# +# @individual: Do not attempt to cancel any other Actions if any Actions fail +# after the Transaction request succeeds. All Actions that +# can complete successfully will do so without waiting on others. +# This is the default. +# +# @grouped: If any Action fails after the Transaction succeeds, cancel all +# Actions. Actions do not complete until all Actions are ready to +# complete. May be rejected by Actions that do not support this +# completion mode. +# +# Since: 2.5 +## +{ 'enum': 'ActionCompletionMode', + 'data': [ 'individual', 'grouped' ] } + +## +# @TransactionActionKind: +# +# @abort: Since 1.6 +# @block-dirty-bitmap-add: Since 2.5 +# @block-dirty-bitmap-remove: Since 4.2 +# @block-dirty-bitmap-clear: Since 2.5 +# @block-dirty-bitmap-enable: Since 4.0 +# @block-dirty-bitmap-disable: Since 4.0 +# @block-dirty-bitmap-merge: Since 4.0 +# @blockdev-backup: Since 2.3 +# @blockdev-snapshot: Since 2.5 +# @blockdev-snapshot-internal-sync: Since 1.7 +# @blockdev-snapshot-sync: since 1.1 +# @drive-backup: Since 1.6 +# +# Features: +# @deprecated: Member @drive-backup is deprecated. Use member +# @blockdev-backup instead. +# +# Since: 1.1 +## +{ 'enum': 'TransactionActionKind', + 'data': [ 'abort', 'block-dirty-bitmap-add', 'block-dirty-bitmap-remove', + 'block-dirty-bitmap-clear', 'block-dirty-bitmap-enable', + 'block-dirty-bitmap-disable', 'block-dirty-bitmap-merge', + 'blockdev-backup', 'blockdev-snapshot', + 'blockdev-snapshot-internal-sync', 'blockdev-snapshot-sync', + { 'name': 'drive-backup', 'features': [ 'deprecated' ] } ] } + +## +# @AbortWrapper: +# +# Since: 1.6 +## +{ 'struct': 'AbortWrapper', + 'data': { 'data': 'Abort' } } + +## +# @BlockDirtyBitmapAddWrapper: +# +# Since: 2.5 +## +{ 'struct': 'BlockDirtyBitmapAddWrapper', + 'data': { 'data': 'BlockDirtyBitmapAdd' } } + +## +# @BlockDirtyBitmapWrapper: +# +# Since: 2.5 +## +{ 'struct': 'BlockDirtyBitmapWrapper', + 'data': { 'data': 'BlockDirtyBitmap' } } + +## +# @BlockDirtyBitmapMergeWrapper: +# +# Since: 4.0 +## +{ 'struct': 'BlockDirtyBitmapMergeWrapper', + 'data': { 'data': 'BlockDirtyBitmapMerge' } } + +## +# @BlockdevBackupWrapper: +# +# Since: 2.3 +## +{ 'struct': 'BlockdevBackupWrapper', + 'data': { 'data': 'BlockdevBackup' } } + +## +# @BlockdevSnapshotWrapper: +# +# Since: 2.5 +## +{ 'struct': 'BlockdevSnapshotWrapper', + 'data': { 'data': 'BlockdevSnapshot' } } + +## +# @BlockdevSnapshotInternalWrapper: +# +# Since: 1.7 +## +{ 'struct': 'BlockdevSnapshotInternalWrapper', + 'data': { 'data': 'BlockdevSnapshotInternal' } } + +## +# @BlockdevSnapshotSyncWrapper: +# +# Since: 1.1 +## +{ 'struct': 'BlockdevSnapshotSyncWrapper', + 'data': { 'data': 'BlockdevSnapshotSync' } } + +## +# @DriveBackupWrapper: +# +# Since: 1.6 +## +{ 'struct': 'DriveBackupWrapper', + 'data': { 'data': 'DriveBackup' } } + +## +# @TransactionAction: +# +# A discriminated record of operations that can be performed with +# @transaction. +# +# Since: 1.1 +## +{ 'union': 'TransactionAction', + 'base': { 'type': 'TransactionActionKind' }, + 'discriminator': 'type', + 'data': { + 'abort': 'AbortWrapper', + 'block-dirty-bitmap-add': 'BlockDirtyBitmapAddWrapper', + 'block-dirty-bitmap-remove': 'BlockDirtyBitmapWrapper', + 'block-dirty-bitmap-clear': 'BlockDirtyBitmapWrapper', + 'block-dirty-bitmap-enable': 'BlockDirtyBitmapWrapper', + 'block-dirty-bitmap-disable': 'BlockDirtyBitmapWrapper', + 'block-dirty-bitmap-merge': 'BlockDirtyBitmapMergeWrapper', + 'blockdev-backup': 'BlockdevBackupWrapper', + 'blockdev-snapshot': 'BlockdevSnapshotWrapper', + 'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternalWrapper', + 'blockdev-snapshot-sync': 'BlockdevSnapshotSyncWrapper', + 'drive-backup': 'DriveBackupWrapper' + } } + +## +# @TransactionProperties: +# +# Optional arguments to modify the behavior of a Transaction. +# +# @completion-mode: Controls how jobs launched asynchronously by +# Actions will complete or fail as a group. +# See @ActionCompletionMode for details. +# +# Since: 2.5 +## +{ 'struct': 'TransactionProperties', + 'data': { + '*completion-mode': 'ActionCompletionMode' + } +} + +## +# @transaction: +# +# Executes a number of transactionable QMP commands atomically. If any +# operation fails, then the entire set of actions will be abandoned and the +# appropriate error returned. +# +# For external snapshots, the dictionary contains the device, the file to use for +# the new snapshot, and the format. The default format, if not specified, is +# qcow2. +# +# Each new snapshot defaults to being created by QEMU (wiping any +# contents if the file already exists), but it is also possible to reuse +# an externally-created file. In the latter case, you should ensure that +# the new image file has the same contents as the current one; QEMU cannot +# perform any meaningful check. Typically this is achieved by using the +# current image file as the backing file for the new image. +# +# On failure, the original disks pre-snapshot attempt will be used. +# +# For internal snapshots, the dictionary contains the device and the +# snapshot's name. If an internal snapshot matching name already exists, +# the request will be rejected. Only some image formats support it, for +# example, qcow2, and rbd, +# +# On failure, qemu will try delete the newly created internal snapshot in the +# transaction. When an I/O error occurs during deletion, the user needs to fix +# it later with qemu-img or other command. +# +# @actions: List of @TransactionAction; +# information needed for the respective operations. +# +# @properties: structure of additional options to control the +# execution of the transaction. See @TransactionProperties +# for additional detail. +# +# Returns: nothing on success +# +# Errors depend on the operations of the transaction +# +# Note: The transaction aborts on the first failure. Therefore, there will be +# information on only one failed operation returned in an error condition, and +# subsequent actions will not have been attempted. +# +# Since: 1.1 +# +# Example: +# +# -> { "execute": "transaction", +# "arguments": { "actions": [ +# { "type": "blockdev-snapshot-sync", "data" : { "device": "ide-hd0", +# "snapshot-file": "/some/place/my-image", +# "format": "qcow2" } }, +# { "type": "blockdev-snapshot-sync", "data" : { "node-name": "myfile", +# "snapshot-file": "/some/place/my-image2", +# "snapshot-node-name": "node3432", +# "mode": "existing", +# "format": "qcow2" } }, +# { "type": "blockdev-snapshot-sync", "data" : { "device": "ide-hd1", +# "snapshot-file": "/some/place/my-image2", +# "mode": "existing", +# "format": "qcow2" } }, +# { "type": "blockdev-snapshot-internal-sync", "data" : { +# "device": "ide-hd2", +# "name": "snapshot0" } } ] } } +# <- { "return": {} } +# +## +{ 'command': 'transaction', + 'data': { 'actions': [ 'TransactionAction' ], + '*properties': 'TransactionProperties' + } +} diff --git a/qapi/ui.json b/qapi/ui.json new file mode 100644 index 000000000..d7567ac86 --- /dev/null +++ b/qapi/ui.json @@ -0,0 +1,1306 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Remote desktop +## + +{ 'include': 'common.json' } +{ 'include': 'sockets.json' } + +## +# @set_password: +# +# Sets the password of a remote display session. +# +# @protocol: - 'vnc' to modify the VNC server password +# - 'spice' to modify the Spice server password +# +# @password: the new password +# +# @connected: how to handle existing clients when changing the +# password. If nothing is specified, defaults to 'keep' +# 'fail' to fail the command if clients are connected +# 'disconnect' to disconnect existing clients +# 'keep' to maintain existing clients +# +# Returns: - Nothing on success +# - If Spice is not enabled, DeviceNotFound +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "set_password", "arguments": { "protocol": "vnc", +# "password": "secret" } } +# <- { "return": {} } +# +## +{ 'command': 'set_password', + 'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} } + +## +# @expire_password: +# +# Expire the password of a remote display server. +# +# @protocol: the name of the remote display protocol 'vnc' or 'spice' +# +# @time: when to expire the password. +# +# - 'now' to expire the password immediately +# - 'never' to cancel password expiration +# - '+INT' where INT is the number of seconds from now (integer) +# - 'INT' where INT is the absolute time in seconds +# +# Returns: - Nothing on success +# - If @protocol is 'spice' and Spice is not active, DeviceNotFound +# +# Since: 0.14 +# +# Notes: Time is relative to the server and currently there is no way to +# coordinate server time with client time. It is not recommended to +# use the absolute time version of the @time parameter unless you're +# sure you are on the same machine as the QEMU instance. +# +# Example: +# +# -> { "execute": "expire_password", "arguments": { "protocol": "vnc", +# "time": "+60" } } +# <- { "return": {} } +# +## +{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} } + +## +# @screendump: +# +# Write a PPM of the VGA screen to a file. +# +# @filename: the path of a new PPM file to store the image +# +# @device: ID of the display device that should be dumped. If this parameter +# is missing, the primary display will be used. (Since 2.12) +# +# @head: head to use in case the device supports multiple heads. If this +# parameter is missing, head #0 will be used. Also note that the head +# can only be specified in conjunction with the device ID. (Since 2.12) +# +# Returns: Nothing on success +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "screendump", +# "arguments": { "filename": "/tmp/image" } } +# <- { "return": {} } +# +## +{ 'command': 'screendump', + 'data': {'filename': 'str', '*device': 'str', '*head': 'int'}, + 'coroutine': true } + +## +# == Spice +## + +## +# @SpiceBasicInfo: +# +# The basic information for SPICE network connection +# +# @host: IP address +# +# @port: port number +# +# @family: address family +# +# Since: 2.1 +## +{ 'struct': 'SpiceBasicInfo', + 'data': { 'host': 'str', + 'port': 'str', + 'family': 'NetworkAddressFamily' }, + 'if': 'CONFIG_SPICE' } + +## +# @SpiceServerInfo: +# +# Information about a SPICE server +# +# @auth: authentication method +# +# Since: 2.1 +## +{ 'struct': 'SpiceServerInfo', + 'base': 'SpiceBasicInfo', + 'data': { '*auth': 'str' }, + 'if': 'CONFIG_SPICE' } + +## +# @SpiceChannel: +# +# Information about a SPICE client channel. +# +# @connection-id: SPICE connection id number. All channels with the same id +# belong to the same SPICE session. +# +# @channel-type: SPICE channel type number. "1" is the main control +# channel, filter for this one if you want to track spice +# sessions only +# +# @channel-id: SPICE channel ID number. Usually "0", might be different when +# multiple channels of the same type exist, such as multiple +# display channels in a multihead setup +# +# @tls: true if the channel is encrypted, false otherwise. +# +# Since: 0.14 +## +{ 'struct': 'SpiceChannel', + 'base': 'SpiceBasicInfo', + 'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int', + 'tls': 'bool'}, + 'if': 'CONFIG_SPICE' } + +## +# @SpiceQueryMouseMode: +# +# An enumeration of Spice mouse states. +# +# @client: Mouse cursor position is determined by the client. +# +# @server: Mouse cursor position is determined by the server. +# +# @unknown: No information is available about mouse mode used by +# the spice server. +# +# Note: spice/enums.h has a SpiceMouseMode already, hence the name. +# +# Since: 1.1 +## +{ 'enum': 'SpiceQueryMouseMode', + 'data': [ 'client', 'server', 'unknown' ], + 'if': 'CONFIG_SPICE' } + +## +# @SpiceInfo: +# +# Information about the SPICE session. +# +# @enabled: true if the SPICE server is enabled, false otherwise +# +# @migrated: true if the last guest migration completed and spice +# migration had completed as well. false otherwise. (since 1.4) +# +# @host: The hostname the SPICE server is bound to. This depends on +# the name resolution on the host and may be an IP address. +# +# @port: The SPICE server's port number. +# +# @compiled-version: SPICE server version. +# +# @tls-port: The SPICE server's TLS port number. +# +# @auth: the current authentication type used by the server +# +# - 'none' if no authentication is being used +# - 'spice' uses SASL or direct TLS authentication, depending on command +# line options +# +# @mouse-mode: The mode in which the mouse cursor is displayed currently. Can +# be determined by the client or the server, or unknown if spice +# server doesn't provide this information. (since: 1.1) +# +# @channels: a list of @SpiceChannel for each active spice channel +# +# Since: 0.14 +## +{ 'struct': 'SpiceInfo', + 'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int', + '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str', + 'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']}, + 'if': 'CONFIG_SPICE' } + +## +# @query-spice: +# +# Returns information about the current SPICE server +# +# Returns: @SpiceInfo +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-spice" } +# <- { "return": { +# "enabled": true, +# "auth": "spice", +# "port": 5920, +# "tls-port": 5921, +# "host": "0.0.0.0", +# "channels": [ +# { +# "port": "54924", +# "family": "ipv4", +# "channel-type": 1, +# "connection-id": 1804289383, +# "host": "127.0.0.1", +# "channel-id": 0, +# "tls": true +# }, +# { +# "port": "36710", +# "family": "ipv4", +# "channel-type": 4, +# "connection-id": 1804289383, +# "host": "127.0.0.1", +# "channel-id": 0, +# "tls": false +# }, +# [ ... more channels follow ... ] +# ] +# } +# } +# +## +{ 'command': 'query-spice', 'returns': 'SpiceInfo', + 'if': 'CONFIG_SPICE' } + +## +# @SPICE_CONNECTED: +# +# Emitted when a SPICE client establishes a connection +# +# @server: server information +# +# @client: client information +# +# Since: 0.14 +# +# 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"} +# }} +# +## +{ 'event': 'SPICE_CONNECTED', + 'data': { 'server': 'SpiceBasicInfo', + 'client': 'SpiceBasicInfo' }, + 'if': 'CONFIG_SPICE' } + +## +# @SPICE_INITIALIZED: +# +# Emitted after initial handshake and authentication takes place (if any) +# and the SPICE channel is up and running +# +# @server: server information +# +# @client: client information +# +# Since: 0.14 +# +# 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': 'SPICE_INITIALIZED', + 'data': { 'server': 'SpiceServerInfo', + 'client': 'SpiceChannel' }, + 'if': 'CONFIG_SPICE' } + +## +# @SPICE_DISCONNECTED: +# +# Emitted when the SPICE connection is closed +# +# @server: server information +# +# @client: client information +# +# Since: 0.14 +# +# Example: +# +# <- { "timestamp": {"seconds": 1290688046, "microseconds": 388707}, +# "event": "SPICE_DISCONNECTED", +# "data": { +# "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"}, +# "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"} +# }} +# +## +{ 'event': 'SPICE_DISCONNECTED', + 'data': { 'server': 'SpiceBasicInfo', + 'client': 'SpiceBasicInfo' }, + 'if': 'CONFIG_SPICE' } + +## +# @SPICE_MIGRATE_COMPLETED: +# +# Emitted when SPICE migration has completed +# +# Since: 1.3 +# +# Example: +# +# <- { "timestamp": {"seconds": 1290688046, "microseconds": 417172}, +# "event": "SPICE_MIGRATE_COMPLETED" } +# +## +{ 'event': 'SPICE_MIGRATE_COMPLETED', + 'if': 'CONFIG_SPICE' } + +## +# == VNC +## + +## +# @VncBasicInfo: +# +# The basic information for vnc network connection +# +# @host: IP address +# +# @service: The service name of the vnc port. This may depend on the host +# system's service database so symbolic names should not be relied +# on. +# +# @family: address family +# +# @websocket: true in case the socket is a websocket (since 2.3). +# +# Since: 2.1 +## +{ 'struct': 'VncBasicInfo', + 'data': { 'host': 'str', + 'service': 'str', + 'family': 'NetworkAddressFamily', + 'websocket': 'bool' }, + 'if': 'CONFIG_VNC' } + +## +# @VncServerInfo: +# +# The network connection information for server +# +# @auth: authentication method used for +# the plain (non-websocket) VNC server +# +# Since: 2.1 +## +{ 'struct': 'VncServerInfo', + 'base': 'VncBasicInfo', + 'data': { '*auth': 'str' }, + 'if': 'CONFIG_VNC' } + +## +# @VncClientInfo: +# +# Information about a connected VNC client. +# +# @x509_dname: If x509 authentication is in use, the Distinguished +# Name of the client. +# +# @sasl_username: If SASL authentication is in use, the SASL username +# used for authentication. +# +# Since: 0.14 +## +{ 'struct': 'VncClientInfo', + 'base': 'VncBasicInfo', + 'data': { '*x509_dname': 'str', '*sasl_username': 'str' }, + 'if': 'CONFIG_VNC' } + +## +# @VncInfo: +# +# Information about the VNC session. +# +# @enabled: true if the VNC server is enabled, false otherwise +# +# @host: The hostname the VNC server is bound to. This depends on +# the name resolution on the host and may be an IP address. +# +# @family: - 'ipv6' if the host is listening for IPv6 connections +# - 'ipv4' if the host is listening for IPv4 connections +# - 'unix' if the host is listening on a unix domain socket +# - 'unknown' otherwise +# +# @service: The service name of the server's port. This may depends +# on the host system's service database so symbolic names should not +# be relied on. +# +# @auth: the current authentication type used by the server +# +# - 'none' if no authentication is being used +# - 'vnc' if VNC authentication is being used +# - 'vencrypt+plain' if VEncrypt is used with plain text authentication +# - 'vencrypt+tls+none' if VEncrypt is used with TLS and no authentication +# - 'vencrypt+tls+vnc' if VEncrypt is used with TLS and VNC authentication +# - 'vencrypt+tls+plain' if VEncrypt is used with TLS and plain text auth +# - 'vencrypt+x509+none' if VEncrypt is used with x509 and no auth +# - 'vencrypt+x509+vnc' if VEncrypt is used with x509 and VNC auth +# - 'vencrypt+x509+plain' if VEncrypt is used with x509 and plain text auth +# - 'vencrypt+tls+sasl' if VEncrypt is used with TLS and SASL auth +# - 'vencrypt+x509+sasl' if VEncrypt is used with x509 and SASL auth +# +# @clients: a list of @VncClientInfo of all currently connected clients +# +# Since: 0.14 +## +{ 'struct': 'VncInfo', + 'data': {'enabled': 'bool', '*host': 'str', + '*family': 'NetworkAddressFamily', + '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']}, + 'if': 'CONFIG_VNC' } + +## +# @VncPrimaryAuth: +# +# vnc primary authentication method. +# +# Since: 2.3 +## +{ 'enum': 'VncPrimaryAuth', + 'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra', + 'tls', 'vencrypt', 'sasl' ], + 'if': 'CONFIG_VNC' } + +## +# @VncVencryptSubAuth: +# +# vnc sub authentication method with vencrypt. +# +# Since: 2.3 +## +{ 'enum': 'VncVencryptSubAuth', + 'data': [ 'plain', + 'tls-none', 'x509-none', + 'tls-vnc', 'x509-vnc', + 'tls-plain', 'x509-plain', + 'tls-sasl', 'x509-sasl' ], + 'if': 'CONFIG_VNC' } + +## +# @VncServerInfo2: +# +# The network connection information for server +# +# @auth: The current authentication type used by the servers +# +# @vencrypt: The vencrypt sub authentication type used by the +# servers, only specified in case auth == vencrypt. +# +# Since: 2.9 +## +{ 'struct': 'VncServerInfo2', + 'base': 'VncBasicInfo', + 'data': { 'auth' : 'VncPrimaryAuth', + '*vencrypt' : 'VncVencryptSubAuth' }, + 'if': 'CONFIG_VNC' } + +## +# @VncInfo2: +# +# Information about a vnc server +# +# @id: vnc server name. +# +# @server: A list of @VncBasincInfo describing all listening sockets. +# The list can be empty (in case the vnc server is disabled). +# It also may have multiple entries: normal + websocket, +# possibly also ipv4 + ipv6 in the future. +# +# @clients: A list of @VncClientInfo of all currently connected clients. +# The list can be empty, for obvious reasons. +# +# @auth: The current authentication type used by the non-websockets servers +# +# @vencrypt: The vencrypt authentication type used by the servers, +# only specified in case auth == vencrypt. +# +# @display: The display device the vnc server is linked to. +# +# Since: 2.3 +## +{ 'struct': 'VncInfo2', + 'data': { 'id' : 'str', + 'server' : ['VncServerInfo2'], + 'clients' : ['VncClientInfo'], + 'auth' : 'VncPrimaryAuth', + '*vencrypt' : 'VncVencryptSubAuth', + '*display' : 'str' }, + 'if': 'CONFIG_VNC' } + +## +# @query-vnc: +# +# Returns information about the current VNC server +# +# Returns: @VncInfo +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-vnc" } +# <- { "return": { +# "enabled":true, +# "host":"0.0.0.0", +# "service":"50402", +# "auth":"vnc", +# "family":"ipv4", +# "clients":[ +# { +# "host":"127.0.0.1", +# "service":"50401", +# "family":"ipv4" +# } +# ] +# } +# } +# +## +{ 'command': 'query-vnc', 'returns': 'VncInfo', + 'if': 'CONFIG_VNC' } +## +# @query-vnc-servers: +# +# Returns a list of vnc servers. The list can be empty. +# +# Returns: a list of @VncInfo2 +# +# Since: 2.3 +## +{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'], + 'if': 'CONFIG_VNC' } + +## +# @change-vnc-password: +# +# Change the VNC server password. +# +# @password: the new password to use with VNC authentication +# +# Since: 1.1 +# +# Notes: An empty password in this command will set the password to the empty +# string. Existing clients are unaffected by executing this command. +## +{ 'command': 'change-vnc-password', + 'data': { 'password': 'str' }, + 'if': 'CONFIG_VNC' } + +## +# @VNC_CONNECTED: +# +# Emitted when a VNC client establishes a connection +# +# @server: server information +# +# @client: client information +# +# Note: This event is emitted before any authentication takes place, thus +# the authentication ID is not provided +# +# Since: 0.13 +# +# Example: +# +# <- { "event": "VNC_CONNECTED", +# "data": { +# "server": { "auth": "sasl", "family": "ipv4", +# "service": "5901", "host": "0.0.0.0" }, +# "client": { "family": "ipv4", "service": "58425", +# "host": "127.0.0.1" } }, +# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } } +# +## +{ 'event': 'VNC_CONNECTED', + 'data': { 'server': 'VncServerInfo', + 'client': 'VncBasicInfo' }, + 'if': 'CONFIG_VNC' } + +## +# @VNC_INITIALIZED: +# +# Emitted after authentication takes place (if any) and the VNC session is +# made active +# +# @server: server information +# +# @client: client information +# +# Since: 0.13 +# +# Example: +# +# <- { "event": "VNC_INITIALIZED", +# "data": { +# "server": { "auth": "sasl", "family": "ipv4", +# "service": "5901", "host": "0.0.0.0"}, +# "client": { "family": "ipv4", "service": "46089", +# "host": "127.0.0.1", "sasl_username": "luiz" } }, +# "timestamp": { "seconds": 1263475302, "microseconds": 150772 } } +# +## +{ 'event': 'VNC_INITIALIZED', + 'data': { 'server': 'VncServerInfo', + 'client': 'VncClientInfo' }, + 'if': 'CONFIG_VNC' } + +## +# @VNC_DISCONNECTED: +# +# Emitted when the connection is closed +# +# @server: server information +# +# @client: client information +# +# Since: 0.13 +# +# Example: +# +# <- { "event": "VNC_DISCONNECTED", +# "data": { +# "server": { "auth": "sasl", "family": "ipv4", +# "service": "5901", "host": "0.0.0.0" }, +# "client": { "family": "ipv4", "service": "58425", +# "host": "127.0.0.1", "sasl_username": "luiz" } }, +# "timestamp": { "seconds": 1262976601, "microseconds": 975795 } } +# +## +{ 'event': 'VNC_DISCONNECTED', + 'data': { 'server': 'VncServerInfo', + 'client': 'VncClientInfo' }, + 'if': 'CONFIG_VNC' } + +## +# = Input +## + +## +# @MouseInfo: +# +# Information about a mouse device. +# +# @name: the name of the mouse device +# +# @index: the index of the mouse device +# +# @current: true if this device is currently receiving mouse events +# +# @absolute: true if this device supports absolute coordinates as input +# +# Since: 0.14 +## +{ 'struct': 'MouseInfo', + 'data': {'name': 'str', 'index': 'int', 'current': 'bool', + 'absolute': 'bool'} } + +## +# @query-mice: +# +# Returns information about each active mouse device +# +# Returns: a list of @MouseInfo for each device +# +# Since: 0.14 +# +# Example: +# +# -> { "execute": "query-mice" } +# <- { "return": [ +# { +# "name":"QEMU Microsoft Mouse", +# "index":0, +# "current":false, +# "absolute":false +# }, +# { +# "name":"QEMU PS/2 Mouse", +# "index":1, +# "current":true, +# "absolute":true +# } +# ] +# } +# +## +{ 'command': 'query-mice', 'returns': ['MouseInfo'] } + +## +# @QKeyCode: +# +# An enumeration of key name. +# +# This is used by the @send-key command. +# +# @unmapped: since 2.0 +# @pause: since 2.0 +# @ro: since 2.4 +# @kp_comma: since 2.4 +# @kp_equals: since 2.6 +# @power: since 2.6 +# @hiragana: since 2.9 +# @henkan: since 2.9 +# @yen: since 2.9 +# +# @sleep: since 2.10 +# @wake: since 2.10 +# @audionext: since 2.10 +# @audioprev: since 2.10 +# @audiostop: since 2.10 +# @audioplay: since 2.10 +# @audiomute: since 2.10 +# @volumeup: since 2.10 +# @volumedown: since 2.10 +# @mediaselect: since 2.10 +# @mail: since 2.10 +# @calculator: since 2.10 +# @computer: since 2.10 +# @ac_home: since 2.10 +# @ac_back: since 2.10 +# @ac_forward: since 2.10 +# @ac_refresh: since 2.10 +# @ac_bookmarks: since 2.10 +# +# @muhenkan: since 2.12 +# @katakanahiragana: since 2.12 +# +# @lang1: since 6.1 +# @lang2: since 6.1 +# +# 'sysrq' was mistakenly added to hack around the fact that +# the ps2 driver was not generating correct scancodes sequences +# when 'alt+print' was pressed. This flaw is now fixed and the +# 'sysrq' key serves no further purpose. Any further use of +# 'sysrq' will be transparently changed to 'print', so they +# are effectively synonyms. +# +# Since: 1.3 +# +## +{ 'enum': 'QKeyCode', + 'data': [ 'unmapped', + 'shift', 'shift_r', 'alt', 'alt_r', 'ctrl', + 'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e', + 'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right', + 'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon', + 'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b', + 'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock', + 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', + 'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply', + 'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0', + 'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8', + 'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end', + 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', + 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', + 'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', + 'ro', 'hiragana', 'henkan', 'yen', 'muhenkan', 'katakanahiragana', + 'kp_comma', 'kp_equals', 'power', 'sleep', 'wake', + 'audionext', 'audioprev', 'audiostop', 'audioplay', 'audiomute', + 'volumeup', 'volumedown', 'mediaselect', + 'mail', 'calculator', 'computer', + 'ac_home', 'ac_back', 'ac_forward', 'ac_refresh', 'ac_bookmarks', + 'lang1', 'lang2' ] } + +## +# @KeyValueKind: +# +# Since: 1.3 +## +{ 'enum': 'KeyValueKind', + 'data': [ 'number', 'qcode' ] } + +## +# @IntWrapper: +# +# Since: 1.3 +## +{ 'struct': 'IntWrapper', + 'data': { 'data': 'int' } } + +## +# @QKeyCodeWrapper: +# +# Since: 1.3 +## +{ 'struct': 'QKeyCodeWrapper', + 'data': { 'data': 'QKeyCode' } } + +## +# @KeyValue: +# +# Represents a keyboard key. +# +# Since: 1.3 +## +{ 'union': 'KeyValue', + 'base': { 'type': 'KeyValueKind' }, + 'discriminator': 'type', + 'data': { + 'number': 'IntWrapper', + 'qcode': 'QKeyCodeWrapper' } } + +## +# @send-key: +# +# Send keys to guest. +# +# @keys: An array of @KeyValue elements. All @KeyValues in this array are +# simultaneously sent to the guest. A @KeyValue.number value is sent +# directly to the guest, while @KeyValue.qcode must be a valid +# @QKeyCode value +# +# @hold-time: time to delay key up events, milliseconds. Defaults +# to 100 +# +# Returns: - Nothing on success +# - If key is unknown or redundant, InvalidParameter +# +# Since: 1.3 +# +# Example: +# +# -> { "execute": "send-key", +# "arguments": { "keys": [ { "type": "qcode", "data": "ctrl" }, +# { "type": "qcode", "data": "alt" }, +# { "type": "qcode", "data": "delete" } ] } } +# <- { "return": {} } +# +## +{ 'command': 'send-key', + 'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } } + +## +# @InputButton: +# +# Button of a pointer input device (mouse, tablet). +# +# @side: front side button of a 5-button mouse (since 2.9) +# +# @extra: rear side button of a 5-button mouse (since 2.9) +# +# Since: 2.0 +## +{ 'enum' : 'InputButton', + 'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down', 'side', + 'extra' ] } + +## +# @InputAxis: +# +# Position axis of a pointer input device (mouse, tablet). +# +# Since: 2.0 +## +{ 'enum' : 'InputAxis', + 'data' : [ 'x', 'y' ] } + +## +# @InputKeyEvent: +# +# Keyboard input event. +# +# @key: Which key this event is for. +# @down: True for key-down and false for key-up events. +# +# Since: 2.0 +## +{ 'struct' : 'InputKeyEvent', + 'data' : { 'key' : 'KeyValue', + 'down' : 'bool' } } + +## +# @InputBtnEvent: +# +# Pointer button input event. +# +# @button: Which button this event is for. +# @down: True for key-down and false for key-up events. +# +# Since: 2.0 +## +{ 'struct' : 'InputBtnEvent', + 'data' : { 'button' : 'InputButton', + 'down' : 'bool' } } + +## +# @InputMoveEvent: +# +# Pointer motion input event. +# +# @axis: Which axis is referenced by @value. +# @value: Pointer position. For absolute coordinates the +# valid range is 0 -> 0x7ffff +# +# Since: 2.0 +## +{ 'struct' : 'InputMoveEvent', + 'data' : { 'axis' : 'InputAxis', + 'value' : 'int' } } + +## +# @InputEventKind: +# +# Since: 2.0 +## +{ 'enum': 'InputEventKind', + 'data': [ 'key', 'btn', 'rel', 'abs' ] } + +## +# @InputKeyEventWrapper: +# +# Since: 2.0 +## +{ 'struct': 'InputKeyEventWrapper', + 'data': { 'data': 'InputKeyEvent' } } + +## +# @InputBtnEventWrapper: +# +# Since: 2.0 +## +{ 'struct': 'InputBtnEventWrapper', + 'data': { 'data': 'InputBtnEvent' } } + +## +# @InputMoveEventWrapper: +# +# Since: 2.0 +## +{ 'struct': 'InputMoveEventWrapper', + 'data': { 'data': 'InputMoveEvent' } } + +## +# @InputEvent: +# +# Input event union. +# +# @type: the input type, one of: +# +# - 'key': Input event of Keyboard +# - 'btn': Input event of pointer buttons +# - 'rel': Input event of relative pointer motion +# - 'abs': Input event of absolute pointer motion +# +# Since: 2.0 +## +{ 'union' : 'InputEvent', + 'base': { 'type': 'InputEventKind' }, + 'discriminator': 'type', + 'data' : { 'key' : 'InputKeyEventWrapper', + 'btn' : 'InputBtnEventWrapper', + 'rel' : 'InputMoveEventWrapper', + 'abs' : 'InputMoveEventWrapper' } } + +## +# @input-send-event: +# +# Send input event(s) to guest. +# +# The @device and @head parameters can be used to send the input event +# to specific input devices in case (a) multiple input devices of the +# same kind are added to the virtual machine and (b) you have +# configured input routing (see docs/multiseat.txt) for those input +# devices. The parameters work exactly like the device and head +# properties of input devices. If @device is missing, only devices +# that have no input routing config are admissible. If @device is +# specified, both input devices with and without input routing config +# are admissible, but devices with input routing config take +# precedence. +# +# @device: display device to send event(s) to. +# @head: head to send event(s) to, in case the +# display device supports multiple scanouts. +# @events: List of InputEvent union. +# +# Returns: Nothing on success. +# +# Since: 2.6 +# +# Note: The consoles are visible in the qom tree, under +# /backend/console[$index]. They have a device link and head property, +# so it is possible to map which console belongs to which device and +# display. +# +# Example: +# +# 1. Press left mouse button. +# +# -> { "execute": "input-send-event", +# "arguments": { "device": "video0", +# "events": [ { "type": "btn", +# "data" : { "down": true, "button": "left" } } ] } } +# <- { "return": {} } +# +# -> { "execute": "input-send-event", +# "arguments": { "device": "video0", +# "events": [ { "type": "btn", +# "data" : { "down": false, "button": "left" } } ] } } +# <- { "return": {} } +# +# 2. Press ctrl-alt-del. +# +# -> { "execute": "input-send-event", +# "arguments": { "events": [ +# { "type": "key", "data" : { "down": true, +# "key": {"type": "qcode", "data": "ctrl" } } }, +# { "type": "key", "data" : { "down": true, +# "key": {"type": "qcode", "data": "alt" } } }, +# { "type": "key", "data" : { "down": true, +# "key": {"type": "qcode", "data": "delete" } } } ] } } +# <- { "return": {} } +# +# 3. Move mouse pointer to absolute coordinates (20000, 400). +# +# -> { "execute": "input-send-event" , +# "arguments": { "events": [ +# { "type": "abs", "data" : { "axis": "x", "value" : 20000 } }, +# { "type": "abs", "data" : { "axis": "y", "value" : 400 } } ] } } +# <- { "return": {} } +# +## +{ 'command': 'input-send-event', + 'data': { '*device': 'str', + '*head' : 'int', + 'events' : [ 'InputEvent' ] } } + +## +# @DisplayGTK: +# +# GTK display options. +# +# @grab-on-hover: Grab keyboard input on mouse hover. +# @zoom-to-fit: Zoom guest display to fit into the host window. When +# turned off the host window will be resized instead. +# In case the display device can notify the guest on +# window resizes (virtio-gpu) this will default to "on", +# assuming the guest will resize the display to match +# the window size then. Otherwise it defaults to "off". +# Since 3.1 +# +# Since: 2.12 +# +## +{ 'struct' : 'DisplayGTK', + 'data' : { '*grab-on-hover' : 'bool', + '*zoom-to-fit' : 'bool' } } + +## +# @DisplayEGLHeadless: +# +# EGL headless display options. +# +# @rendernode: Which DRM render node should be used. Default is the first +# available node on the host. +# +# Since: 3.1 +# +## +{ 'struct' : 'DisplayEGLHeadless', + 'data' : { '*rendernode' : 'str' } } + + ## + # @DisplayGLMode: + # + # Display OpenGL mode. + # + # @off: Disable OpenGL (default). + # @on: Use OpenGL, pick context type automatically. + # Would better be named 'auto' but is called 'on' for backward + # compatibility with bool type. + # @core: Use OpenGL with Core (desktop) Context. + # @es: Use OpenGL with ES (embedded systems) Context. + # + # Since: 3.0 + # + ## +{ 'enum' : 'DisplayGLMode', + 'data' : [ 'off', 'on', 'core', 'es' ] } + +## +# @DisplayCurses: +# +# Curses display options. +# +# @charset: Font charset used by guest (default: CP437). +# +# Since: 4.0 +# +## +{ 'struct' : 'DisplayCurses', + 'data' : { '*charset' : 'str' } } + +## +# @DisplayType: +# +# Display (user interface) type. +# +# @default: The default user interface, selecting from the first available +# of gtk, sdl, cocoa, and vnc. +# +# @none: No user interface or video output display. The guest will +# still see an emulated graphics card, but its output will not +# be displayed to the QEMU user. +# +# @gtk: The GTK user interface. +# +# @sdl: The SDL user interface. +# +# @egl-headless: No user interface, offload GL operations to a local +# DRI device. Graphical display need to be paired with +# VNC or Spice. (Since 3.1) +# +# @curses: Display video output via curses. For graphics device +# models which support a text mode, QEMU can display this +# output using a curses/ncurses interface. Nothing is +# displayed when the graphics device is in graphical mode or +# if the graphics device does not support a text +# mode. Generally only the VGA device models support text +# mode. +# +# @cocoa: The Cocoa user interface. +# +# @spice-app: Set up a Spice server and run the default associated +# application to connect to it. The server will redirect +# the serial console and QEMU monitors. (Since 4.0) +# +# Since: 2.12 +# +## +{ 'enum' : 'DisplayType', + 'data' : [ + { 'name': 'default' }, + { 'name': 'none' }, + { 'name': 'gtk', 'if': 'CONFIG_GTK' }, + { 'name': 'sdl', 'if': 'CONFIG_SDL' }, + { 'name': 'egl-headless', + 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }, + { 'name': 'curses', 'if': 'CONFIG_CURSES' }, + { 'name': 'cocoa', 'if': 'CONFIG_COCOA' }, + { 'name': 'spice-app', 'if': 'CONFIG_SPICE'} ] } + +## +# @DisplayOptions: +# +# Display (user interface) options. +# +# @type: Which DisplayType qemu should use. +# @full-screen: Start user interface in fullscreen mode (default: off). +# @window-close: Allow to quit qemu with window close button (default: on). +# @show-cursor: Force showing the mouse cursor (default: off). +# (since: 5.0) +# @gl: Enable OpenGL support (default: off). +# +# Since: 2.12 +# +## +{ 'union' : 'DisplayOptions', + 'base' : { 'type' : 'DisplayType', + '*full-screen' : 'bool', + '*window-close' : 'bool', + '*show-cursor' : 'bool', + '*gl' : 'DisplayGLMode' }, + 'discriminator' : 'type', + 'data' : { + 'gtk': { 'type': 'DisplayGTK', 'if': 'CONFIG_GTK' }, + 'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' }, + 'egl-headless': { 'type': 'DisplayEGLHeadless', + 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } } + } +} + +## +# @query-display-options: +# +# Returns information about display configuration +# +# Returns: @DisplayOptions +# +# Since: 3.1 +# +## +{ 'command': 'query-display-options', + 'returns': 'DisplayOptions' } + +## +# @DisplayReloadType: +# +# Available DisplayReload types. +# +# @vnc: VNC display +# +# Since: 6.0 +# +## +{ 'enum': 'DisplayReloadType', + 'data': ['vnc'] } + +## +# @DisplayReloadOptionsVNC: +# +# Specify the VNC reload options. +# +# @tls-certs: reload tls certs or not. +# +# Since: 6.0 +# +## +{ 'struct': 'DisplayReloadOptionsVNC', + 'data': { '*tls-certs': 'bool' } } + +## +# @DisplayReloadOptions: +# +# Options of the display configuration reload. +# +# @type: Specify the display type. +# +# Since: 6.0 +# +## +{ 'union': 'DisplayReloadOptions', + 'base': {'type': 'DisplayReloadType'}, + 'discriminator': 'type', + 'data': { 'vnc': 'DisplayReloadOptionsVNC' } } + +## +# @display-reload: +# +# Reload display configuration. +# +# Returns: Nothing on success. +# +# Since: 6.0 +# +# Example: +# +# -> { "execute": "display-reload", +# "arguments": { "type": "vnc", "tls-certs": true } } +# <- { "return": {} } +# +## +{ 'command': 'display-reload', + 'data': 'DisplayReloadOptions', + 'boxed' : true } diff --git a/qapi/yank.json b/qapi/yank.json new file mode 100644 index 000000000..167a77559 --- /dev/null +++ b/qapi/yank.json @@ -0,0 +1,119 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Yank feature +## + +## +# @YankInstanceType: +# +# An enumeration of yank instance types. See @YankInstance for more +# information. +# +# Since: 6.0 +## +{ 'enum': 'YankInstanceType', + 'data': [ 'block-node', 'chardev', 'migration' ] } + +## +# @YankInstanceBlockNode: +# +# Specifies which block graph node to yank. See @YankInstance for more +# information. +# +# @node-name: the name of the block graph node +# +# Since: 6.0 +## +{ 'struct': 'YankInstanceBlockNode', + 'data': { 'node-name': 'str' } } + +## +# @YankInstanceChardev: +# +# Specifies which character device to yank. See @YankInstance for more +# information. +# +# @id: the chardev's ID +# +# Since: 6.0 +## +{ 'struct': 'YankInstanceChardev', + 'data': { 'id': 'str' } } + +## +# @YankInstance: +# +# A yank instance can be yanked with the @yank qmp command to recover from a +# hanging QEMU. +# +# Currently implemented yank instances: +# - nbd block device: +# Yanking it will shut down the connection to the nbd server without +# attempting to reconnect. +# - socket chardev: +# Yanking it will shut down the connected socket. +# - migration: +# Yanking it will shut down all migration connections. Unlike +# @migrate_cancel, it will not notify the migration process, so migration +# will go into @failed state, instead of @cancelled state. @yank should be +# used to recover from hangs. +# +# Since: 6.0 +## +{ 'union': 'YankInstance', + 'base': { 'type': 'YankInstanceType' }, + 'discriminator': 'type', + 'data': { + 'block-node': 'YankInstanceBlockNode', + 'chardev': 'YankInstanceChardev' } } + +## +# @yank: +# +# Try to recover from hanging QEMU by yanking the specified instances. See +# @YankInstance for more information. +# +# Takes a list of @YankInstance as argument. +# +# Returns: - Nothing on success +# - @DeviceNotFound error, if any of the YankInstances doesn't exist +# +# Example: +# +# -> { "execute": "yank", +# "arguments": { +# "instances": [ +# { "type": "block-node", +# "node-name": "nbd0" } +# ] } } +# <- { "return": {} } +# +# Since: 6.0 +## +{ 'command': 'yank', + 'data': { 'instances': ['YankInstance'] }, + 'allow-oob': true } + +## +# @query-yank: +# +# Query yank instances. See @YankInstance for more information. +# +# Returns: list of @YankInstance +# +# Example: +# +# -> { "execute": "query-yank" } +# <- { "return": [ +# { "type": "block-node", +# "node-name": "nbd0" } +# ] } +# +# Since: 6.0 +## +{ 'command': 'query-yank', + 'returns': ['YankInstance'], + 'allow-oob': true } |