libvirt/src/qemu/qemu_monitor_json.h

706 lines
29 KiB
C
Raw Normal View History

/*
* qemu_monitor_json.h: interaction with QEMU monitor console
*
qemu: read backing chain names from qemu https://bugzilla.redhat.com/show_bug.cgi?id=1199182 documents that after a series of disk snapshots into existing destination images, followed by active commits of the top image, it is possible for qemu 2.2 and earlier to end up tracking a different name for the image than what it would have had when opening the chain afresh. That is, when starting with the chain 'a <- b <- c', the name associated with 'b' is how it was spelled in the metadata of 'c', but when starting with 'a', taking two snapshots into 'a <- b <- c', then committing 'c' back into 'b', the name associated with 'b' is now the name used when taking the first snapshot. Sadly, older qemu doesn't know how to treat different spellings of the same filename as identical files (it uses strcmp() instead of checking for the same inode), which means libvirt's attempt to commit an image using solely the names learned from qcow2 metadata fails with a cryptic: error: internal error: unable to execute QEMU command 'block-commit': Top image file /tmp/images/c/../b/b not found even though the file exists. Trying to teach libvirt the rules on which name qemu will expect is not worth the effort (besides, we'd have to remember it across libvirtd restarts, and track whether a file was opened via metadata or via snapshot creation for a given qemu process); it is easier to just always directly ask qemu what string it expects to see in the first place. As a safety valve, we validate that any name returned by qemu still maps to the same local file as we have tracked it, so that a compromised qemu cannot accidentally cause us to act on an incorrect file. * src/qemu/qemu_monitor.h (qemuMonitorDiskNameLookup): New prototype. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDiskNameLookup): Likewise. * src/qemu/qemu_monitor.c (qemuMonitorDiskNameLookup): New function. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONDiskNameLookup) (qemuMonitorJSONDiskNameLookupOne): Likewise. * src/qemu/qemu_driver.c (qemuDomainBlockCommit) (qemuDomainBlockJobImpl): Use it. Signed-off-by: Eric Blake <eblake@redhat.com>
2015-03-11 20:37:04 +00:00
* Copyright (C) 2006-2009, 2011-2015 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "internal.h"
#include "qemu_monitor.h"
#include "virbitmap.h"
#include "cpu/cpu.h"
#include "util/virgic.h"
int qemuMonitorJSONIOProcessLine(qemuMonitor *mon,
const char *line,
qemuMonitorMessage *msg) G_GNUC_NO_INLINE;
int qemuMonitorJSONIOProcess(qemuMonitor *mon,
const char *data,
size_t len,
qemuMonitorMessage *msg);
int qemuMonitorJSONHumanCommand(qemuMonitor *mon,
const char *cmd,
char **reply);
int qemuMonitorJSONSetCapabilities(qemuMonitor *mon);
int qemuMonitorJSONStartCPUs(qemuMonitor *mon);
int qemuMonitorJSONStopCPUs(qemuMonitor *mon);
int qemuMonitorJSONGetStatus(qemuMonitor *mon,
bool *running,
virDomainPausedReason *reason);
int qemuMonitorJSONSystemPowerdown(qemuMonitor *mon);
int qemuMonitorJSONSystemReset(qemuMonitor *mon);
int qemuMonitorJSONQueryCPUs(qemuMonitor *mon,
struct qemuMonitorQueryCpusEntry **entries,
size_t *nentries,
bool force,
bool fast);
int qemuMonitorJSONUpdateVideoMemorySize(qemuMonitor *mon,
virDomainVideoDef *video,
char *path);
int qemuMonitorJSONUpdateVideoVram64Size(qemuMonitor *mon,
virDomainVideoDef *video,
char *path);
int qemuMonitorJSONGetBalloonInfo(qemuMonitor *mon,
xml: use better types for memory values Using 'unsigned long' for memory values is risky on 32-bit platforms, as a PAE guest can have more than 4GiB memory. Our API is (unfortunately) locked at 'unsigned long' and a scale of 1024, but the rest of our system should consistently use 64-bit values, especially since the previous patch centralized overflow checking. * src/conf/domain_conf.h (_virDomainDef): Always use 64-bit values for memory. Change hugepage_backed to a bool. * src/conf/domain_conf.c (virDomainDefParseXML) (virDomainDefCheckABIStability, virDomainDefFormatInternal): Fix clients. * src/vmx/vmx.c (virVMXFormatConfig): Likewise. * src/xenxs/xen_sxpr.c (xenParseSxpr, xenFormatSxpr): Likewise. * src/xenxs/xen_xm.c (xenXMConfigGetULongLong): New function. (xenXMConfigGetULong, xenXMConfigSetInt): Avoid truncation. (xenParseXM, xenFormatXM): Fix clients. * src/phyp/phyp_driver.c (phypBuildLpar): Likewise. * src/openvz/openvz_driver.c (openvzDomainSetMemoryInternal): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainDefineXML): Likewise. * src/qemu/qemu_command.c (qemuBuildCommandLine): Likewise. * src/qemu/qemu_process.c (qemuProcessStart): Likewise. * src/qemu/qemu_monitor.h (qemuMonitorGetBalloonInfo): Likewise. * src/qemu/qemu_monitor_text.h (qemuMonitorTextGetBalloonInfo): Likewise. * src/qemu/qemu_monitor_text.c (qemuMonitorTextGetBalloonInfo): Likewise. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONGetBalloonInfo): Likewise. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONGetBalloonInfo): Likewise. * src/qemu/qemu_driver.c (qemudDomainGetInfo) (qemuDomainGetXMLDesc): Likewise. * src/uml/uml_conf.c (umlBuildCommandLine): Likewise.
2012-03-02 20:27:39 +00:00
unsigned long long *currmem);
int qemuMonitorJSONGetMemoryStats(qemuMonitor *mon,
char *balloonpath,
virDomainMemoryStatPtr stats,
unsigned int nr_stats);
int qemuMonitorJSONSetMemoryStatsPeriod(qemuMonitor *mon,
char *balloonpath,
int period);
int qemuMonitorJSONGetBlockInfo(qemuMonitor *mon,
GHashTable *table);
virJSONValue *qemuMonitorJSONQueryBlockstats(qemuMonitor *mon);
int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitor *mon,
GHashTable *hash,
bool backingChain);
int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitor *mon,
GHashTable *stats,
bool backingChain);
int qemuMonitorJSONBlockStatsUpdateCapacityBlockdev(qemuMonitor *mon,
GHashTable *stats);
GHashTable *
qemuMonitorJSONBlockGetNamedNodeDataJSON(virJSONValue *nodes);
GHashTable *
qemuMonitorJSONBlockGetNamedNodeData(qemuMonitor *mon,
bool supports_flat);
int qemuMonitorJSONBlockResize(qemuMonitor *mon,
const char *device,
const char *nodename,
unsigned long long size);
int qemuMonitorJSONSetPassword(qemuMonitor *mon,
const char *protocol,
const char *password,
const char *action_if_connected);
int qemuMonitorJSONExpirePassword(qemuMonitor *mon,
const char *protocol,
const char *expire_time);
int qemuMonitorJSONSetBalloon(qemuMonitor *mon,
unsigned long long newmem);
int qemuMonitorJSONSetCPU(qemuMonitor *mon, int cpu, bool online);
int qemuMonitorJSONEjectMedia(qemuMonitor *mon,
const char *dev_name,
bool force);
int qemuMonitorJSONChangeMedia(qemuMonitor *mon,
const char *dev_name,
const char *newmedia,
const char *format);
int qemuMonitorJSONSaveVirtualMemory(qemuMonitor *mon,
unsigned long long offset,
unsigned long long length,
const char *path);
int qemuMonitorJSONSavePhysicalMemory(qemuMonitor *mon,
unsigned long long offset,
unsigned long long length,
const char *path);
int qemuMonitorJSONSetMigrationSpeed(qemuMonitor *mon,
unsigned long bandwidth);
int qemuMonitorJSONSetMigrationDowntime(qemuMonitor *mon,
unsigned long long downtime);
int qemuMonitorJSONGetMigrationCacheSize(qemuMonitor *mon,
unsigned long long *cacheSize);
int qemuMonitorJSONSetMigrationCacheSize(qemuMonitor *mon,
unsigned long long cacheSize);
int qemuMonitorJSONGetMigrationParams(qemuMonitor *mon,
virJSONValue **params);
int qemuMonitorJSONSetMigrationParams(qemuMonitor *mon,
virJSONValue **params);
int qemuMonitorJSONGetMigrationStats(qemuMonitor *mon,
qemuMonitorMigrationStats *stats,
char **error);
int qemuMonitorJSONGetMigrationCapabilities(qemuMonitor *mon,
2014-09-11 12:11:54 +00:00
char ***capabilities);
int qemuMonitorJSONSetMigrationCapabilities(qemuMonitor *mon,
virJSONValue **caps);
int qemuMonitorJSONGetGICCapabilities(qemuMonitor *mon,
virGICCapability **capabilities);
int qemuMonitorJSONGetSEVCapabilities(qemuMonitor *mon,
virSEVCapability **capabilities);
int qemuMonitorJSONMigrate(qemuMonitor *mon,
unsigned int flags,
const char *uri);
int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitor *mon,
bool *spice_migrated);
int qemuMonitorJSONMigrateCancel(qemuMonitor *mon);
int qemuMonitorJSONQueryDump(qemuMonitor *mon,
qemuMonitorDumpStats *stats);
int qemuMonitorJSONGetDumpGuestMemoryCapability(qemuMonitor *mon,
const char *capability);
int qemuMonitorJSONDump(qemuMonitor *mon,
const char *protocol,
const char *dumpformat,
bool detach);
int qemuMonitorJSONGraphicsRelocate(qemuMonitor *mon,
int type,
const char *hostname,
int port,
int tlsPort,
const char *tlsSubject);
int qemuMonitorJSONAddPCIHostDevice(qemuMonitor *mon,
virPCIDeviceAddress *hostAddr,
virPCIDeviceAddress *guestAddr);
int qemuMonitorJSONAddPCIDisk(qemuMonitor *mon,
const char *path,
const char *bus,
virPCIDeviceAddress *guestAddr);
int qemuMonitorJSONAddPCINetwork(qemuMonitor *mon,
const char *nicstr,
virPCIDeviceAddress *guestAddr);
int qemuMonitorJSONRemovePCIDevice(qemuMonitor *mon,
virPCIDeviceAddress *guestAddr);
int qemuMonitorJSONAddFileHandleToSet(qemuMonitor *mon,
int fd,
int fdset,
const char *opaque,
qemuMonitorAddFdInfo *info);
int qemuMonitorJSONRemoveFdset(qemuMonitor *mon,
int fdset);
int qemuMonitorJSONQueryFdsets(qemuMonitor *mon,
qemuMonitorFdsets **fdsets);
int qemuMonitorJSONSendFileHandle(qemuMonitor *mon,
const char *fdname,
int fd);
int qemuMonitorJSONCloseFileHandle(qemuMonitor *mon,
const char *fdname);
int qemuMonitorJSONAddNetdev(qemuMonitor *mon,
virJSONValue **props);
int qemuMonitorJSONRemoveNetdev(qemuMonitor *mon,
const char *alias);
int qemuMonitorJSONQueryRxFilter(qemuMonitor *mon, const char *alias,
virNetDevRxFilter **filter);
qemu: qemuMonitorQueryRxFilter - retrieve guest netdev rx-filter This function can be called at any time to get the current status of a guest's network device rx-filter. In particular it is useful to call after libvirt recieves a NIC_RX_FILTER_CHANGED event - this event only tells you that something has changed in the rx-filter, the details are retrieved with the query-rx-filter monitor command (only available in the json monitor). The command sent to the qemu monitor looks like this: {"execute":"query-rx-filter", "arguments": {"name":"net2"} }' and the results will look something like this: { "return": [ { "promiscuous": false, "name": "net2", "main-mac": "52:54:00:98:2d:e3", "unicast": "normal", "vlan": "normal", "vlan-table": [ 42, 0 ], "unicast-table": [ ], "multicast": "normal", "multicast-overflow": false, "unicast-overflow": false, "multicast-table": [ "33:33:ff:98:2d:e3", "01:80:c2:00:00:21", "01:00:5e:00:00:fb", "33:33:ff:98:2d:e2", "01:00:5e:00:00:01", "33:33:00:00:00:01" ], "broadcast-allowed": false } ], "id": "libvirt-14" } This is all parsed from JSON into a virNetDevRxFilter object for easier consumption. (unicast-table is usually empty, but is also an array of mac addresses similar to multicast-table). (NB: LIBNL_CFLAGS was added to tests/Makefile.am because virnetdev.h now includes util/virnetlink.h, which includes netlink/msg.h when appropriate. Without LIBNL_CFLAGS, gcc can't find that file (if libnl/netlink isn't available, LIBNL_CFLAGS will be empty and virnetlink.h won't try to include netlink/msg.h anyway).)
2014-09-22 16:19:41 +00:00
int qemuMonitorJSONGetChardevInfo(qemuMonitor *mon,
GHashTable *info);
int qemuMonitorJSONAttachPCIDiskController(qemuMonitor *mon,
const char *bus,
virPCIDeviceAddress *guestAddr);
int qemuMonitorJSONAddDeviceArgs(qemuMonitor *mon,
virJSONValue *args);
int qemuMonitorJSONAddDevice(qemuMonitor *mon,
const char *devicestr);
int qemuMonitorJSONDelDevice(qemuMonitor *mon,
const char *devalias);
int qemuMonitorJSONAddObject(qemuMonitor *mon,
virJSONValue **props);
int qemuMonitorJSONDelObject(qemuMonitor *mon,
const char *objalias,
bool report_error);
int qemuMonitorJSONTransaction(qemuMonitor *mon, virJSONValue **actions)
blockjob: add qemu capabilities related to block jobs Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror' and 'block-job-complete'[1], which can drive live block copy and storage migration. [Additionally, RHEL 6.3 had backported an earlier version of most of the same functionality, but under the names '__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with slightly different JSON arguments, and has been using patches similar to these upstream patches for several months now.] The libvirt API virDomainBlockRebase as already committed for 0.9.12 is flexible enough to expose the basics of block copy, but some additional features in the 'drive-mirror' qemu command, such as setting error policy, setting granularity, or using a persistent bitmap, may later require a new libvirt API virDomainBlockCopy. I will wait to add that API until we know more about what qemu 1.3 will finally provide. This patch caters only to the upstream qemu 1.3 interface, although I have proven that the changes for RHEL 6.3 can be isolated to just qemu_monitor_json.c, and the rest of this series will gracefully handle either interface once the JSON differences are papered over in a downstream patch. For consistency with other block job commands, libvirt must handle the bandwidth argument as MiB/sec from the user, even though qemu exposes the speed argument as bytes/sec; then again, qemu rounds up to cluster size internally, so using MiB hides the worst effects of that rounding if you pass small numbers. [1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html * src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR) (QEMU_CAPS_DRIVE_REOPEN): New bits. * src/qemu/qemu_capabilities.c (qemuCaps): Name them. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set them. (qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror) (qemuMonitorDrivePivot): Declare them. * src/qemu/qemu_monitor.c (qemuMonitorDriveMirror) (qemuMonitorDrivePivot): New passthroughs. * src/qemu/qemu_monitor.h (qemuMonitorDriveMirror) (qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONDriveMirror(qemuMonitor *mon,
blockjob: add qemu capabilities related to block jobs Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror' and 'block-job-complete'[1], which can drive live block copy and storage migration. [Additionally, RHEL 6.3 had backported an earlier version of most of the same functionality, but under the names '__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with slightly different JSON arguments, and has been using patches similar to these upstream patches for several months now.] The libvirt API virDomainBlockRebase as already committed for 0.9.12 is flexible enough to expose the basics of block copy, but some additional features in the 'drive-mirror' qemu command, such as setting error policy, setting granularity, or using a persistent bitmap, may later require a new libvirt API virDomainBlockCopy. I will wait to add that API until we know more about what qemu 1.3 will finally provide. This patch caters only to the upstream qemu 1.3 interface, although I have proven that the changes for RHEL 6.3 can be isolated to just qemu_monitor_json.c, and the rest of this series will gracefully handle either interface once the JSON differences are papered over in a downstream patch. For consistency with other block job commands, libvirt must handle the bandwidth argument as MiB/sec from the user, even though qemu exposes the speed argument as bytes/sec; then again, qemu rounds up to cluster size internally, so using MiB hides the worst effects of that rounding if you pass small numbers. [1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html * src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR) (QEMU_CAPS_DRIVE_REOPEN): New bits. * src/qemu/qemu_capabilities.c (qemuCaps): Name them. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set them. (qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror) (qemuMonitorDrivePivot): Declare them. * src/qemu/qemu_monitor.c (qemuMonitorDriveMirror) (qemuMonitorDrivePivot): New passthroughs. * src/qemu/qemu_monitor.h (qemuMonitorDriveMirror) (qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
const char *device,
const char *file,
const char *format,
unsigned long long speed,
blockcopy: add qemu implementation of new tunables Upstream qemu 1.4 added some drive-mirror tunables not present when it was first introduced in 1.3. Management apps may want to set these in some cases (for example, without tuning granularity down to sector size, a copy may end up occupying more bytes than the original because an entire cluster is copied even when only a sector within the cluster is dirty, although tuning it down results in more CPU time to do the copy). I haven't personally needed to use the parameters, but since they exist, and since the new API supports virTypedParams, we might as well expose them. Since the tuning parameters aren't often used, and omitted from the QMP command when unspecified, I think it is safe to rely on qemu 1.3 to issue an error about them being unsupported, rather than trying to create a new capability bit in libvirt. Meanwhile, all versions of qemu from 1.4 to 2.1 have a bug where a bad granularity (such as non-power-of-2) gives a poor message: error: internal error: unable to execute QEMU command 'drive-mirror': Invalid parameter 'drive-virtio-disk0' because of abuse of QERR_INVALID_PARAMETER (which is supposed to name the parameter that was given a bad value, rather than the value passed to some other parameter). I don't see that a capability check will help, so we'll just live with it (and it has since been improved in upstream qemu). * src/qemu/qemu_monitor.h (qemuMonitorDriveMirror): Add parameters. * src/qemu/qemu_monitor.c (qemuMonitorDriveMirror): Likewise. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror): Likewise. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONDriveMirror): Likewise. * src/qemu/qemu_driver.c (qemuDomainBlockCopyCommon): Likewise. (qemuDomainBlockRebase, qemuDomainBlockCopy): Adjust callers. * src/qemu/qemu_migration.c (qemuMigrationDriveMirror): Likewise. * tests/qemumonitorjsontest.c (qemuMonitorJSONDriveMirror): Likewise. Signed-off-by: Eric Blake <eblake@redhat.com>
2014-09-08 20:53:12 +00:00
unsigned int granularity,
unsigned long long buf_size,
bool shallow,
bool reuse)
blockjob: add qemu capabilities related to block jobs Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror' and 'block-job-complete'[1], which can drive live block copy and storage migration. [Additionally, RHEL 6.3 had backported an earlier version of most of the same functionality, but under the names '__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with slightly different JSON arguments, and has been using patches similar to these upstream patches for several months now.] The libvirt API virDomainBlockRebase as already committed for 0.9.12 is flexible enough to expose the basics of block copy, but some additional features in the 'drive-mirror' qemu command, such as setting error policy, setting granularity, or using a persistent bitmap, may later require a new libvirt API virDomainBlockCopy. I will wait to add that API until we know more about what qemu 1.3 will finally provide. This patch caters only to the upstream qemu 1.3 interface, although I have proven that the changes for RHEL 6.3 can be isolated to just qemu_monitor_json.c, and the rest of this series will gracefully handle either interface once the JSON differences are papered over in a downstream patch. For consistency with other block job commands, libvirt must handle the bandwidth argument as MiB/sec from the user, even though qemu exposes the speed argument as bytes/sec; then again, qemu rounds up to cluster size internally, so using MiB hides the worst effects of that rounding if you pass small numbers. [1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html * src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR) (QEMU_CAPS_DRIVE_REOPEN): New bits. * src/qemu/qemu_capabilities.c (qemuCaps): Name them. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set them. (qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror) (qemuMonitorDrivePivot): Declare them. * src/qemu/qemu_monitor.c (qemuMonitorDriveMirror) (qemuMonitorDrivePivot): New passthroughs. * src/qemu/qemu_monitor.h (qemuMonitorDriveMirror) (qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorJSONBlockdevMirror(qemuMonitor *mon,
const char *jobname,
bool persistjob,
const char *device,
const char *target,
unsigned long long speed,
unsigned int granularity,
unsigned long long buf_size,
bool shallow)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
int qemuMonitorJSONDrivePivot(qemuMonitor *mon,
const char *jobname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockCommit(qemuMonitor *mon,
const char *device,
const char *jobname,
bool persistjob,
const char *top,
const char *topNode,
const char *base,
const char *baseNode,
const char *backingName,
unsigned long long bandwidth)
blockjob: allow omitted arguments to QMP block-commit We are about to turn on support for active block commit. Although qemu 2.0 was the first version to mostly support it, that version mis-handles 0-length files, and doesn't have anything available for easy probing. But qemu 2.1 fixed bugs, and made life simpler by letting the 'top' argument be optional. Unless someone begs for active commit with qemu 2.0, for now we are just going to enable it only by probing for qemu 2.1 behavior (anyone backporting active commit can also backport the optional argument behavior). This requires qemu.git commit 7676e2c597000eff3a7233b40cca768b358f9bc9. Although all our actual uses of block-commit supply arguments for both base and top, we can omit both arguments and use a bogus device string to trigger an interesting behavior in qemu. All QMP commands first do argument validation, failing with GenericError if a mandatory argument is missing. Once that passes, the code in the specific command gets to do further checking, and the qemu developers made sure that if device is the only supplied argument, then the block-commit code will look up the device first, with a failure of DeviceNotFound, before attempting any further argument validation (most other validations fail with GenericError). Thus, the category of error class can reliably be used to decipher whether the top argument was optional, which in turn implies a working active commit. Since we expect our bogus device string to trigger an error either way, the code is written to return a distinct return value without spamming the logs. * src/qemu/qemu_monitor.h (qemuMonitorSupportsActiveCommit): New prototype. * src/qemu/qemu_monitor.c (qemuMonitorSupportsActiveCommit): Implement it. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit): Allow NULL for top and base, for probing purposes. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit): Likewise, implementing the probe. * tests/qemumonitorjsontest.c (mymain): Enable... (testQemuMonitorJSONqemuMonitorSupportsActiveCommit): ...a new test. Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-17 03:42:49 +00:00
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
char *qemuMonitorJSONDiskNameLookup(qemuMonitor *mon,
qemu: read backing chain names from qemu https://bugzilla.redhat.com/show_bug.cgi?id=1199182 documents that after a series of disk snapshots into existing destination images, followed by active commits of the top image, it is possible for qemu 2.2 and earlier to end up tracking a different name for the image than what it would have had when opening the chain afresh. That is, when starting with the chain 'a <- b <- c', the name associated with 'b' is how it was spelled in the metadata of 'c', but when starting with 'a', taking two snapshots into 'a <- b <- c', then committing 'c' back into 'b', the name associated with 'b' is now the name used when taking the first snapshot. Sadly, older qemu doesn't know how to treat different spellings of the same filename as identical files (it uses strcmp() instead of checking for the same inode), which means libvirt's attempt to commit an image using solely the names learned from qcow2 metadata fails with a cryptic: error: internal error: unable to execute QEMU command 'block-commit': Top image file /tmp/images/c/../b/b not found even though the file exists. Trying to teach libvirt the rules on which name qemu will expect is not worth the effort (besides, we'd have to remember it across libvirtd restarts, and track whether a file was opened via metadata or via snapshot creation for a given qemu process); it is easier to just always directly ask qemu what string it expects to see in the first place. As a safety valve, we validate that any name returned by qemu still maps to the same local file as we have tracked it, so that a compromised qemu cannot accidentally cause us to act on an incorrect file. * src/qemu/qemu_monitor.h (qemuMonitorDiskNameLookup): New prototype. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDiskNameLookup): Likewise. * src/qemu/qemu_monitor.c (qemuMonitorDiskNameLookup): New function. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONDiskNameLookup) (qemuMonitorJSONDiskNameLookupOne): Likewise. * src/qemu/qemu_driver.c (qemuDomainBlockCommit) (qemuDomainBlockJobImpl): Use it. Signed-off-by: Eric Blake <eblake@redhat.com>
2015-03-11 20:37:04 +00:00
const char *device,
virStorageSource *top,
virStorageSource *target)
qemu: read backing chain names from qemu https://bugzilla.redhat.com/show_bug.cgi?id=1199182 documents that after a series of disk snapshots into existing destination images, followed by active commits of the top image, it is possible for qemu 2.2 and earlier to end up tracking a different name for the image than what it would have had when opening the chain afresh. That is, when starting with the chain 'a <- b <- c', the name associated with 'b' is how it was spelled in the metadata of 'c', but when starting with 'a', taking two snapshots into 'a <- b <- c', then committing 'c' back into 'b', the name associated with 'b' is now the name used when taking the first snapshot. Sadly, older qemu doesn't know how to treat different spellings of the same filename as identical files (it uses strcmp() instead of checking for the same inode), which means libvirt's attempt to commit an image using solely the names learned from qcow2 metadata fails with a cryptic: error: internal error: unable to execute QEMU command 'block-commit': Top image file /tmp/images/c/../b/b not found even though the file exists. Trying to teach libvirt the rules on which name qemu will expect is not worth the effort (besides, we'd have to remember it across libvirtd restarts, and track whether a file was opened via metadata or via snapshot creation for a given qemu process); it is easier to just always directly ask qemu what string it expects to see in the first place. As a safety valve, we validate that any name returned by qemu still maps to the same local file as we have tracked it, so that a compromised qemu cannot accidentally cause us to act on an incorrect file. * src/qemu/qemu_monitor.h (qemuMonitorDiskNameLookup): New prototype. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDiskNameLookup): Likewise. * src/qemu/qemu_monitor.c (qemuMonitorDiskNameLookup): New function. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONDiskNameLookup) (qemuMonitorJSONDiskNameLookupOne): Likewise. * src/qemu/qemu_driver.c (qemuDomainBlockCommit) (qemuDomainBlockJobImpl): Use it. Signed-off-by: Eric Blake <eblake@redhat.com>
2015-03-11 20:37:04 +00:00
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_NONNULL(4);
int qemuMonitorJSONArbitraryCommand(qemuMonitor *mon,
const char *cmd_str,
char **reply_str);
int qemuMonitorJSONInjectNMI(qemuMonitor *mon);
int qemuMonitorJSONSendKey(qemuMonitor *mon,
unsigned int holdtime,
unsigned int *keycodes,
unsigned int nkeycodes);
int qemuMonitorJSONScreendump(qemuMonitor *mon,
const char *device,
unsigned int head,
const char *file);
int qemuMonitorJSONBlockStream(qemuMonitor *mon,
const char *device,
const char *jobname,
bool persistjob,
const char *base,
const char *baseNode,
const char *backingName,
unsigned long long speed)
blockjob: add qemu capabilities related to block pull jobs RHEL 6.2 was released with an early version of block jobs, which only worked on the qed file format, where the commands were spelled with underscore (contrary to QMP style), and where 'block_job_cancel' was synchronous and did not trigger an event. The upcoming qemu 1.1 release has fixed these short-comings [1][2]: the commands now work on multiple file types, are spelled with dash, and 'block-job-cancel' is asynchronous and emits an event upon conclusion. [1]qemu commit 370521a1d6f5537ea7271c119f3fbb7b0fa57063 [2]https://lists.gnu.org/archive/html/qemu-devel/2012-04/msg01248.html This patch recognizes the new spellings, and fixes virDomainBlockRebase to give a graceful error when talking to a too-old qemu on a partial rebase attempt. Fixes for the new semantics will come later. This patch also removes a bogus ATTRIBUTE_NONNULL mistakenly added in commit 10ec36e2. * src/qemu/qemu_capabilities.h (QEMU_CAPS_BLOCKJOB_SYNC) (QEMU_CAPS_BLOCKJOB_ASYNC): New bits. * src/qemu/qemu_capabilities.c (qemuCaps): Name them. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set them. (qemuMonitorJSONBlockJob): Manage both command names. (qemuMonitorJSONDiskSnapshot): Minor formatting fix. * src/qemu/qemu_monitor.h (qemuMonitorBlockJob): Alter signature. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockJob): Likewise. * src/qemu/qemu_monitor.c (qemuMonitorBlockJob): Pass through capability bit. * src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Update callers.
2012-04-11 21:40:16 +00:00
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockJobCancel(qemuMonitor *mon,
const char *jobname,
bool force)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int
qemuMonitorJSONGetJobInfo(qemuMonitor *mon,
qemuMonitorJobInfo ***jobs,
size_t *njobs);
int qemuMonitorJSONBlockJobSetSpeed(qemuMonitor *mon,
const char *jobname,
unsigned long long speed)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
GHashTable *qemuMonitorJSONGetAllBlockJobInfo(qemuMonitor *mon,
bool rawjobname)
ATTRIBUTE_NONNULL(1);
int qemuMonitorJSONJobDismiss(qemuMonitor *mon,
const char *jobname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONJobComplete(qemuMonitor *mon,
const char *jobname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONSetLink(qemuMonitor *mon,
const char *name,
virDomainNetInterfaceLinkState state);
int qemuMonitorJSONOpenGraphics(qemuMonitor *mon,
const char *protocol,
const char *fdname,
bool skipauth);
int qemuMonitorJSONSetBlockIoThrottle(qemuMonitor *mon,
const char *drivealias,
const char *qomid,
virDomainBlockIoTuneInfo *info);
int qemuMonitorJSONGetBlockIoThrottle(qemuMonitor *mon,
const char *drivealias,
const char *qdevid,
virDomainBlockIoTuneInfo *reply);
int qemuMonitorJSONSystemWakeup(qemuMonitor *mon);
char *qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon);
int qemuMonitorJSONGetVersion(qemuMonitor *mon,
int *major,
int *minor,
int *micro,
char **package)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
int qemuMonitorJSONGetMachines(qemuMonitor *mon,
qemuMonitorMachineInfo ***machines)
ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetCPUDefinitions(qemuMonitor *mon,
qemuMonitorCPUDefs **cpuDefs)
ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetCPUModelExpansion(qemuMonitor *mon,
qemuMonitorCPUModelExpansionType type,
virCPUDef *cpu,
bool migratable,
bool fail_no_props,
qemuMonitorCPUModelInfo **model_info)
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6);
int qemuMonitorJSONGetCPUModelBaseline(qemuMonitor *mon,
virCPUDef *cpu_a,
virCPUDef *cpu_b,
qemuMonitorCPUModelInfo **baseline)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
int qemuMonitorJSONGetCPUModelComparison(qemuMonitor *mon,
virCPUDef *cpu_a,
virCPUDef *cpu_b,
char **result)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorJSONGetCommands(qemuMonitor *mon,
char ***commands)
ATTRIBUTE_NONNULL(2);
GHashTable *qemuMonitorJSONGetCommandLineOptions(qemuMonitor *mon);
int qemuMonitorJSONGetKVMState(qemuMonitor *mon,
bool *enabled,
bool *present)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorJSONGetObjectTypes(qemuMonitor *mon,
char ***types)
ATTRIBUTE_NONNULL(2);
/* ListPath structures and API's are public only for qemumonitorjsontest */
typedef struct _qemuMonitorJSONListPath qemuMonitorJSONListPath;
struct _qemuMonitorJSONListPath {
char *name;
char *type;
};
int qemuMonitorJSONGetObjectListPaths(qemuMonitor *mon,
const char *path,
qemuMonitorJSONListPath ***paths)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
void qemuMonitorJSONListPathFree(qemuMonitorJSONListPath *paths);
/* ObjectProperty structures and Get/Set API's are public only
* for qemumonitorjsontest
*/
/* Flags for the 'type' field in _qemuMonitorJSONObjectProperty */
typedef enum {
QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN=1,
QEMU_MONITOR_OBJECT_PROPERTY_INT,
QEMU_MONITOR_OBJECT_PROPERTY_LONG,
QEMU_MONITOR_OBJECT_PROPERTY_UINT,
QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE,
QEMU_MONITOR_OBJECT_PROPERTY_STRING,
QEMU_MONITOR_OBJECT_PROPERTY_LAST
} qemuMonitorJSONObjectPropertyType;
typedef struct _qemuMonitorJSONObjectProperty qemuMonitorJSONObjectProperty;
struct _qemuMonitorJSONObjectProperty {
int type; /* qemuMonitorJSONObjectPropertyType */
union {
bool b;
int iv;
long long l;
unsigned int ui;
unsigned long long ul;
double d;
char *str;
} val;
};
int qemuMonitorJSONGetObjectProperty(qemuMonitor *mon,
const char *path,
const char *property,
qemuMonitorJSONObjectProperty *prop)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
int qemuMonitorJSONSetObjectProperty(qemuMonitor *mon,
const char *path,
const char *property,
qemuMonitorJSONObjectProperty *prop)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
GHashTable *qemuMonitorJSONGetDeviceProps(qemuMonitor *mon,
const char *device)
ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetObjectProps(qemuMonitor *mon,
const char *object,
char ***props)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
char *qemuMonitorJSONGetTargetArch(qemuMonitor *mon);
int qemuMonitorJSONNBDServerStart(qemuMonitor *mon,
const virStorageNetHostDef *server,
const char *tls_alias);
int qemuMonitorJSONNBDServerAdd(qemuMonitor *mon,
const char *deviceID,
const char *export,
bool writable,
const char *bitmap);
int qemuMonitorJSONNBDServerStop(qemuMonitor *mon);
int qemuMonitorJSONBlockExportAdd(qemuMonitor *mon,
virJSONValue **props);
int qemuMonitorJSONGetTPMModels(qemuMonitor *mon,
char ***tpmmodels)
ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetTPMTypes(qemuMonitor *mon,
char ***tpmtypes)
ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONAttachCharDev(qemuMonitor *mon,
const char *chrID,
virDomainChrSourceDef *chr);
int qemuMonitorJSONDetachCharDev(qemuMonitor *mon,
const char *chrID);
int qemuMonitorJSONGetDeviceAliases(qemuMonitor *mon,
char ***aliases);
int qemuMonitorJSONGetCPUx86Data(qemuMonitor *mon,
const char *property,
virCPUData **cpudata);
int qemuMonitorJSONGetGuestCPUx86(qemuMonitor *mon,
virCPUData **data,
virCPUData **disabled);
int qemuMonitorJSONGetGuestCPU(qemuMonitor *mon,
virArch arch,
qemuMonitorCPUFeatureTranslationCallback translate,
void *opaque,
virCPUData **enabled,
virCPUData **disabled);
int qemuMonitorJSONRTCResetReinjection(qemuMonitor *mon);
int qemuMonitorJSONGetIOThreads(qemuMonitor *mon,
qemuMonitorIOThreadInfo ***iothreads,
int *niothreads)
ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONSetIOThread(qemuMonitor *mon,
qemuMonitorIOThreadInfo *iothreadInfo)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitor *mon,
GHashTable *info)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONFindLinkPath(qemuMonitor *mon,
const char *name,
const char *alias,
char **path)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
int qemuMonitorJSONMigrateIncoming(qemuMonitor *mon,
const char *uri)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONMigrateStartPostCopy(qemuMonitor *mon)
ATTRIBUTE_NONNULL(1);
int qemuMonitorJSONMigrateContinue(qemuMonitor *mon,
qemuMonitorMigrationStatus status)
ATTRIBUTE_NONNULL(1);
int qemuMonitorJSONGetRTCTime(qemuMonitor *mon,
struct tm *tm)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONGetHotpluggableCPUs(qemuMonitor *mon,
struct qemuMonitorQueryHotpluggableCpusEntry **entries,
size_t *nentries)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
virJSONValue *qemuMonitorJSONQueryQMPSchema(qemuMonitor *mon)
ATTRIBUTE_NONNULL(1);
int qemuMonitorJSONSetBlockThreshold(qemuMonitor *mon,
const char *nodename,
unsigned long long threshold)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
virJSONValue *qemuMonitorJSONQueryNamedBlockNodes(qemuMonitor *mon,
bool flat)
ATTRIBUTE_NONNULL(1);
int qemuMonitorJSONSetWatchdogAction(qemuMonitor *mon,
const char *action)
ATTRIBUTE_NONNULL(1);
int qemuMonitorJSONBlockdevCreate(qemuMonitor *mon,
const char *jobname,
virJSONValue *props)
ATTRIBUTE_NONNULL(1);
int qemuMonitorJSONBlockdevAdd(qemuMonitor *mon,
virJSONValue **props)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockdevReopen(qemuMonitor *mon,
virJSONValue **props)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockdevDel(qemuMonitor *mon,
const char *nodename)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockdevTrayOpen(qemuMonitor *mon,
const char *id,
bool force)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockdevTrayClose(qemuMonitor *mon,
const char *id)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockdevMediumRemove(qemuMonitor *mon,
const char *id)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockdevMediumInsert(qemuMonitor *mon,
const char *id,
const char *nodename)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorJSONGetPRManagerInfo(qemuMonitor *mon,
GHashTable *info)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int
qemuMonitorJSONGetCurrentMachineInfo(qemuMonitor *mon,
qemuMonitorCurrentMachineInfo *info)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int
qemuMonitorJSONTransactionBitmapAdd(virJSONValue *actions,
const char *node,
const char *name,
bool persistent,
bool disabled,
unsigned long long granularity);
int
qemuMonitorJSONTransactionBitmapRemove(virJSONValue *actions,
const char *node,
const char *name);
int
qemuMonitorJSONBitmapRemove(qemuMonitor *mon,
const char *node,
const char *name);
int
qemuMonitorJSONTransactionBitmapEnable(virJSONValue *actions,
const char *node,
const char *name);
int
qemuMonitorJSONTransactionBitmapDisable(virJSONValue *actions,
const char *node,
const char *name);
int
qemuMonitorJSONTransactionBitmapMerge(virJSONValue *actions,
const char *node,
const char *target,
virJSONValue **sources);
int
qemuMonitorJSONTransactionBitmapMergeSourceAddBitmap(virJSONValue *sources,
const char *sourcenode,
const char *sourcebitmap);
int
qemuMonitorJSONTransactionSnapshotLegacy(virJSONValue *actions,
const char *device,
const char *path,
const char *format,
bool existing);
int
qemuMonitorJSONTransactionSnapshotBlockdev(virJSONValue *actions,
const char *node,
const char *overlay);
int
qemuMonitorJSONTransactionBackup(virJSONValue *actions,
const char *device,
const char *jobname,
const char *target,
const char *bitmap,
qemuMonitorTransactionBackupSyncMode syncmode);
int qemuMonitorJSONSetDBusVMStateIdList(qemuMonitor *mon,
const char *vmstatepath,
const char *idstr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int
qemuMonitorJSONGetCPUMigratable(qemuMonitor *mon,
bool *migratable);
int
qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon,
int seconds);
int
qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon,
qemuMonitorDirtyRateInfo *info);