libvirt/src/qemu/qemu_monitor.c
Matthew Booth 60e8977fdd Get QEMU pty paths from the monitor
This change makes the QEMU driver get pty paths from the output of the
monitor 'info chardev' command. This output is structured, and contains
both the name of the device and the path on the same line. This is
considerably more reliable than parsing the startup log output, which
requires the parsing code to know which order QEMU will print pty
information in.

Note that we still need to parse the log output as the monitor itself
may be on a pty. This should be rare, however, and the new code will
replace all pty paths parsed by the log output method once the monitor
is available.

* src/qemu/qemu_monitor.(c|h) src/qemu_monitor_text.(c|h): Implement
  qemuMonitorGetPtyPaths().
* src/qemu/qemu_driver.c: Get pty path information using
  qemuMonitorGetPtyPaths().
2009-12-14 10:50:01 +01:00

1279 lines
34 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(NULL, 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) {
qemudReportError(NULL, NULL, NULL, 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(NULL, errno, "%s",
_("failed to connect to monitor socket"));
goto error;
} while ((++i <= timeout*5) && (usleep(.2 * 1000000) <= 0));
if (ret != 0) {
virReportSystemError(NULL, 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) {
qemudReportError(NULL, NULL, NULL, 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) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
_("EOF notify callback must be supplied"));
return NULL;
}
if (VIR_ALLOC(mon) < 0) {
virReportOOMError(NULL);
return NULL;
}
if (virMutexInit(&mon->lock) < 0) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot initialize monitor mutex"));
VIR_FREE(mon);
return NULL;
}
if (virCondInit(&mon->notify) < 0) {
qemudReportError(NULL, NULL, NULL, 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:
qemudReportError(NULL, NULL, NULL, 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) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Unable to set monitor close-on-exec flag"));
goto cleanup;
}
if (virSetNonBlock(mon->fd) < 0) {
qemudReportError(NULL, NULL, NULL, 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) {
qemudReportError(NULL, NULL, NULL, 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
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,
unsigned hostDomain,
unsigned hostBus,
unsigned hostSlot,
unsigned hostFunction,
unsigned *guestDomain,
unsigned *guestBus,
unsigned *guestSlot)
{
int ret;
DEBUG("mon=%p, fd=%d domain=%d bus=%d slot=%d function=%d",
mon, mon->fd,
hostDomain, hostBus, hostSlot, hostFunction);
if (mon->json)
ret = qemuMonitorJSONAddPCIHostDevice(mon, hostDomain,
hostBus, hostSlot,
hostFunction,
guestDomain,
guestBus,
guestSlot);
else
ret = qemuMonitorTextAddPCIHostDevice(mon, hostDomain,
hostBus, hostSlot,
hostFunction,
guestDomain,
guestBus,
guestSlot);
return ret;
}
int qemuMonitorAddPCIDisk(qemuMonitorPtr mon,
const char *path,
const char *bus,
unsigned *guestDomain,
unsigned *guestBus,
unsigned *guestSlot)
{
int ret;
DEBUG("mon=%p, fd=%d path=%s bus=%s",
mon, mon->fd, path, bus);
if (mon->json)
ret = qemuMonitorJSONAddPCIDisk(mon, path, bus,
guestDomain, guestBus, guestSlot);
else
ret = qemuMonitorTextAddPCIDisk(mon, path, bus,
guestDomain, guestBus, guestSlot);
return ret;
}
int qemuMonitorAddPCINetwork(qemuMonitorPtr mon,
const char *nicstr,
unsigned *guestDomain,
unsigned *guestBus,
unsigned *guestSlot)
{
int ret;
DEBUG("mon=%p, fd=%d nicstr=%s", mon, mon->fd, nicstr);
if (mon->json)
ret = qemuMonitorJSONAddPCINetwork(mon, nicstr, guestDomain,
guestBus, guestSlot);
else
ret = qemuMonitorTextAddPCINetwork(mon, nicstr, guestDomain,
guestBus, guestSlot);
return ret;
}
int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon,
unsigned guestDomain,
unsigned guestBus,
unsigned guestSlot)
{
int ret;
DEBUG("mon=%p, fd=%d domain=%d bus=%d slot=%d",
mon, mon->fd, guestDomain, guestBus, guestSlot);
if (mon->json)
ret = qemuMonitorJSONRemovePCIDevice(mon, guestDomain,
guestBus, guestSlot);
else
ret = qemuMonitorTextRemovePCIDevice(mon, guestDomain,
guestBus, guestSlot);
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)
{
DEBUG("mon=%p, fd=%d",
mon, mon->fd);
return qemuMonitorTextGetPtyPaths(mon, paths);
}