libvirt/src/qemu/qemu_monitor.c
Daniel P. Berrange 5d72a89442 Run 'qmp_capabilities' command at QEMU monitor startup
When in JSON mode, QEMU requires that 'qmp_capabilities' is run as
the first command in the monitor. This is a no-op when run in the
text mode monitor

* src/qemu/qemu_driver.c: Run capabilities negotiation when
  connecting to the monitor
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
  src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h: Add
  support for the 'qmp_capabilities' command, no-op in text mode.
2010-02-16 14:21:25 +00:00

1362 lines
35 KiB
C

/*
* qemu_monitor.c: interaction with QEMU monitor console
*
* Copyright (C) 2006-2009 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <poll.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include "qemu_monitor.h"
#include "qemu_monitor_text.h"
#include "qemu_monitor_json.h"
#include "qemu_conf.h"
#include "event.h"
#include "virterror_internal.h"
#include "memory.h"
#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
#define QEMU_DEBUG_RAW_IO 0
struct _qemuMonitor {
virMutex lock;
virCond notify;
int refs;
int fd;
int watch;
int hasSendFD;
virDomainObjPtr vm;
qemuMonitorCallbacksPtr cb;
/* If there's a command being processed this will be
* non-NULL */
qemuMonitorMessagePtr msg;
/* Buffer incoming data ready for Text/QMP monitor
* code to process & find message boundaries */
size_t bufferOffset;
size_t bufferLength;
char *buffer;
/* If anything went wrong, this will be fed back
* the next monitor msg */
int lastErrno;
/* If the monitor EOF callback is currently active (stops more commands being run) */
unsigned eofcb: 1;
/* If the monitor is in process of shutting down */
unsigned closed: 1;
unsigned json: 1;
};
VIR_ENUM_IMPL(qemuMonitorMigrationStatus,
QEMU_MONITOR_MIGRATION_STATUS_LAST,
"inactive", "active", "completed", "failed", "cancelled")
static char *qemuMonitorEscape(const char *in, int shell)
{
int len = 0;
int i, j;
char *out;
/* To pass through the QEMU monitor, we need to use escape
sequences: \r, \n, \", \\
To pass through both QEMU + the shell, we need to escape
the single character ' as the five characters '\\''
*/
for (i = 0; in[i] != '\0'; i++) {
switch(in[i]) {
case '\r':
case '\n':
case '"':
case '\\':
len += 2;
break;
case '\'':
if (shell)
len += 5;
else
len += 1;
break;
default:
len += 1;
break;
}
}
if (VIR_ALLOC_N(out, len + 1) < 0)
return NULL;
for (i = j = 0; in[i] != '\0'; i++) {
switch(in[i]) {
case '\r':
out[j++] = '\\';
out[j++] = 'r';
break;
case '\n':
out[j++] = '\\';
out[j++] = 'n';
break;
case '"':
case '\\':
out[j++] = '\\';
out[j++] = in[i];
break;
case '\'':
if (shell) {
out[j++] = '\'';
out[j++] = '\\';
out[j++] = '\\';
out[j++] = '\'';
out[j++] = '\'';
} else {
out[j++] = in[i];
}
break;
default:
out[j++] = in[i];
break;
}
}
out[j] = '\0';
return out;
}
char *qemuMonitorEscapeArg(const char *in)
{
return qemuMonitorEscape(in, 0);
}
char *qemuMonitorEscapeShell(const char *in)
{
return qemuMonitorEscape(in, 1);
}
#if QEMU_DEBUG_RAW_IO
#include <c-ctype.h>
static char * qemuMonitorEscapeNonPrintable(const char *text)
{
int i;
virBuffer buf = VIR_BUFFER_INITIALIZER;
for (i = 0 ; text[i] != '\0' ; i++) {
if (c_isprint(text[i]) ||
text[i] == '\n' ||
(text[i] == '\r' && text[i+1] == '\n'))
virBufferVSprintf(&buf,"%c", text[i]);
else
virBufferVSprintf(&buf, "0x%02x", text[i]);
}
return virBufferContentAndReset(&buf);
}
#endif
void qemuMonitorLock(qemuMonitorPtr mon)
{
virMutexLock(&mon->lock);
}
void qemuMonitorUnlock(qemuMonitorPtr mon)
{
virMutexUnlock(&mon->lock);
}
static void qemuMonitorFree(qemuMonitorPtr mon)
{
VIR_DEBUG("mon=%p", mon);
if (virCondDestroy(&mon->notify) < 0)
{}
virMutexDestroy(&mon->lock);
VIR_FREE(mon);
}
int qemuMonitorRef(qemuMonitorPtr mon)
{
mon->refs++;
return mon->refs;
}
int qemuMonitorUnref(qemuMonitorPtr mon)
{
mon->refs--;
if (mon->refs == 0) {
qemuMonitorUnlock(mon);
qemuMonitorFree(mon);
return 0;
}
return mon->refs;
}
static int
qemuMonitorOpenUnix(const char *monitor)
{
struct sockaddr_un addr;
int monfd;
int timeout = 3; /* In seconds */
int ret, i = 0;
if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
virReportSystemError(errno,
"%s", _("failed to create socket"));
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
if (virStrcpyStatic(addr.sun_path, monitor) == NULL) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("Monitor path %s too big for destination"), monitor);
goto error;
}
do {
ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret == 0)
break;
if (errno == ENOENT || errno == ECONNREFUSED) {
/* ENOENT : Socket may not have shown up yet
* ECONNREFUSED : Leftover socket hasn't been removed yet */
continue;
}
virReportSystemError(errno, "%s",
_("failed to connect to monitor socket"));
goto error;
} while ((++i <= timeout*5) && (usleep(.2 * 1000000) <= 0));
if (ret != 0) {
virReportSystemError(errno, "%s",
_("monitor socket did not show up."));
goto error;
}
return monfd;
error:
close(monfd);
return -1;
}
static int
qemuMonitorOpenPty(const char *monitor)
{
int monfd;
if ((monfd = open(monitor, O_RDWR)) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to open monitor path %s"), monitor);
return -1;
}
return monfd;
}
static int
qemuMonitorIOProcess(qemuMonitorPtr mon)
{
int len;
qemuMonitorMessagePtr msg = NULL;
/* See if there's a message & whether its ready for its reply
* ie whether its completed writing all its data */
if (mon->msg && mon->msg->txOffset == mon->msg->txLength)
msg = mon->msg;
#if QEMU_DEBUG_RAW_IO
char *str1 = qemuMonitorEscapeNonPrintable(msg ? msg->txBuffer : "");
char *str2 = qemuMonitorEscapeNonPrintable(mon->buffer);
VIR_ERROR("Process %d %p %p [[[[%s]]][[[%s]]]", (int)mon->bufferOffset, mon->msg, msg, str1, str2);
VIR_FREE(str1);
VIR_FREE(str2);
#else
VIR_DEBUG("Process %d", (int)mon->bufferOffset);
#endif
if (mon->json)
len = qemuMonitorJSONIOProcess(mon,
mon->buffer, mon->bufferOffset,
msg);
else
len = qemuMonitorTextIOProcess(mon,
mon->buffer, mon->bufferOffset,
msg);
if (len < 0) {
mon->lastErrno = errno;
return -1;
}
if (len < mon->bufferOffset) {
memmove(mon->buffer, mon->buffer + len, mon->bufferOffset - len);
mon->bufferOffset -= len;
} else {
VIR_FREE(mon->buffer);
mon->bufferOffset = mon->bufferLength = 0;
}
VIR_DEBUG("Process done %d used %d", (int)mon->bufferOffset, len);
if (msg && msg->finished)
virCondBroadcast(&mon->notify);
return len;
}
static int
qemuMonitorIOWriteWithFD(qemuMonitorPtr mon,
const char *data,
size_t len,
int fd)
{
struct msghdr msg;
struct iovec iov[1];
int ret;
char control[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmsg;
if (!mon->hasSendFD) {
errno = EINVAL;
return -1;
}
memset(&msg, 0, sizeof(msg));
iov[0].iov_base = (void *)data;
iov[0].iov_len = len;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = control;
msg.msg_controllen = sizeof(control);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
do {
ret = sendmsg(mon->fd, &msg, 0);
} while (ret < 0 && errno == EINTR);
return ret;
}
/* Called when the monitor is able to write data */
static int
qemuMonitorIOWrite(qemuMonitorPtr mon)
{
int done;
/* If no active message, or fully transmitted, the no-op */
if (!mon->msg || mon->msg->txOffset == mon->msg->txLength)
return 0;
if (mon->msg->txFD == -1)
done = write(mon->fd,
mon->msg->txBuffer + mon->msg->txOffset,
mon->msg->txLength - mon->msg->txOffset);
else
done = qemuMonitorIOWriteWithFD(mon,
mon->msg->txBuffer + mon->msg->txOffset,
mon->msg->txLength - mon->msg->txOffset,
mon->msg->txFD);
if (done < 0) {
if (errno == EAGAIN)
return 0;
mon->lastErrno = errno;
return -1;
}
mon->msg->txOffset += done;
return done;
}
/*
* Called when the monitor has incoming data to read
*
* Returns -1 on error, or number of bytes read
*/
static int
qemuMonitorIORead(qemuMonitorPtr mon)
{
size_t avail = mon->bufferLength - mon->bufferOffset;
int ret = 0;
if (avail < 1024) {
if (VIR_REALLOC_N(mon->buffer,
mon->bufferLength + 1024) < 0) {
errno = ENOMEM;
return -1;
}
mon->bufferLength += 1024;
avail += 1024;
}
/* Read as much as we can get into our buffer,
until we block on EAGAIN, or hit EOF */
while (avail > 1) {
int got;
got = read(mon->fd,
mon->buffer + mon->bufferOffset,
avail - 1);
if (got < 0) {
if (errno == EAGAIN)
break;
mon->lastErrno = errno;
ret = -1;
break;
}
if (got == 0)
break;
ret += got;
avail -= got;
mon->bufferOffset += got;
mon->buffer[mon->bufferOffset] = '\0';
}
VIR_DEBUG("Now read %d bytes of data", (int)mon->bufferOffset);
return ret;
}
static void qemuMonitorUpdateWatch(qemuMonitorPtr mon)
{
int events =
VIR_EVENT_HANDLE_HANGUP |
VIR_EVENT_HANDLE_ERROR;
if (!mon->lastErrno) {
events |= VIR_EVENT_HANDLE_READABLE;
if (mon->msg && mon->msg->txOffset < mon->msg->txLength)
events |= VIR_EVENT_HANDLE_WRITABLE;
}
virEventUpdateHandle(mon->watch, events);
}
static void
qemuMonitorIO(int watch, int fd, int events, void *opaque) {
qemuMonitorPtr mon = opaque;
int quit = 0, failed = 0;
qemuMonitorLock(mon);
qemuMonitorRef(mon);
VIR_DEBUG("Monitor %p I/O on watch %d fd %d events %d", mon, watch, fd, events);
if (mon->fd != fd || mon->watch != watch) {
VIR_ERROR("event from unexpected fd %d!=%d / watch %d!=%d", mon->fd, fd, mon->watch, watch);
failed = 1;
} else {
if (!mon->lastErrno &&
events & VIR_EVENT_HANDLE_WRITABLE) {
int done = qemuMonitorIOWrite(mon);
if (done < 0)
failed = 1;
events &= ~VIR_EVENT_HANDLE_WRITABLE;
}
if (!mon->lastErrno &&
events & VIR_EVENT_HANDLE_READABLE) {
int got = qemuMonitorIORead(mon);
if (got < 0)
failed = 1;
/* Ignore hangup/error events if we read some data, to
* give time for that data to be consumed */
if (got > 0) {
events = 0;
if (qemuMonitorIOProcess(mon) < 0)
failed = 1;
} else
events &= ~VIR_EVENT_HANDLE_READABLE;
}
/* If IO process resulted in an error & we have a message,
* then wakeup that waiter */
if (mon->lastErrno && mon->msg && !mon->msg->finished) {
mon->msg->lastErrno = mon->lastErrno;
mon->msg->finished = 1;
virCondSignal(&mon->notify);
}
qemuMonitorUpdateWatch(mon);
if (events & VIR_EVENT_HANDLE_HANGUP) {
/* If IO process resulted in EOF & we have a message,
* then wakeup that waiter */
if (mon->msg && !mon->msg->finished) {
mon->msg->finished = 1;
mon->msg->lastErrno = EIO;
virCondSignal(&mon->notify);
}
quit = 1;
} else if (events) {
VIR_ERROR(_("unhandled fd event %d for monitor fd %d"),
events, mon->fd);
failed = 1;
}
}
/* We have to unlock to avoid deadlock against command thread,
* but is this safe ? I think it is, because the callback
* will try to acquire the virDomainObjPtr mutex next */
if (failed || quit) {
void (*eofNotify)(qemuMonitorPtr, virDomainObjPtr, int)
= mon->cb->eofNotify;
virDomainObjPtr vm = mon->vm;
/* Make sure anyone waiting wakes up now */
virCondSignal(&mon->notify);
if (qemuMonitorUnref(mon) > 0)
qemuMonitorUnlock(mon);
VIR_DEBUG("Triggering EOF callback error? %d", failed);
(eofNotify)(mon, vm, failed);
} else {
if (qemuMonitorUnref(mon) > 0)
qemuMonitorUnlock(mon);
}
}
qemuMonitorPtr
qemuMonitorOpen(virDomainObjPtr vm,
virDomainChrDefPtr config,
int json,
qemuMonitorCallbacksPtr cb)
{
qemuMonitorPtr mon;
if (!cb || !cb->eofNotify) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("EOF notify callback must be supplied"));
return NULL;
}
if (VIR_ALLOC(mon) < 0) {
virReportOOMError();
return NULL;
}
if (virMutexInit(&mon->lock) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot initialize monitor mutex"));
VIR_FREE(mon);
return NULL;
}
if (virCondInit(&mon->notify) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot initialize monitor condition"));
virMutexDestroy(&mon->lock);
VIR_FREE(mon);
return NULL;
}
mon->fd = -1;
mon->refs = 1;
mon->vm = vm;
mon->json = json;
mon->cb = cb;
qemuMonitorLock(mon);
switch (config->type) {
case VIR_DOMAIN_CHR_TYPE_UNIX:
mon->hasSendFD = 1;
mon->fd = qemuMonitorOpenUnix(config->data.nix.path);
break;
case VIR_DOMAIN_CHR_TYPE_PTY:
mon->fd = qemuMonitorOpenPty(config->data.file.path);
break;
default:
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("unable to handle monitor type: %s"),
virDomainChrTypeToString(config->type));
goto cleanup;
}
if (mon->fd == -1) goto cleanup;
if (virSetCloseExec(mon->fd) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Unable to set monitor close-on-exec flag"));
goto cleanup;
}
if (virSetNonBlock(mon->fd) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Unable to put monitor into non-blocking mode"));
goto cleanup;
}
if ((mon->watch = virEventAddHandle(mon->fd,
VIR_EVENT_HANDLE_HANGUP |
VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_READABLE,
qemuMonitorIO,
mon, NULL)) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unable to register monitor events"));
goto cleanup;
}
VIR_DEBUG("New mon %p fd =%d watch=%d", mon, mon->fd, mon->watch);
qemuMonitorUnlock(mon);
return mon;
cleanup:
qemuMonitorUnlock(mon);
qemuMonitorClose(mon);
return NULL;
}
int qemuMonitorClose(qemuMonitorPtr mon)
{
int refs;
if (!mon)
return 0;
VIR_DEBUG("mon=%p", mon);
qemuMonitorLock(mon);
if (!mon->closed) {
if (mon->watch)
virEventRemoveHandle(mon->watch);
if (mon->fd != -1)
close(mon->fd);
/* NB: ordinarily one might immediately set mon->watch to -1
* and mon->fd to -1, but there may be a callback active
* that is still relying on these fields being valid. So
* we merely close them, but not clear their values and
* use this explicit 'closed' flag to track this state */
mon->closed = 1;
}
if ((refs = qemuMonitorUnref(mon)) > 0)
qemuMonitorUnlock(mon);
return refs;
}
int qemuMonitorSend(qemuMonitorPtr mon,
qemuMonitorMessagePtr msg)
{
int ret = -1;
if (mon->eofcb) {
msg->lastErrno = EIO;
return -1;
}
mon->msg = msg;
qemuMonitorUpdateWatch(mon);
while (!mon->msg->finished) {
if (virCondWait(&mon->notify, &mon->lock) < 0)
goto cleanup;
}
if (mon->lastErrno == 0)
ret = 0;
cleanup:
mon->msg = NULL;
qemuMonitorUpdateWatch(mon);
return ret;
}
int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
virConnectPtr conn,
const char *path,
char **secret,
size_t *secretLen)
{
int ret = -1;
*secret = NULL;
*secretLen = 0;
qemuMonitorRef(mon);
qemuMonitorUnlock(mon);
if (mon->cb && mon->cb->diskSecretLookup)
ret = mon->cb->diskSecretLookup(mon, conn, mon->vm, path, secret, secretLen);
qemuMonitorLock(mon);
qemuMonitorUnref(mon);
return ret;
}
int qemuMonitorEmitShutdown(qemuMonitorPtr mon)
{
int ret = -1;
VIR_DEBUG("mon=%p", mon);
qemuMonitorRef(mon);
qemuMonitorUnlock(mon);
if (mon->cb && mon->cb->domainShutdown)
ret = mon->cb->domainShutdown(mon, mon->vm);
qemuMonitorLock(mon);
qemuMonitorUnref(mon);
return ret;
}
int qemuMonitorEmitReset(qemuMonitorPtr mon)
{
int ret = -1;
VIR_DEBUG("mon=%p", mon);
qemuMonitorRef(mon);
qemuMonitorUnlock(mon);
if (mon->cb && mon->cb->domainReset)
ret = mon->cb->domainReset(mon, mon->vm);
qemuMonitorLock(mon);
qemuMonitorUnref(mon);
return ret;
}
int qemuMonitorEmitPowerdown(qemuMonitorPtr mon)
{
int ret = -1;
VIR_DEBUG("mon=%p", mon);
qemuMonitorRef(mon);
qemuMonitorUnlock(mon);
if (mon->cb && mon->cb->domainPowerdown)
ret = mon->cb->domainPowerdown(mon, mon->vm);
qemuMonitorLock(mon);
qemuMonitorUnref(mon);
return ret;
}
int qemuMonitorEmitStop(qemuMonitorPtr mon)
{
int ret = -1;
VIR_DEBUG("mon=%p", mon);
qemuMonitorRef(mon);
qemuMonitorUnlock(mon);
if (mon->cb && mon->cb->domainStop)
ret = mon->cb->domainStop(mon, mon->vm);
qemuMonitorLock(mon);
qemuMonitorUnref(mon);
return ret;
}
int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONSetCapabilities(mon);
else
ret = 0;
return ret;
}
int
qemuMonitorStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONStartCPUs(mon, conn);
else
ret = qemuMonitorTextStartCPUs(mon, conn);
return ret;
}
int
qemuMonitorStopCPUs(qemuMonitorPtr mon)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONStopCPUs(mon);
else
ret = qemuMonitorTextStopCPUs(mon);
return ret;
}
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONSystemPowerdown(mon);
else
ret = qemuMonitorTextSystemPowerdown(mon);
return ret;
}
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
int **pids)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONGetCPUInfo(mon, pids);
else
ret = qemuMonitorTextGetCPUInfo(mon, pids);
return ret;
}
int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
unsigned long *currmem)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONGetBalloonInfo(mon, currmem);
else
ret = qemuMonitorTextGetBalloonInfo(mon, currmem);
return ret;
}
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
long long *rd_req,
long long *rd_bytes,
long long *wr_req,
long long *wr_bytes,
long long *errs)
{
int ret;
DEBUG("mon=%p, fd=%d dev=%s", mon, mon->fd, devname);
if (mon->json)
ret = qemuMonitorJSONGetBlockStatsInfo(mon, devname,
rd_req, rd_bytes,
wr_req, wr_bytes,
errs);
else
ret = qemuMonitorTextGetBlockStatsInfo(mon, devname,
rd_req, rd_bytes,
wr_req, wr_bytes,
errs);
return ret;
}
int qemuMonitorSetVNCPassword(qemuMonitorPtr mon,
const char *password)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONSetVNCPassword(mon, password);
else
ret = qemuMonitorTextSetVNCPassword(mon, password);
return ret;
}
int qemuMonitorSetBalloon(qemuMonitorPtr mon,
unsigned long newmem)
{
int ret;
DEBUG("mon=%p, fd=%d newmem=%lu", mon, mon->fd, newmem);
if (mon->json)
ret = qemuMonitorJSONSetBalloon(mon, newmem);
else
ret = qemuMonitorTextSetBalloon(mon, newmem);
return ret;
}
int qemuMonitorEjectMedia(qemuMonitorPtr mon,
const char *devname)
{
int ret;
DEBUG("mon=%p, fd=%d devname=%s", mon, mon->fd, devname);
if (mon->json)
ret = qemuMonitorJSONEjectMedia(mon, devname);
else
ret = qemuMonitorTextEjectMedia(mon, devname);
return ret;
}
int qemuMonitorChangeMedia(qemuMonitorPtr mon,
const char *devname,
const char *newmedia,
const char *format)
{
int ret;
DEBUG("mon=%p, fd=%d devname=%s newmedia=%s format=%s",
mon, mon->fd, devname, newmedia, format);
if (mon->json)
ret = qemuMonitorJSONChangeMedia(mon, devname, newmedia, format);
else
ret = qemuMonitorTextChangeMedia(mon, devname, newmedia, format);
return ret;
}
int qemuMonitorSaveVirtualMemory(qemuMonitorPtr mon,
unsigned long long offset,
size_t length,
const char *path)
{
int ret;
DEBUG("mon=%p, fd=%d offset=%llu length=%zu path=%s",
mon, mon->fd, offset, length, path);
if (mon->json)
ret = qemuMonitorJSONSaveVirtualMemory(mon, offset, length, path);
else
ret = qemuMonitorTextSaveVirtualMemory(mon, offset, length, path);
return ret;
}
int qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon,
unsigned long long offset,
size_t length,
const char *path)
{
int ret;
DEBUG("mon=%p, fd=%d offset=%llu length=%zu path=%s",
mon, mon->fd, offset, length, path);
if (mon->json)
ret = qemuMonitorJSONSavePhysicalMemory(mon, offset, length, path);
else
ret = qemuMonitorTextSavePhysicalMemory(mon, offset, length, path);
return ret;
}
int qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
unsigned long bandwidth)
{
int ret;
DEBUG("mon=%p, fd=%d bandwidth=%lu", mon, mon->fd, bandwidth);
if (mon->json)
ret = qemuMonitorJSONSetMigrationSpeed(mon, bandwidth);
else
ret = qemuMonitorTextSetMigrationSpeed(mon, bandwidth);
return ret;
}
int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
int *status,
unsigned long long *transferred,
unsigned long long *remaining,
unsigned long long *total)
{
int ret;
DEBUG("mon=%p, fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONGetMigrationStatus(mon, status,
transferred,
remaining,
total);
else
ret = qemuMonitorTextGetMigrationStatus(mon, status,
transferred,
remaining,
total);
return ret;
}
int qemuMonitorMigrateToHost(qemuMonitorPtr mon,
int background,
const char *hostname,
int port)
{
int ret;
DEBUG("mon=%p, fd=%d hostname=%s port=%d",
mon, mon->fd, hostname, port);
if (mon->json)
ret = qemuMonitorJSONMigrateToHost(mon, background, hostname, port);
else
ret = qemuMonitorTextMigrateToHost(mon, background, hostname, port);
return ret;
}
int qemuMonitorMigrateToCommand(qemuMonitorPtr mon,
int background,
const char * const *argv,
const char *target)
{
int ret;
DEBUG("mon=%p, fd=%d argv=%p target=%s",
mon, mon->fd, argv, target);
if (mon->json)
ret = qemuMonitorJSONMigrateToCommand(mon, background, argv, target);
else
ret = qemuMonitorTextMigrateToCommand(mon, background, argv, target);
return ret;
}
int qemuMonitorMigrateToUnix(qemuMonitorPtr mon,
int background,
const char *unixfile)
{
int ret;
DEBUG("mon=%p fd=%d unixfile=%s",
mon, mon->fd, unixfile);
if (mon->json)
ret = qemuMonitorJSONMigrateToUnix(mon, background, unixfile);
else
ret = qemuMonitorTextMigrateToUnix(mon, background, unixfile);
return ret;
}
int qemuMonitorMigrateCancel(qemuMonitorPtr mon)
{
int ret;
DEBUG("mon=%p fd=%d", mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONMigrateCancel(mon);
else
ret = qemuMonitorTextMigrateCancel(mon);
return ret;
}
int qemuMonitorAddUSBDisk(qemuMonitorPtr mon,
const char *path)
{
int ret;
DEBUG("mon=%p, fd=%d path=%s", mon, mon->fd, path);
if (mon->json)
ret = qemuMonitorJSONAddUSBDisk(mon, path);
else
ret = qemuMonitorTextAddUSBDisk(mon, path);
return ret;
}
int qemuMonitorAddUSBDeviceExact(qemuMonitorPtr mon,
int bus,
int dev)
{
int ret;
DEBUG("mon=%p, fd=%d bus=%d dev=%d", mon, mon->fd, bus, dev);
if (mon->json)
ret = qemuMonitorJSONAddUSBDeviceExact(mon, bus, dev);
else
ret = qemuMonitorTextAddUSBDeviceExact(mon, bus, dev);
return ret;
}
int qemuMonitorAddUSBDeviceMatch(qemuMonitorPtr mon,
int vendor,
int product)
{
int ret;
DEBUG("mon=%p, fd=%d vendor=%d product=%d",
mon, mon->fd, vendor, product);
if (mon->json)
ret = qemuMonitorJSONAddUSBDeviceMatch(mon, vendor, product);
else
ret = qemuMonitorTextAddUSBDeviceMatch(mon, vendor, product);
return ret;
}
int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon,
virDomainDevicePCIAddress *hostAddr,
virDomainDevicePCIAddress *guestAddr)
{
int ret;
DEBUG("mon=%p, fd=%d domain=%d bus=%d slot=%d function=%d",
mon, mon->fd,
hostAddr->domain, hostAddr->bus, hostAddr->slot, hostAddr->function);
if (mon->json)
ret = qemuMonitorJSONAddPCIHostDevice(mon, hostAddr, guestAddr);
else
ret = qemuMonitorTextAddPCIHostDevice(mon, hostAddr, guestAddr);
return ret;
}
int qemuMonitorAddPCIDisk(qemuMonitorPtr mon,
const char *path,
const char *bus,
virDomainDevicePCIAddress *guestAddr)
{
int ret;
DEBUG("mon=%p, fd=%d path=%s bus=%s",
mon, mon->fd, path, bus);
if (mon->json)
ret = qemuMonitorJSONAddPCIDisk(mon, path, bus, guestAddr);
else
ret = qemuMonitorTextAddPCIDisk(mon, path, bus, guestAddr);
return ret;
}
int qemuMonitorAddPCINetwork(qemuMonitorPtr mon,
const char *nicstr,
virDomainDevicePCIAddress *guestAddr)
{
int ret;
DEBUG("mon=%p, fd=%d nicstr=%s", mon, mon->fd, nicstr);
if (mon->json)
ret = qemuMonitorJSONAddPCINetwork(mon, nicstr, guestAddr);
else
ret = qemuMonitorTextAddPCINetwork(mon, nicstr, guestAddr);
return ret;
}
int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon,
virDomainDevicePCIAddress *guestAddr)
{
int ret;
DEBUG("mon=%p, fd=%d domain=%d bus=%d slot=%d function=%d",
mon, mon->fd, guestAddr->domain, guestAddr->bus,
guestAddr->slot, guestAddr->function);
if (mon->json)
ret = qemuMonitorJSONRemovePCIDevice(mon, guestAddr);
else
ret = qemuMonitorTextRemovePCIDevice(mon, guestAddr);
return ret;
}
int qemuMonitorSendFileHandle(qemuMonitorPtr mon,
const char *fdname,
int fd)
{
int ret;
DEBUG("mon=%p, fd=%d fdname=%s fd=%d",
mon, mon->fd, fdname, fd);
if (mon->json)
ret = qemuMonitorJSONSendFileHandle(mon, fdname, fd);
else
ret = qemuMonitorTextSendFileHandle(mon, fdname, fd);
return ret;
}
int qemuMonitorCloseFileHandle(qemuMonitorPtr mon,
const char *fdname)
{
int ret;
DEBUG("mon=%p, fd=%d fdname=%s",
mon, mon->fd, fdname);
if (mon->json)
ret = qemuMonitorJSONCloseFileHandle(mon, fdname);
else
ret = qemuMonitorTextCloseFileHandle(mon, fdname);
return ret;
}
int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
const char *netstr)
{
int ret;
DEBUG("mon=%p, fd=%d netstr=%s",
mon, mon->fd, netstr);
if (mon->json)
ret = qemuMonitorJSONAddHostNetwork(mon, netstr);
else
ret = qemuMonitorTextAddHostNetwork(mon, netstr);
return ret;
}
int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon,
int vlan,
const char *netname)
{
int ret;
DEBUG("mon=%p, fd=%d netname=%s",
mon, mon->fd, netname);
if (mon->json)
ret = qemuMonitorJSONRemoveHostNetwork(mon, vlan, netname);
else
ret = qemuMonitorTextRemoveHostNetwork(mon, vlan, netname);
return ret;
}
int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
virHashTablePtr paths)
{
int ret;
DEBUG("mon=%p, fd=%d",
mon, mon->fd);
if (mon->json)
ret = qemuMonitorJSONGetPtyPaths(mon, paths);
else
ret = qemuMonitorTextGetPtyPaths(mon, paths);
return ret;
}
int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon,
const char *bus,
virDomainDevicePCIAddress *guestAddr)
{
DEBUG("mon=%p, fd=%d type=%s", mon, mon->fd, bus);
int ret;
if (mon->json)
ret = qemuMonitorJSONAttachPCIDiskController(mon, bus, guestAddr);
else
ret = qemuMonitorTextAttachPCIDiskController(mon, bus, guestAddr);
return ret;
}
int qemuMonitorAttachDrive(qemuMonitorPtr mon,
const char *drivestr,
virDomainDevicePCIAddress *controllerAddr,
virDomainDeviceDriveAddress *driveAddr)
{
DEBUG("mon=%p, fd=%d drivestr=%s domain=%d bus=%d slot=%d function=%d",
mon, mon->fd, drivestr,
controllerAddr->domain, controllerAddr->bus,
controllerAddr->slot, controllerAddr->function);
int ret;
if (mon->json)
ret = qemuMonitorJSONAttachDrive(mon, drivestr, controllerAddr, driveAddr);
else
ret = qemuMonitorTextAttachDrive(mon, drivestr, controllerAddr, driveAddr);
return ret;
}
int qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon,
qemuMonitorPCIAddress **addrs)
{
DEBUG("mon=%p, fd=%d addrs=%p", mon, mon->fd, addrs);
int ret;
if (mon->json)
ret = qemuMonitorJSONGetAllPCIAddresses(mon, addrs);
else
ret = qemuMonitorTextGetAllPCIAddresses(mon, addrs);
return ret;
}
int qemuMonitorAddDevice(qemuMonitorPtr mon,
const char *devicestr)
{
DEBUG("mon=%p, fd=%d device=%s", mon, mon->fd, devicestr);
int ret;
if (mon->json)
ret = qemuMonitorJSONAddDevice(mon, devicestr);
else
ret = qemuMonitorTextAddDevice(mon, devicestr);
return ret;
}
int qemuMonitorAddDrive(qemuMonitorPtr mon,
const char *drivestr)
{
DEBUG("mon=%p, fd=%d drive=%s", mon, mon->fd, drivestr);
int ret;
if (mon->json)
ret = qemuMonitorJSONAddDrive(mon, drivestr);
else
ret = qemuMonitorTextAddDrive(mon, drivestr);
return ret;
}
int qemuMonitorSetDrivePassphrase(qemuMonitorPtr mon,
const char *alias,
const char *passphrase)
{
DEBUG("mon=%p, fd=%d alias=%s passphrase=%p(value hidden)", mon, mon->fd, alias, passphrase);
int ret;
if (mon->json)
ret = qemuMonitorJSONSetDrivePassphrase(mon, alias, passphrase);
else
ret = qemuMonitorTextSetDrivePassphrase(mon, alias, passphrase);
return ret;
}