qemu_monitor.c 89.2 KB
Newer Older
1 2 3
/*
 * qemu_monitor.c: interaction with QEMU monitor console
 *
4
 * Copyright (C) 2006-2013 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26 27 28 29 30 31
 *
 * 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"
32
#include "qemu_monitor_text.h"
D
Daniel P. Berrange 已提交
33
#include "qemu_monitor_json.h"
34
#include "virerror.h"
35
#include "viralloc.h"
36
#include "virlog.h"
E
Eric Blake 已提交
37
#include "virfile.h"
38
#include "virprocess.h"
39
#include "virobject.h"
40

41 42 43 44
#ifdef WITH_DTRACE_PROBES
# include "libvirt_qemu_probes.h"
#endif

45 46
#define VIR_FROM_THIS VIR_FROM_QEMU

47 48
#define DEBUG_IO 0
#define DEBUG_RAW_IO 0
49

50
struct _qemuMonitor {
51
    virObjectLockable parent;
52

53 54
    virCond notify;

55 56 57 58 59 60
    int fd;
    int watch;
    int hasSendFD;

    virDomainObjPtr vm;

61
    qemuMonitorCallbacksPtr cb;
62 63 64 65 66 67 68 69 70 71 72 73 74

    /* 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 */
75 76 77
    virError lastError;

    int nextSerial;
78

D
Daniel P. Berrange 已提交
79
    unsigned json: 1;
80
    unsigned wait_greeting: 1;
81 82
};

83 84 85 86 87
static virClassPtr qemuMonitorClass;
static void qemuMonitorDispose(void *obj);

static int qemuMonitorOnceInit(void)
{
88
    if (!(qemuMonitorClass = virClassNew(virClassForObjectLockable(),
89 90 91
                                         "qemuMonitor",
                                         sizeof(qemuMonitor),
                                         qemuMonitorDispose)))
92 93 94 95 96 97 98
        return -1;

    return 0;
}

VIR_ONCE_GLOBAL_INIT(qemuMonitor)

99

100 101 102 103
VIR_ENUM_IMPL(qemuMonitorMigrationStatus,
              QEMU_MONITOR_MIGRATION_STATUS_LAST,
              "inactive", "active", "completed", "failed", "cancelled")

104 105 106 107 108 109
VIR_ENUM_IMPL(qemuMonitorVMStatus,
              QEMU_MONITOR_VM_STATUS_LAST,
              "debug", "inmigrate", "internal-error", "io-error", "paused",
              "postmigrate", "prelaunch", "finish-migrate", "restore-vm",
              "running", "save-vm", "shutdown", "watchdog")

110 111 112 113 114 115 116 117 118 119 120 121 122 123
typedef enum {
    QEMU_MONITOR_BLOCK_IO_STATUS_OK,
    QEMU_MONITOR_BLOCK_IO_STATUS_FAILED,
    QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE,

    QEMU_MONITOR_BLOCK_IO_STATUS_LAST
} qemuMonitorBlockIOStatus;

VIR_ENUM_DECL(qemuMonitorBlockIOStatus)

VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
              QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
              "ok", "failed", "nospace")

124
char *qemuMonitorEscapeArg(const char *in)
125 126 127 128 129 130 131 132 133 134
{
    int len = 0;
    int i, j;
    char *out;

    /* To pass through the QEMU monitor, we need to use escape
       sequences: \r, \n, \", \\
    */

    for (i = 0; in[i] != '\0'; i++) {
135
        switch (in[i]) {
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
        case '\r':
        case '\n':
        case '"':
        case '\\':
            len += 2;
            break;
        default:
            len += 1;
            break;
        }
    }

    if (VIR_ALLOC_N(out, len + 1) < 0)
        return NULL;

    for (i = j = 0; in[i] != '\0'; i++) {
152
        switch (in[i]) {
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
        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;
        default:
            out[j++] = in[i];
            break;
        }
    }
    out[j] = '\0';

    return out;
}

176 177 178 179
char *qemuMonitorUnescapeArg(const char *in)
{
    int i, j;
    char *out;
180
    int len = strlen(in);
181 182
    char next;

183
    if (VIR_ALLOC_N(out, len + 1) < 0)
184 185 186 187 188 189
        return NULL;

    for (i = j = 0; i < len; ++i) {
        next = in[i];
        if (in[i] == '\\') {
            ++i;
190
            switch (in[i]) {
191 192 193 194 195 196 197 198 199 200 201
            case 'r':
                next = '\r';
                break;
            case 'n':
                next = '\n';
                break;
            case '"':
            case '\\':
                next = in[i];
                break;
            default:
202
                /* invalid input (including trailing '\' at end of in) */
203 204 205 206 207 208 209 210 211 212 213
                VIR_FREE(out);
                return NULL;
            }
        }
        out[j++] = next;
    }
    out[j] = '\0';

    return out;
}

J
Jiri Denemark 已提交
214
#if DEBUG_RAW_IO
215
# include <c-ctype.h>
216 217 218 219 220 221 222 223
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'))
224
            virBufferAsprintf(&buf,"%c", text[i]);
225
        else
226
            virBufferAsprintf(&buf, "0x%02x", text[i]);
227 228 229 230 231
    }
    return virBufferContentAndReset(&buf);
}
#endif

232
static void qemuMonitorDispose(void *obj)
233
{
234 235
    qemuMonitorPtr mon = obj;

236
    VIR_DEBUG("mon=%p", mon);
237
    if (mon->cb && mon->cb->destroy)
238
        (mon->cb->destroy)(mon, mon->vm);
239
    virCondDestroy(&mon->notify);
E
Eric Blake 已提交
240
    VIR_FREE(mon->buffer);
241 242 243 244
}


static int
245
qemuMonitorOpenUnix(const char *monitor, pid_t cpid)
246 247 248 249 250 251 252
{
    struct sockaddr_un addr;
    int monfd;
    int timeout = 3; /* In seconds */
    int ret, i = 0;

    if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
253
        virReportSystemError(errno,
254 255 256 257 258 259 260
                             "%s", _("failed to create socket"));
        return -1;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    if (virStrcpyStatic(addr.sun_path, monitor) == NULL) {
261 262
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Monitor path %s too big for destination"), monitor);
263 264 265 266 267 268 269 270 271
        goto error;
    }

    do {
        ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));

        if (ret == 0)
            break;

272
        if ((errno == ENOENT || errno == ECONNREFUSED) &&
273
            (!cpid || virProcessKill(cpid, 0) == 0)) {
274 275 276 277 278
            /* ENOENT       : Socket may not have shown up yet
             * ECONNREFUSED : Leftover socket hasn't been removed yet */
            continue;
        }

279
        virReportSystemError(errno, "%s",
280 281 282 283 284 285
                             _("failed to connect to monitor socket"));
        goto error;

    } while ((++i <= timeout*5) && (usleep(.2 * 1000000) <= 0));

    if (ret != 0) {
286
        virReportSystemError(errno, "%s",
287
                             _("monitor socket did not show up"));
288 289 290
        goto error;
    }

291
    return monfd;
292 293

error:
294
    VIR_FORCE_CLOSE(monfd);
295 296 297 298
    return -1;
}

static int
299
qemuMonitorOpenPty(const char *monitor)
300 301 302 303
{
    int monfd;

    if ((monfd = open(monitor, O_RDWR)) < 0) {
304 305
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unable to open monitor path %s"), monitor);
306 307 308
        return -1;
    }

309
    return monfd;
310
}
311

312

313 314 315 316
/* This method processes data that has been received
 * from the monitor. Looking for async events and
 * replies/errors.
 */
317 318 319 320 321 322 323 324 325 326 327
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;

328
#if DEBUG_IO
329
# if DEBUG_RAW_IO
330 331
    char *str1 = qemuMonitorEscapeNonPrintable(msg ? msg->txBuffer : "");
    char *str2 = qemuMonitorEscapeNonPrintable(mon->buffer);
332
    VIR_ERROR(_("Process %d %p %p [[[[%s]]][[[%s]]]"), (int)mon->bufferOffset, mon->msg, msg, str1, str2);
333 334
    VIR_FREE(str1);
    VIR_FREE(str2);
335
# else
336
    VIR_DEBUG("Process %d", (int)mon->bufferOffset);
337
# endif
338 339
#endif

340 341 342
    PROBE(QEMU_MONITOR_IO_PROCESS,
          "mon=%p buf=%s len=%zu", mon, mon->buffer, mon->bufferOffset);

D
Daniel P. Berrange 已提交
343 344 345 346 347 348 349 350
    if (mon->json)
        len = qemuMonitorJSONIOProcess(mon,
                                       mon->buffer, mon->bufferOffset,
                                       msg);
    else
        len = qemuMonitorTextIOProcess(mon,
                                       mon->buffer, mon->bufferOffset,
                                       msg);
351

352
    if (len < 0)
353 354
        return -1;

355 356 357
    if (len && mon->wait_greeting)
        mon->wait_greeting = 0;

358 359 360 361 362 363 364
    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;
    }
365
#if DEBUG_IO
366
    VIR_DEBUG("Process done %d used %d", (int)mon->bufferOffset, len);
367
#endif
368 369 370 371 372 373
    if (msg && msg->finished)
        virCondBroadcast(&mon->notify);
    return len;
}


S
Stefan Berger 已提交
374
/* Call this function while holding the monitor lock. */
375 376 377 378 379 380 381 382 383 384 385 386 387
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;

    memset(&msg, 0, sizeof(msg));
388
    memset(control, 0, sizeof(control));
389 390 391 392 393 394 395 396 397 398 399

    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);
400 401 402
    /* Some static analyzers, like clang 2.6-0.6.pre2, fail to see
       that our use of CMSG_FIRSTHDR will not return NULL.  */
    sa_assert(cmsg);
403 404 405 406 407 408 409 410 411 412 413 414
    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;
}

S
Stefan Berger 已提交
415 416 417 418
/*
 * Called when the monitor is able to write data
 * Call this function while holding the monitor lock.
 */
419 420 421 422 423 424 425 426 427
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;

428
    if (mon->msg->txFD != -1 && !mon->hasSendFD) {
429 430
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Monitor does not support sending of file descriptors"));
431 432 433
        return -1;
    }

434 435 436 437 438 439 440 441 442 443
    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);

444 445 446 447 448 449 450 451 452 453 454 455
    PROBE(QEMU_MONITOR_IO_WRITE,
          "mon=%p buf=%s len=%d ret=%d errno=%d",
          mon,
          mon->msg->txBuffer + mon->msg->txOffset,
          mon->msg->txLength - mon->msg->txOffset,
          done, errno);

    if (mon->msg->txFD != -1)
        PROBE(QEMU_MONITOR_IO_SEND_FD,
              "mon=%p fd=%d ret=%d errno=%d",
              mon, mon->msg->txFD, done, errno);

456 457 458 459
    if (done < 0) {
        if (errno == EAGAIN)
            return 0;

460 461
        virReportSystemError(errno, "%s",
                             _("Unable to write to monitor"));
462 463 464 465 466 467 468 469
        return -1;
    }
    mon->msg->txOffset += done;
    return done;
}

/*
 * Called when the monitor has incoming data to read
S
Stefan Berger 已提交
470
 * Call this function while holding the monitor lock.
471 472 473 474 475 476 477 478 479 480 481 482
 *
 * 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) {
483
            virReportOOMError();
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
            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;
500 501
            virReportSystemError(errno, "%s",
                                 _("Unable to read from monitor"));
502 503 504 505 506 507 508 509 510 511 512 513
            ret = -1;
            break;
        }
        if (got == 0)
            break;

        ret += got;
        avail -= got;
        mon->bufferOffset += got;
        mon->buffer[mon->bufferOffset] = '\0';
    }

514
#if DEBUG_IO
515
    VIR_DEBUG("Now read %d bytes of data", (int)mon->bufferOffset);
516
#endif
517 518 519 520 521 522 523 524 525 526 527

    return ret;
}


static void qemuMonitorUpdateWatch(qemuMonitorPtr mon)
{
    int events =
        VIR_EVENT_HANDLE_HANGUP |
        VIR_EVENT_HANDLE_ERROR;

528 529 530
    if (!mon->watch)
        return;

531
    if (mon->lastError.code == VIR_ERR_OK) {
532 533
        events |= VIR_EVENT_HANDLE_READABLE;

534 535
        if ((mon->msg && mon->msg->txOffset < mon->msg->txLength) &&
            !mon->wait_greeting)
536 537 538 539
            events |= VIR_EVENT_HANDLE_WRITABLE;
    }

    virEventUpdateHandle(mon->watch, events);
540 541
}

542 543 544 545

static void
qemuMonitorIO(int watch, int fd, int events, void *opaque) {
    qemuMonitorPtr mon = opaque;
546 547
    bool error = false;
    bool eof = false;
548

549 550
    virObjectRef(mon);

S
Stefan Berger 已提交
551
    /* lock access to the monitor and protect fd */
552
    virObjectLock(mon);
553
#if DEBUG_IO
554
    VIR_DEBUG("Monitor %p I/O on watch %d fd %d events %d", mon, watch, fd, events);
555
#endif
556
    if (mon->fd == -1 || mon->watch == 0) {
557
        virObjectUnlock(mon);
558 559 560
        virObjectUnref(mon);
        return;
    }
561

562
    if (mon->fd != fd || mon->watch != watch) {
563
        if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
564
            eof = true;
565 566 567
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("event from unexpected fd %d!=%d / watch %d!=%d"),
                       mon->fd, fd, mon->watch, watch);
568 569
        error = true;
    } else if (mon->lastError.code != VIR_ERR_OK) {
570
        if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
571
            eof = true;
572
        error = true;
573
    } else {
574 575 576
        if (events & VIR_EVENT_HANDLE_WRITABLE) {
            if (qemuMonitorIOWrite(mon) < 0)
                error = true;
577 578
            events &= ~VIR_EVENT_HANDLE_WRITABLE;
        }
579 580

        if (!error &&
581 582
            events & VIR_EVENT_HANDLE_READABLE) {
            int got = qemuMonitorIORead(mon);
583 584
            events &= ~VIR_EVENT_HANDLE_READABLE;
            if (got < 0) {
585
                error = true;
586 587 588 589 590
            } else if (got == 0) {
                eof = true;
            } else {
                /* Ignore hangup/error events if we read some data, to
                 * give time for that data to be consumed */
591 592 593
                events = 0;

                if (qemuMonitorIOProcess(mon) < 0)
594
                    error = true;
595
            }
596 597
        }

598 599
        if (!error &&
            events & VIR_EVENT_HANDLE_HANGUP) {
600 601
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("End of file from monitor"));
602 603
            eof = 1;
            events &= ~VIR_EVENT_HANDLE_HANGUP;
604 605
        }

606 607
        if (!error && !eof &&
            events & VIR_EVENT_HANDLE_ERROR) {
608 609
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Invalid file descriptor while waiting for monitor"));
610 611
            eof = 1;
            events &= ~VIR_EVENT_HANDLE_ERROR;
612 613
        }
        if (!error && events) {
614 615 616
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unhandled event %d for monitor fd %d"),
                           events, mon->fd);
617
            error = 1;
618 619 620
        }
    }

621 622 623 624 625 626 627
    if (error || eof) {
        if (mon->lastError.code != VIR_ERR_OK) {
            /* Already have an error, so clear any new error */
            virResetLastError();
        } else {
            virErrorPtr err = virGetLastError();
            if (!err)
628 629
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Error while processing monitor IO"));
630 631 632 633 634 635 636 637 638 639 640 641
            virCopyLastError(&mon->lastError);
            virResetLastError();
        }

        VIR_DEBUG("Error on monitor %s", NULLSTR(mon->lastError.message));
        /* If IO process resulted in an error & we have a message,
         * then wakeup that waiter */
        if (mon->msg && !mon->msg->finished) {
            mon->msg->finished = 1;
            virCondSignal(&mon->notify);
        }
    }
642 643 644

    qemuMonitorUpdateWatch(mon);

645 646 647
    /* 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 */
648 649
    if (eof) {
        void (*eofNotify)(qemuMonitorPtr, virDomainObjPtr)
650
            = mon->cb->eofNotify;
651
        virDomainObjPtr vm = mon->vm;
652

653 654
        /* Make sure anyone waiting wakes up now */
        virCondSignal(&mon->notify);
655
        virObjectUnlock(mon);
656
        virObjectUnref(mon);
657 658 659 660 661 662
        VIR_DEBUG("Triggering EOF callback");
        (eofNotify)(mon, vm);
    } else if (error) {
        void (*errorNotify)(qemuMonitorPtr, virDomainObjPtr)
            = mon->cb->errorNotify;
        virDomainObjPtr vm = mon->vm;
663

664 665
        /* Make sure anyone waiting wakes up now */
        virCondSignal(&mon->notify);
666
        virObjectUnlock(mon);
667
        virObjectUnref(mon);
668 669
        VIR_DEBUG("Triggering error callback");
        (errorNotify)(mon, vm);
670
    } else {
671
        virObjectUnlock(mon);
672
        virObjectUnref(mon);
673
    }
674 675 676
}


677 678 679 680 681 682
static qemuMonitorPtr
qemuMonitorOpenInternal(virDomainObjPtr vm,
                        int fd,
                        bool hasSendFD,
                        int json,
                        qemuMonitorCallbacksPtr cb)
683
{
684 685
    qemuMonitorPtr mon;

686
    if (!cb->eofNotify) {
687 688
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("EOF notify callback must be supplied"));
689 690
        return NULL;
    }
691 692 693 694 695
    if (!cb->errorNotify) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Error notify callback must be supplied"));
        return NULL;
    }
696

697 698 699
    if (qemuMonitorInitialize() < 0)
        return NULL;

700
    if (!(mon = virObjectLockableNew(qemuMonitorClass)))
701 702
        return NULL;

703
    mon->fd = -1;
704
    if (virCondInit(&mon->notify) < 0) {
705 706
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot initialize monitor condition"));
707
        goto cleanup;
708
    }
709 710
    mon->fd = fd;
    mon->hasSendFD = hasSendFD;
711
    mon->vm = vm;
D
Daniel P. Berrange 已提交
712
    mon->json = json;
713 714
    if (json)
        mon->wait_greeting = 1;
715
    mon->cb = cb;
716
    virObjectLock(mon);
717

718
    if (virSetCloseExec(mon->fd) < 0) {
719 720
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Unable to set monitor close-on-exec flag"));
721 722 723
        goto cleanup;
    }
    if (virSetNonBlock(mon->fd) < 0) {
724 725
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Unable to put monitor into non-blocking mode"));
726 727 728 729
        goto cleanup;
    }


730
    virObjectRef(mon);
731
    if ((mon->watch = virEventAddHandle(mon->fd,
732 733 734
                                        VIR_EVENT_HANDLE_HANGUP |
                                        VIR_EVENT_HANDLE_ERROR |
                                        VIR_EVENT_HANDLE_READABLE,
735
                                        qemuMonitorIO,
736 737
                                        mon,
                                        virObjectFreeCallback)) < 0) {
738
        virObjectUnref(mon);
739 740
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unable to register monitor events"));
741 742 743
        goto cleanup;
    }

744 745
    PROBE(QEMU_MONITOR_NEW,
          "mon=%p refs=%d fd=%d",
746 747
          mon, mon->parent.parent.refs, mon->fd);
    virObjectUnlock(mon);
748

749 750 751
    return mon;

cleanup:
752 753 754 755 756 757
    /* We don't want the 'destroy' callback invoked during
     * cleanup from construction failure, because that can
     * give a double-unref on virDomainObjPtr in the caller,
     * so kill the callbacks now.
     */
    mon->cb = NULL;
758
    virObjectUnlock(mon);
759 760 761 762
    /* The caller owns 'fd' on failure */
    mon->fd = -1;
    if (mon->watch)
        virEventRemoveHandle(mon->watch);
763 764 765 766
    qemuMonitorClose(mon);
    return NULL;
}

767 768 769 770 771 772 773 774 775 776 777 778 779
qemuMonitorPtr
qemuMonitorOpen(virDomainObjPtr vm,
                virDomainChrSourceDefPtr config,
                int json,
                qemuMonitorCallbacksPtr cb)
{
    int fd;
    bool hasSendFD = false;
    qemuMonitorPtr ret;

    switch (config->type) {
    case VIR_DOMAIN_CHR_TYPE_UNIX:
        hasSendFD = true;
780
        if ((fd = qemuMonitorOpenUnix(config->data.nix.path, vm ? vm->pid : 0)) < 0)
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
            return NULL;
        break;

    case VIR_DOMAIN_CHR_TYPE_PTY:
        if ((fd = qemuMonitorOpenPty(config->data.file.path)) < 0)
            return NULL;
        break;

    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unable to handle monitor type: %s"),
                       virDomainChrTypeToString(config->type));
        return NULL;
    }

    ret = qemuMonitorOpenInternal(vm, fd, hasSendFD, json, cb);
    if (!ret)
        VIR_FORCE_CLOSE(fd);
    return ret;
}


qemuMonitorPtr qemuMonitorOpenFD(virDomainObjPtr vm,
                                 int sockfd,
                                 int json,
                                 qemuMonitorCallbacksPtr cb)
{
    return qemuMonitorOpenInternal(vm, sockfd, true, json, cb);
}

811

812
void qemuMonitorClose(qemuMonitorPtr mon)
813 814
{
    if (!mon)
815
        return;
816

817
    virObjectLock(mon);
818
    PROBE(QEMU_MONITOR_CLOSE,
819
          "mon=%p refs=%d", mon, mon->parent.parent.refs);
S
Stefan Berger 已提交
820 821

    if (mon->fd >= 0) {
822
        if (mon->watch) {
823
            virEventRemoveHandle(mon->watch);
824 825
            mon->watch = 0;
        }
S
Stefan Berger 已提交
826
        VIR_FORCE_CLOSE(mon->fd);
827
    }
828

829 830 831 832 833 834 835
    /* In case another thread is waiting for its monitor command to be
     * processed, we need to wake it up with appropriate error set.
     */
    if (mon->msg) {
        if (mon->lastError.code == VIR_ERR_OK) {
            virErrorPtr err = virSaveLastError();

836 837
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("Qemu monitor was closed"));
838 839 840 841 842 843 844 845 846 847 848 849
            virCopyLastError(&mon->lastError);
            if (err) {
                virSetError(err);
                virFreeError(err);
            } else {
                virResetLastError();
            }
        }
        mon->msg->finished = 1;
        virCondSignal(&mon->notify);
    }

850
    virObjectUnlock(mon);
851
    virObjectUnref(mon);
852 853 854
}


855 856 857 858 859 860 861 862 863 864 865 866
char *qemuMonitorNextCommandID(qemuMonitorPtr mon)
{
    char *id;

    if (virAsprintf(&id, "libvirt-%d", ++mon->nextSerial) < 0) {
        virReportOOMError();
        return NULL;
    }
    return id;
}


867 868
int qemuMonitorSend(qemuMonitorPtr mon,
                    qemuMonitorMessagePtr msg)
869
{
870
    int ret = -1;
871

872
    /* Check whether qemu quited unexpectedly */
873 874 875 876
    if (mon->lastError.code != VIR_ERR_OK) {
        VIR_DEBUG("Attempt to send command while error is set %s",
                  NULLSTR(mon->lastError.message));
        virSetError(&mon->lastError);
877 878 879
        return -1;
    }

880 881
    mon->msg = msg;
    qemuMonitorUpdateWatch(mon);
882

883 884 885 886
    PROBE(QEMU_MONITOR_SEND_MSG,
          "mon=%p msg=%s fd=%d",
          mon, mon->msg->txBuffer, mon->msg->txFD);

887
    while (!mon->msg->finished) {
888
        if (virCondWait(&mon->notify, &mon->parent.lock) < 0) {
889 890
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Unable to wait on monitor condition"));
891
            goto cleanup;
892 893 894 895 896 897 898 899
        }
    }

    if (mon->lastError.code != VIR_ERR_OK) {
        VIR_DEBUG("Send command resulted in error %s",
                  NULLSTR(mon->lastError.message));
        virSetError(&mon->lastError);
        goto cleanup;
900
    }
901

902
    ret = 0;
903

904 905 906
cleanup:
    mon->msg = NULL;
    qemuMonitorUpdateWatch(mon);
907

908
    return ret;
909
}
910 911


912 913 914 915
int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
                                const char *cmd,
                                int scm_fd,
                                char **reply)
916
{
917 918 919 920 921 922 923 924
    char *json_cmd = NULL;
    int ret = -1;

    if (mon->json) {
        /* hack to avoid complicating each call to text monitor functions */
        json_cmd = qemuMonitorUnescapeArg(cmd);
        if (!json_cmd) {
            VIR_DEBUG("Could not unescape command: %s", cmd);
925 926
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Unable to unescape command"));
927 928 929 930 931 932 933 934 935 936
            goto cleanup;
        }
        ret = qemuMonitorJSONHumanCommandWithFd(mon, json_cmd, scm_fd, reply);
    } else {
        ret = qemuMonitorTextCommandWithFd(mon, cmd, scm_fd, reply);
    }

cleanup:
    VIR_FREE(json_cmd);
    return ret;
937 938
}

E
Eric Blake 已提交
939 940 941
/* Ensure proper locking around callbacks.  */
#define QEMU_MONITOR_CALLBACK(mon, ret, callback, ...)          \
    do {                                                        \
942
        virObjectRef(mon);                                      \
943
        virObjectUnlock(mon);                                   \
E
Eric Blake 已提交
944 945
        if ((mon)->cb && (mon)->cb->callback)                   \
            (ret) = ((mon)->cb->callback)(mon, __VA_ARGS__);    \
946
        virObjectLock(mon);                                     \
947
        virObjectUnref(mon);                                    \
E
Eric Blake 已提交
948
    } while (0)
949

950 951 952 953 954 955
int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
                             virConnectPtr conn,
                             const char *path,
                             char **secret,
                             size_t *secretLen)
{
956
    int ret = -1;
957 958 959
    *secret = NULL;
    *secretLen = 0;

E
Eric Blake 已提交
960 961
    QEMU_MONITOR_CALLBACK(mon, ret, diskSecretLookup, conn, mon->vm,
                          path, secret, secretLen);
962
    return ret;
963
}
964 965


966 967 968 969 970
int qemuMonitorEmitShutdown(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
971
    QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm);
972 973 974 975 976 977 978 979 980
    return ret;
}


int qemuMonitorEmitReset(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
981
    QEMU_MONITOR_CALLBACK(mon, ret, domainReset, mon->vm);
982 983 984 985 986 987 988 989 990
    return ret;
}


int qemuMonitorEmitPowerdown(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
991
    QEMU_MONITOR_CALLBACK(mon, ret, domainPowerdown, mon->vm);
992 993 994 995 996 997 998 999 1000
    return ret;
}


int qemuMonitorEmitStop(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
1001
    QEMU_MONITOR_CALLBACK(mon, ret, domainStop, mon->vm);
1002 1003 1004 1005
    return ret;
}


1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
int qemuMonitorEmitResume(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

    QEMU_MONITOR_CALLBACK(mon, ret, domainResume, mon->vm);
    return ret;
}


1016 1017 1018 1019 1020
int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
1021
    QEMU_MONITOR_CALLBACK(mon, ret, domainRTCChange, mon->vm, offset);
1022 1023 1024 1025
    return ret;
}


1026 1027 1028 1029 1030
int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
1031
    QEMU_MONITOR_CALLBACK(mon, ret, domainWatchdog, mon->vm, action);
1032 1033 1034 1035
    return ret;
}


1036 1037
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
                           const char *diskAlias,
1038 1039
                           int action,
                           const char *reason)
1040 1041 1042 1043
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
1044 1045
    QEMU_MONITOR_CALLBACK(mon, ret, domainIOError, mon->vm,
                          diskAlias, action, reason);
1046 1047 1048 1049
    return ret;
}


1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
                            int phase,
                            int localFamily,
                            const char *localNode,
                            const char *localService,
                            int remoteFamily,
                            const char *remoteNode,
                            const char *remoteService,
                            const char *authScheme,
                            const char *x509dname,
                            const char *saslUsername)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

E
Eric Blake 已提交
1065 1066 1067 1068
    QEMU_MONITOR_CALLBACK(mon, ret, domainGraphics, mon->vm, phase,
                          localFamily, localNode, localService,
                          remoteFamily, remoteNode, remoteService,
                          authScheme, x509dname, saslUsername);
1069 1070 1071
    return ret;
}

1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
int qemuMonitorEmitTrayChange(qemuMonitorPtr mon,
                              const char *devAlias,
                              int reason)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

    QEMU_MONITOR_CALLBACK(mon, ret, domainTrayChange, mon->vm,
                          devAlias, reason);

    return ret;
}

O
Osier Yang 已提交
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
int qemuMonitorEmitPMWakeup(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

    QEMU_MONITOR_CALLBACK(mon, ret, domainPMWakeup, mon->vm);

    return ret;
}

O
Osier Yang 已提交
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
int qemuMonitorEmitPMSuspend(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

    QEMU_MONITOR_CALLBACK(mon, ret, domainPMSuspend, mon->vm);

    return ret;
}

1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

    QEMU_MONITOR_CALLBACK(mon, ret, domainPMSuspendDisk, mon->vm);

    return ret;
}

1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
                            const char *diskAlias,
                            int type,
                            int status)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

    QEMU_MONITOR_CALLBACK(mon, ret, domainBlockJob, mon->vm,
                          diskAlias, type, status);
    return ret;
}

1128

1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
int qemuMonitorEmitBalloonChange(qemuMonitorPtr mon,
                                 unsigned long long actual)
{
    int ret = -1;
    VIR_DEBUG("mon=%p", mon);

    QEMU_MONITOR_CALLBACK(mon, ret, domainBalloonChange, mon->vm, actual);
    return ret;
}

1139

1140
int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
1141 1142
{
    int ret;
1143
    VIR_DEBUG("mon=%p", mon);
1144 1145

    if (!mon) {
1146 1147
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1148 1149
        return -1;
    }
1150

1151
    if (mon->json) {
1152
        ret = qemuMonitorJSONSetCapabilities(mon);
1153
        if (ret < 0)
1154
            goto cleanup;
1155
    } else {
1156
        ret = 0;
1157
    }
1158 1159

cleanup:
1160 1161 1162 1163
    return ret;
}


1164 1165 1166 1167
int
qemuMonitorStartCPUs(qemuMonitorPtr mon,
                     virConnectPtr conn)
{
D
Daniel P. Berrange 已提交
1168
    int ret;
1169
    VIR_DEBUG("mon=%p", mon);
1170 1171

    if (!mon) {
1172 1173
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1174 1175
        return -1;
    }
1176

D
Daniel P. Berrange 已提交
1177 1178 1179 1180 1181
    if (mon->json)
        ret = qemuMonitorJSONStartCPUs(mon, conn);
    else
        ret = qemuMonitorTextStartCPUs(mon, conn);
    return ret;
1182 1183 1184 1185 1186 1187
}


int
qemuMonitorStopCPUs(qemuMonitorPtr mon)
{
D
Daniel P. Berrange 已提交
1188
    int ret;
1189
    VIR_DEBUG("mon=%p", mon);
1190 1191

    if (!mon) {
1192 1193
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1194 1195
        return -1;
    }
1196

D
Daniel P. Berrange 已提交
1197 1198 1199 1200 1201
    if (mon->json)
        ret = qemuMonitorJSONStopCPUs(mon);
    else
        ret = qemuMonitorTextStopCPUs(mon);
    return ret;
1202 1203 1204
}


1205
int
1206 1207 1208
qemuMonitorGetStatus(qemuMonitorPtr mon,
                     bool *running,
                     virDomainPausedReason *reason)
1209 1210
{
    int ret;
1211
    VIR_DEBUG("mon=%p, running=%p, reason=%p", mon, running, reason);
1212 1213

    if (!mon || !running) {
1214 1215
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("both monitor and running must not be NULL"));
1216 1217 1218 1219
        return -1;
    }

    if (mon->json)
1220
        ret = qemuMonitorJSONGetStatus(mon, running, reason);
1221
    else
1222
        ret = qemuMonitorTextGetStatus(mon, running, reason);
1223 1224 1225 1226
    return ret;
}


1227 1228
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon)
{
D
Daniel P. Berrange 已提交
1229
    int ret;
1230
    VIR_DEBUG("mon=%p", mon);
1231 1232

    if (!mon) {
1233 1234
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1235 1236
        return -1;
    }
1237

D
Daniel P. Berrange 已提交
1238 1239 1240 1241 1242
    if (mon->json)
        ret = qemuMonitorJSONSystemPowerdown(mon);
    else
        ret = qemuMonitorTextSystemPowerdown(mon);
    return ret;
1243 1244 1245
}


1246 1247 1248 1249 1250 1251
int qemuMonitorSystemReset(qemuMonitorPtr mon)
{
    int ret;
    VIR_DEBUG("mon=%p", mon);

    if (!mon) {
1252 1253
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
        return -1;
    }

    if (mon->json)
        ret = qemuMonitorJSONSystemReset(mon);
    else
        ret = qemuMonitorTextSystemReset(mon);
    return ret;
}


1265 1266 1267
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
                          int **pids)
{
D
Daniel P. Berrange 已提交
1268
    int ret;
1269
    VIR_DEBUG("mon=%p", mon);
1270 1271

    if (!mon) {
1272 1273
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1274 1275
        return -1;
    }
1276

D
Daniel P. Berrange 已提交
1277 1278 1279 1280 1281
    if (mon->json)
        ret = qemuMonitorJSONGetCPUInfo(mon, pids);
    else
        ret = qemuMonitorTextGetCPUInfo(mon, pids);
    return ret;
1282 1283
}

1284 1285 1286 1287 1288 1289 1290 1291
int qemuMonitorSetLink(qemuMonitorPtr mon,
                       const char *name,
                       enum virDomainNetInterfaceLinkState state)
{
    int ret;
    VIR_DEBUG("mon=%p, name=%p:%s, state=%u", mon, name, name, state);

    if (!mon || !name) {
1292 1293
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor || name must not be NULL"));
1294 1295 1296 1297 1298 1299 1300 1301 1302
        return -1;
    }

    if (mon->json)
        ret = qemuMonitorJSONSetLink(mon, name, state);
    else
        ret = qemuMonitorTextSetLink(mon, name, state);
    return ret;
}
1303 1304 1305 1306 1307 1308 1309 1310

int qemuMonitorGetVirtType(qemuMonitorPtr mon,
                           int *virtType)
{
    int ret;
    VIR_DEBUG("mon=%p", mon);

    if (!mon) {
1311 1312
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
        return -1;
    }

    if (mon->json)
        ret = qemuMonitorJSONGetVirtType(mon, virtType);
    else
        ret = qemuMonitorTextGetVirtType(mon, virtType);
    return ret;
}


1324
int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
1325
                              unsigned long long *currmem)
1326
{
D
Daniel P. Berrange 已提交
1327
    int ret;
1328
    VIR_DEBUG("mon=%p", mon);
1329 1330

    if (!mon) {
1331 1332
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1333 1334
        return -1;
    }
1335

D
Daniel P. Berrange 已提交
1336 1337 1338 1339 1340
    if (mon->json)
        ret = qemuMonitorJSONGetBalloonInfo(mon, currmem);
    else
        ret = qemuMonitorTextGetBalloonInfo(mon, currmem);
    return ret;
1341 1342 1343
}


1344 1345 1346 1347 1348
int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
                              virDomainMemoryStatPtr stats,
                              unsigned int nr_stats)
{
    int ret;
1349
    VIR_DEBUG("mon=%p stats=%p nstats=%u", mon, stats, nr_stats);
1350 1351

    if (!mon) {
1352 1353
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1354 1355
        return -1;
    }
1356 1357 1358 1359 1360 1361 1362 1363

    if (mon->json)
        ret = qemuMonitorJSONGetMemoryStats(mon, stats, nr_stats);
    else
        ret = qemuMonitorTextGetMemoryStats(mon, stats, nr_stats);
    return ret;
}

1364 1365 1366 1367 1368 1369
int
qemuMonitorBlockIOStatusToError(const char *status)
{
    int st = qemuMonitorBlockIOStatusTypeFromString(status);

    if (st < 0) {
1370 1371
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown block IO status: %s"), status);
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
        return -1;
    }

    switch ((qemuMonitorBlockIOStatus) st) {
    case QEMU_MONITOR_BLOCK_IO_STATUS_OK:
        return VIR_DOMAIN_DISK_ERROR_NONE;
    case QEMU_MONITOR_BLOCK_IO_STATUS_FAILED:
        return VIR_DOMAIN_DISK_ERROR_UNSPEC;
    case QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE:
        return VIR_DOMAIN_DISK_ERROR_NO_SPACE;

    /* unreachable */
    case QEMU_MONITOR_BLOCK_IO_STATUS_LAST:
        break;
    }
    return -1;
}

1390 1391
virHashTablePtr
qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
1392 1393
{
    int ret;
1394 1395 1396
    virHashTablePtr table;

    VIR_DEBUG("mon=%p", mon);
1397 1398

    if (!mon) {
1399 1400
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1401
        return NULL;
1402 1403
    }

1404 1405 1406
    if (!(table = virHashCreate(32, (virHashDataFree) free)))
        return NULL;

1407
    if (mon->json)
1408
        ret = qemuMonitorJSONGetBlockInfo(mon, table);
1409
    else
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
        ret = qemuMonitorTextGetBlockInfo(mon, table);

    if (ret < 0) {
        virHashFree(table);
        return NULL;
    }

    return table;
}

struct qemuDomainDiskInfo *
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
E
Eric Blake 已提交
1422
                           const char *dev)
1423 1424 1425
{
    struct qemuDomainDiskInfo *info;

E
Eric Blake 已提交
1426
    VIR_DEBUG("blockInfo=%p dev=%s", blockInfo, NULLSTR(dev));
1427

E
Eric Blake 已提交
1428
    if (!(info = virHashLookup(blockInfo, dev))) {
1429 1430
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find info for device '%s'"),
E
Eric Blake 已提交
1431
                       NULLSTR(dev));
1432 1433 1434
    }

    return info;
1435
}
1436

1437
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
1438
                                 const char *dev_name,
1439 1440
                                 long long *rd_req,
                                 long long *rd_bytes,
1441
                                 long long *rd_total_times,
1442 1443
                                 long long *wr_req,
                                 long long *wr_bytes,
1444 1445 1446
                                 long long *wr_total_times,
                                 long long *flush_req,
                                 long long *flush_total_times,
1447 1448
                                 long long *errs)
{
D
Daniel P. Berrange 已提交
1449
    int ret;
1450
    VIR_DEBUG("mon=%p dev=%s", mon, dev_name);
1451 1452

    if (!mon) {
1453 1454
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1455 1456
        return -1;
    }
1457

D
Daniel P. Berrange 已提交
1458
    if (mon->json)
1459
        ret = qemuMonitorJSONGetBlockStatsInfo(mon, dev_name,
D
Daniel P. Berrange 已提交
1460
                                               rd_req, rd_bytes,
1461
                                               rd_total_times,
D
Daniel P. Berrange 已提交
1462
                                               wr_req, wr_bytes,
1463 1464 1465
                                               wr_total_times,
                                               flush_req,
                                               flush_total_times,
D
Daniel P. Berrange 已提交
1466 1467
                                               errs);
    else
1468
        ret = qemuMonitorTextGetBlockStatsInfo(mon, dev_name,
D
Daniel P. Berrange 已提交
1469
                                               rd_req, rd_bytes,
1470
                                               rd_total_times,
D
Daniel P. Berrange 已提交
1471
                                               wr_req, wr_bytes,
1472 1473 1474
                                               wr_total_times,
                                               flush_req,
                                               flush_total_times,
D
Daniel P. Berrange 已提交
1475 1476
                                               errs);
    return ret;
1477 1478
}

1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
/* Return 0 and update @nparams with the number of block stats
 * QEMU supports if success. Return -1 if failure.
 */
int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon,
                                         int *nparams)
{
    int ret;
    VIR_DEBUG("mon=%p nparams=%p", mon, nparams);

    if (!mon) {
1489 1490
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501
        return -1;
    }

    if (mon->json)
        ret = qemuMonitorJSONGetBlockStatsParamsNumber(mon, nparams);
    else
        ret = qemuMonitorTextGetBlockStatsParamsNumber(mon, nparams);

    return ret;
}

1502
int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
1503
                              const char *dev_name,
1504 1505 1506
                              unsigned long long *extent)
{
    int ret;
1507 1508
    VIR_DEBUG("mon=%p, fd=%d, dev_name=%p",
          mon, mon->fd, dev_name);
1509 1510

    if (mon->json)
1511
        ret = qemuMonitorJSONGetBlockExtent(mon, dev_name, extent);
1512
    else
1513
        ret = qemuMonitorTextGetBlockExtent(mon, dev_name, extent);
1514 1515 1516 1517

    return ret;
}

1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
int qemuMonitorBlockResize(qemuMonitorPtr mon,
                           const char *device,
                           unsigned long long size)
{
    int ret;
    VIR_DEBUG("mon=%p, fd=%d, devname=%p size=%llu",
              mon, mon->fd, device, size);

    if (mon->json)
        ret = qemuMonitorJSONBlockResize(mon, device, size);
    else
        ret = qemuMonitorTextBlockResize(mon, device, size);

    return ret;
}
1533 1534 1535 1536

int qemuMonitorSetVNCPassword(qemuMonitorPtr mon,
                              const char *password)
{
D
Daniel P. Berrange 已提交
1537
    int ret;
1538
    VIR_DEBUG("mon=%p, password=%p",
1539 1540 1541
          mon, password);

    if (!mon) {
1542 1543
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1544 1545
        return -1;
    }
1546

1547 1548 1549
    if (!password)
        password = "";

D
Daniel P. Berrange 已提交
1550 1551 1552 1553 1554
    if (mon->json)
        ret = qemuMonitorJSONSetVNCPassword(mon, password);
    else
        ret = qemuMonitorTextSetVNCPassword(mon, password);
    return ret;
1555 1556
}

1557 1558 1559 1560 1561 1562 1563 1564
static const char* qemuMonitorTypeToProtocol(int type)
{
    switch (type) {
    case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
        return "vnc";
    case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
        return "spice";
    default:
1565 1566 1567
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported protocol type %s"),
                       virDomainGraphicsTypeToString(type));
1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583
        return NULL;
    }
}

/* Returns -2 if not supported with this monitor connection */
int qemuMonitorSetPassword(qemuMonitorPtr mon,
                           int type,
                           const char *password,
                           const char *action_if_connected)
{
    const char *protocol = qemuMonitorTypeToProtocol(type);
    int ret;

    if (!protocol)
        return -1;

1584
    VIR_DEBUG("mon=%p, protocol=%s, password=%p, action_if_connected=%s",
1585 1586 1587
          mon, protocol, password, action_if_connected);

    if (!mon) {
1588 1589
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
        return -1;
    }

    if (!password)
        password = "";

    if (!action_if_connected)
        action_if_connected = "keep";

    if (mon->json)
        ret = qemuMonitorJSONSetPassword(mon, protocol, password, action_if_connected);
    else
        ret = qemuMonitorTextSetPassword(mon, protocol, password, action_if_connected);
    return ret;
}

int qemuMonitorExpirePassword(qemuMonitorPtr mon,
                              int type,
                              const char *expire_time)
{
    const char *protocol = qemuMonitorTypeToProtocol(type);
    int ret;

    if (!protocol)
        return -1;

1616
    VIR_DEBUG("mon=%p, protocol=%s, expire_time=%s",
1617 1618 1619
          mon, protocol, expire_time);

    if (!mon) {
1620 1621
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633
        return -1;
    }

    if (!expire_time)
        expire_time = "now";

    if (mon->json)
        ret = qemuMonitorJSONExpirePassword(mon, protocol, expire_time);
    else
        ret = qemuMonitorTextExpirePassword(mon, protocol, expire_time);
    return ret;
}
1634 1635 1636 1637

int qemuMonitorSetBalloon(qemuMonitorPtr mon,
                          unsigned long newmem)
{
D
Daniel P. Berrange 已提交
1638
    int ret;
1639
    VIR_DEBUG("mon=%p newmem=%lu", mon, newmem);
1640 1641

    if (!mon) {
1642 1643
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1644 1645
        return -1;
    }
1646

D
Daniel P. Berrange 已提交
1647 1648 1649 1650 1651
    if (mon->json)
        ret = qemuMonitorJSONSetBalloon(mon, newmem);
    else
        ret = qemuMonitorTextSetBalloon(mon, newmem);
    return ret;
1652 1653
}

1654 1655 1656 1657

int qemuMonitorSetCPU(qemuMonitorPtr mon, int cpu, int online)
{
    int ret;
1658
    VIR_DEBUG("mon=%p cpu=%d online=%d", mon, cpu, online);
1659 1660

    if (!mon) {
1661 1662
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1663 1664
        return -1;
    }
1665 1666 1667 1668 1669 1670 1671 1672 1673

    if (mon->json)
        ret = qemuMonitorJSONSetCPU(mon, cpu, online);
    else
        ret = qemuMonitorTextSetCPU(mon, cpu, online);
    return ret;
}


1674
int qemuMonitorEjectMedia(qemuMonitorPtr mon,
1675
                          const char *dev_name,
1676
                          bool force)
1677
{
D
Daniel P. Berrange 已提交
1678
    int ret;
1679
    VIR_DEBUG("mon=%p dev_name=%s force=%d", mon, dev_name, force);
1680 1681

    if (!mon) {
1682 1683
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1684 1685
        return -1;
    }
1686

D
Daniel P. Berrange 已提交
1687
    if (mon->json)
1688
        ret = qemuMonitorJSONEjectMedia(mon, dev_name, force);
D
Daniel P. Berrange 已提交
1689
    else
1690
        ret = qemuMonitorTextEjectMedia(mon, dev_name, force);
D
Daniel P. Berrange 已提交
1691
    return ret;
1692 1693 1694 1695
}


int qemuMonitorChangeMedia(qemuMonitorPtr mon,
1696
                           const char *dev_name,
1697 1698
                           const char *newmedia,
                           const char *format)
1699
{
D
Daniel P. Berrange 已提交
1700
    int ret;
1701 1702
    VIR_DEBUG("mon=%p dev_name=%s newmedia=%s format=%s",
          mon, dev_name, newmedia, format);
1703 1704

    if (!mon) {
1705 1706
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1707 1708
        return -1;
    }
1709

D
Daniel P. Berrange 已提交
1710
    if (mon->json)
1711
        ret = qemuMonitorJSONChangeMedia(mon, dev_name, newmedia, format);
D
Daniel P. Berrange 已提交
1712
    else
1713
        ret = qemuMonitorTextChangeMedia(mon, dev_name, newmedia, format);
D
Daniel P. Berrange 已提交
1714
    return ret;
1715 1716 1717 1718 1719 1720 1721 1722
}


int qemuMonitorSaveVirtualMemory(qemuMonitorPtr mon,
                                 unsigned long long offset,
                                 size_t length,
                                 const char *path)
{
D
Daniel P. Berrange 已提交
1723
    int ret;
1724
    VIR_DEBUG("mon=%p offset=%llu length=%zu path=%s",
1725 1726 1727
          mon, offset, length, path);

    if (!mon) {
1728 1729
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1730 1731
        return -1;
    }
1732

D
Daniel P. Berrange 已提交
1733 1734 1735 1736 1737
    if (mon->json)
        ret = qemuMonitorJSONSaveVirtualMemory(mon, offset, length, path);
    else
        ret = qemuMonitorTextSaveVirtualMemory(mon, offset, length, path);
    return ret;
1738 1739 1740 1741 1742 1743 1744
}

int qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon,
                                  unsigned long long offset,
                                  size_t length,
                                  const char *path)
{
D
Daniel P. Berrange 已提交
1745
    int ret;
1746
    VIR_DEBUG("mon=%p offset=%llu length=%zu path=%s",
1747 1748 1749
          mon, offset, length, path);

    if (!mon) {
1750 1751
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1752 1753
        return -1;
    }
1754

D
Daniel P. Berrange 已提交
1755 1756 1757 1758 1759
    if (mon->json)
        ret = qemuMonitorJSONSavePhysicalMemory(mon, offset, length, path);
    else
        ret = qemuMonitorTextSavePhysicalMemory(mon, offset, length, path);
    return ret;
1760 1761 1762 1763 1764 1765
}


int qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
                                 unsigned long bandwidth)
{
D
Daniel P. Berrange 已提交
1766
    int ret;
1767
    VIR_DEBUG("mon=%p bandwidth=%lu", mon, bandwidth);
1768 1769

    if (!mon) {
1770 1771
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1772 1773
        return -1;
    }
1774

D
Daniel P. Berrange 已提交
1775 1776 1777 1778 1779
    if (mon->json)
        ret = qemuMonitorJSONSetMigrationSpeed(mon, bandwidth);
    else
        ret = qemuMonitorTextSetMigrationSpeed(mon, bandwidth);
    return ret;
1780 1781
}

1782 1783 1784 1785 1786

int qemuMonitorSetMigrationDowntime(qemuMonitorPtr mon,
                                    unsigned long long downtime)
{
    int ret;
1787
    VIR_DEBUG("mon=%p downtime=%llu", mon, downtime);
1788 1789

    if (!mon) {
1790 1791
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1792 1793
        return -1;
    }
1794 1795 1796 1797 1798 1799 1800 1801 1802

    if (mon->json)
        ret = qemuMonitorJSONSetMigrationDowntime(mon, downtime);
    else
        ret = qemuMonitorTextSetMigrationDowntime(mon, downtime);
    return ret;
}


1803 1804 1805 1806 1807 1808
int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
                                  int *status,
                                  unsigned long long *transferred,
                                  unsigned long long *remaining,
                                  unsigned long long *total)
{
D
Daniel P. Berrange 已提交
1809
    int ret;
1810
    VIR_DEBUG("mon=%p", mon);
1811 1812

    if (!mon) {
1813 1814
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1815 1816
        return -1;
    }
1817

D
Daniel P. Berrange 已提交
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828
    if (mon->json)
        ret = qemuMonitorJSONGetMigrationStatus(mon, status,
                                                transferred,
                                                remaining,
                                                total);
    else
        ret = qemuMonitorTextGetMigrationStatus(mon, status,
                                                transferred,
                                                remaining,
                                                total);
    return ret;
1829 1830 1831
}


1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon,
                                       bool *spice_migrated)
{
    int ret;
    VIR_DEBUG("mon=%p", mon);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (mon->json) {
        ret = qemuMonitorJSONGetSpiceMigrationStatus(mon, spice_migrated);
    } else {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("JSON monitor is required"));
        return -1;
    }

    return ret;
}


E
Eric Blake 已提交
1856 1857 1858 1859 1860
int qemuMonitorMigrateToFd(qemuMonitorPtr mon,
                           unsigned int flags,
                           int fd)
{
    int ret;
1861
    VIR_DEBUG("mon=%p fd=%d flags=%x",
E
Eric Blake 已提交
1862 1863 1864
          mon, fd, flags);

    if (!mon) {
1865 1866
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
E
Eric Blake 已提交
1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879
        return -1;
    }

    if (qemuMonitorSendFileHandle(mon, "migrate", fd) < 0)
        return -1;

    if (mon->json)
        ret = qemuMonitorJSONMigrate(mon, flags, "fd:migrate");
    else
        ret = qemuMonitorTextMigrate(mon, flags, "fd:migrate");

    if (ret < 0) {
        if (qemuMonitorCloseFileHandle(mon, "migrate") < 0)
1880
            VIR_WARN("failed to close migration handle");
E
Eric Blake 已提交
1881 1882 1883 1884 1885 1886
    }

    return ret;
}


1887
int qemuMonitorMigrateToHost(qemuMonitorPtr mon,
1888
                             unsigned int flags,
1889 1890 1891
                             const char *hostname,
                             int port)
{
D
Daniel P. Berrange 已提交
1892
    int ret;
1893
    char *uri = NULL;
1894
    VIR_DEBUG("mon=%p hostname=%s port=%d flags=%x",
1895
          mon, hostname, port, flags);
1896 1897

    if (!mon) {
1898 1899
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1900 1901
        return -1;
    }
1902

1903 1904 1905 1906 1907 1908

    if (virAsprintf(&uri, "tcp:%s:%d", hostname, port) < 0) {
        virReportOOMError();
        return -1;
    }

D
Daniel P. Berrange 已提交
1909
    if (mon->json)
1910
        ret = qemuMonitorJSONMigrate(mon, flags, uri);
D
Daniel P. Berrange 已提交
1911
    else
1912 1913 1914
        ret = qemuMonitorTextMigrate(mon, flags, uri);

    VIR_FREE(uri);
D
Daniel P. Berrange 已提交
1915
    return ret;
1916 1917 1918 1919
}


int qemuMonitorMigrateToCommand(qemuMonitorPtr mon,
1920
                                unsigned int flags,
1921
                                const char * const *argv)
1922
{
1923 1924 1925
    char *argstr;
    char *dest = NULL;
    int ret = -1;
1926
    VIR_DEBUG("mon=%p argv=%p flags=%x",
1927
          mon, argv, flags);
1928 1929

    if (!mon) {
1930 1931
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1932 1933
        return -1;
    }
1934

1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
    argstr = virArgvToString(argv);
    if (!argstr) {
        virReportOOMError();
        goto cleanup;
    }

    if (virAsprintf(&dest, "exec:%s", argstr) < 0) {
        virReportOOMError();
        goto cleanup;
    }

D
Daniel P. Berrange 已提交
1946
    if (mon->json)
1947
        ret = qemuMonitorJSONMigrate(mon, flags, dest);
D
Daniel P. Berrange 已提交
1948
    else
1949 1950 1951 1952 1953
        ret = qemuMonitorTextMigrate(mon, flags, dest);

cleanup:
    VIR_FREE(argstr);
    VIR_FREE(dest);
1954 1955 1956 1957
    return ret;
}

int qemuMonitorMigrateToFile(qemuMonitorPtr mon,
1958
                             unsigned int flags,
1959 1960 1961 1962
                             const char * const *argv,
                             const char *target,
                             unsigned long long offset)
{
1963 1964 1965 1966
    char *argstr;
    char *dest = NULL;
    int ret = -1;
    char *safe_target = NULL;
1967
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1968
    VIR_DEBUG("mon=%p argv=%p target=%s offset=%llu flags=%x",
1969
          mon, argv, target, offset, flags);
1970 1971

    if (!mon) {
1972 1973
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
1974 1975
        return -1;
    }
1976 1977

    if (offset % QEMU_MONITOR_MIGRATE_TO_FILE_BS) {
1978 1979 1980
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("file offset must be a multiple of %llu"),
                       QEMU_MONITOR_MIGRATE_TO_FILE_BS);
1981 1982 1983
        return -1;
    }

1984 1985 1986 1987 1988 1989 1990
    argstr = virArgvToString(argv);
    if (!argstr) {
        virReportOOMError();
        goto cleanup;
    }

    /* Migrate to file */
1991 1992
    virBufferEscapeShell(&buf, target);
    if (virBufferError(&buf)) {
1993
        virReportOOMError();
1994
        virBufferFreeAndReset(&buf);
1995 1996
        goto cleanup;
    }
1997
    safe_target = virBufferContentAndReset(&buf);
1998 1999 2000 2001 2002 2003 2004

    /* Two dd processes, sharing the same stdout, are necessary to
     * allow starting at an alignment of 512, but without wasting
     * padding to get to the larger alignment useful for speed.  Use
     * <> redirection to avoid truncating a regular file.  */
    if (virAsprintf(&dest, "exec:" VIR_WRAPPER_SHELL_PREFIX "%s | "
                    "{ dd bs=%llu seek=%llu if=/dev/null && "
2005
                    "dd ibs=%llu obs=%llu; } 1<>%s" VIR_WRAPPER_SHELL_SUFFIX,
2006 2007 2008
                    argstr, QEMU_MONITOR_MIGRATE_TO_FILE_BS,
                    offset / QEMU_MONITOR_MIGRATE_TO_FILE_BS,
                    QEMU_MONITOR_MIGRATE_TO_FILE_TRANSFER_SIZE,
2009
                    QEMU_MONITOR_MIGRATE_TO_FILE_TRANSFER_SIZE,
2010 2011 2012 2013 2014
                    safe_target) < 0) {
        virReportOOMError();
        goto cleanup;
    }

2015
    if (mon->json)
2016
        ret = qemuMonitorJSONMigrate(mon, flags, dest);
2017
    else
2018 2019 2020 2021 2022 2023
        ret = qemuMonitorTextMigrate(mon, flags, dest);

cleanup:
    VIR_FREE(safe_target);
    VIR_FREE(argstr);
    VIR_FREE(dest);
D
Daniel P. Berrange 已提交
2024
    return ret;
2025 2026 2027
}

int qemuMonitorMigrateToUnix(qemuMonitorPtr mon,
2028
                             unsigned int flags,
2029 2030
                             const char *unixfile)
{
2031 2032
    char *dest = NULL;
    int ret = -1;
2033
    VIR_DEBUG("mon=%p, unixfile=%s flags=%x",
2034
          mon, unixfile, flags);
2035 2036

    if (!mon) {
2037 2038
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2039 2040
        return -1;
    }
2041

2042 2043 2044 2045 2046
    if (virAsprintf(&dest, "unix:%s", unixfile) < 0) {
        virReportOOMError();
        return -1;
    }

D
Daniel P. Berrange 已提交
2047
    if (mon->json)
2048
        ret = qemuMonitorJSONMigrate(mon, flags, dest);
D
Daniel P. Berrange 已提交
2049
    else
2050 2051 2052
        ret = qemuMonitorTextMigrate(mon, flags, dest);

    VIR_FREE(dest);
D
Daniel P. Berrange 已提交
2053
    return ret;
2054 2055 2056 2057
}

int qemuMonitorMigrateCancel(qemuMonitorPtr mon)
{
D
Daniel P. Berrange 已提交
2058
    int ret;
2059
    VIR_DEBUG("mon=%p", mon);
2060 2061

    if (!mon) {
2062 2063
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2064 2065
        return -1;
    }
2066

D
Daniel P. Berrange 已提交
2067 2068 2069 2070 2071
    if (mon->json)
        ret = qemuMonitorJSONMigrateCancel(mon);
    else
        ret = qemuMonitorTextMigrateCancel(mon);
    return ret;
2072 2073
}

2074 2075
int
qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd)
2076 2077
{
    int ret;
2078
    VIR_DEBUG("mon=%p fd=%d", mon, fd);
2079 2080

    if (!mon) {
2081 2082
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2083 2084 2085 2086 2087 2088 2089
        return -1;
    }

    if (!mon->json) {
        /* We don't have qemuMonitorTextDump(), so we should check mon->json
         * here.
         */
2090 2091
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
                       _("dump-guest-memory is not supported in text mode"));
2092 2093 2094 2095 2096 2097
        return -1;
    }

    if (qemuMonitorSendFileHandle(mon, "dump", fd) < 0)
        return -1;

2098
    ret = qemuMonitorJSONDump(mon, "fd:dump");
2099 2100 2101 2102 2103 2104 2105 2106

    if (ret < 0) {
        if (qemuMonitorCloseFileHandle(mon, "dump") < 0)
            VIR_WARN("failed to close dumping handle");
    }

    return ret;
}
2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137

int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
                                int type,
                                const char *hostname,
                                int port,
                                int tlsPort,
                                const char *tlsSubject)
{
    int ret;
    VIR_DEBUG("mon=%p type=%d hostname=%s port=%d tlsPort=%d tlsSubject=%s",
              mon, type, hostname, port, tlsPort, NULLSTR(tlsSubject));

    if (mon->json)
        ret = qemuMonitorJSONGraphicsRelocate(mon,
                                              type,
                                              hostname,
                                              port,
                                              tlsPort,
                                              tlsSubject);
    else
        ret = qemuMonitorTextGraphicsRelocate(mon,
                                              type,
                                              hostname,
                                              port,
                                              tlsPort,
                                              tlsSubject);

    return ret;
}


2138 2139 2140
int qemuMonitorAddUSBDisk(qemuMonitorPtr mon,
                          const char *path)
{
D
Daniel P. Berrange 已提交
2141
    int ret;
2142
    VIR_DEBUG("mon=%p path=%s", mon, path);
2143 2144

    if (!mon) {
2145 2146
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2147 2148
        return -1;
    }
2149

D
Daniel P. Berrange 已提交
2150 2151 2152 2153 2154
    if (mon->json)
        ret = qemuMonitorJSONAddUSBDisk(mon, path);
    else
        ret = qemuMonitorTextAddUSBDisk(mon, path);
    return ret;
2155 2156 2157 2158 2159 2160 2161
}


int qemuMonitorAddUSBDeviceExact(qemuMonitorPtr mon,
                                 int bus,
                                 int dev)
{
D
Daniel P. Berrange 已提交
2162
    int ret;
2163
    VIR_DEBUG("mon=%p bus=%d dev=%d", mon, bus, dev);
2164 2165

    if (!mon) {
2166 2167
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2168 2169
        return -1;
    }
2170

D
Daniel P. Berrange 已提交
2171 2172 2173 2174 2175
    if (mon->json)
        ret = qemuMonitorJSONAddUSBDeviceExact(mon, bus, dev);
    else
        ret = qemuMonitorTextAddUSBDeviceExact(mon, bus, dev);
    return ret;
2176 2177 2178 2179 2180 2181
}

int qemuMonitorAddUSBDeviceMatch(qemuMonitorPtr mon,
                                 int vendor,
                                 int product)
{
D
Daniel P. Berrange 已提交
2182
    int ret;
2183
    VIR_DEBUG("mon=%p vendor=%d product=%d",
2184 2185 2186
          mon, vendor, product);

    if (!mon) {
2187 2188
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2189 2190
        return -1;
    }
2191

D
Daniel P. Berrange 已提交
2192 2193 2194 2195 2196
    if (mon->json)
        ret = qemuMonitorJSONAddUSBDeviceMatch(mon, vendor, product);
    else
        ret = qemuMonitorTextAddUSBDeviceMatch(mon, vendor, product);
    return ret;
2197 2198 2199 2200
}


int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon,
2201 2202
                                virDevicePCIAddress *hostAddr,
                                virDevicePCIAddress *guestAddr)
2203
{
D
Daniel P. Berrange 已提交
2204
    int ret;
2205
    VIR_DEBUG("mon=%p domain=%d bus=%d slot=%d function=%d",
2206
          mon,
2207
          hostAddr->domain, hostAddr->bus, hostAddr->slot, hostAddr->function);
2208

2209
    if (!mon) {
2210 2211
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2212 2213 2214
        return -1;
    }

D
Daniel P. Berrange 已提交
2215
    if (mon->json)
2216
        ret = qemuMonitorJSONAddPCIHostDevice(mon, hostAddr, guestAddr);
D
Daniel P. Berrange 已提交
2217
    else
2218
        ret = qemuMonitorTextAddPCIHostDevice(mon, hostAddr, guestAddr);
D
Daniel P. Berrange 已提交
2219
    return ret;
2220 2221 2222 2223 2224 2225
}


int qemuMonitorAddPCIDisk(qemuMonitorPtr mon,
                          const char *path,
                          const char *bus,
2226
                          virDevicePCIAddress *guestAddr)
2227
{
D
Daniel P. Berrange 已提交
2228
    int ret;
2229
    VIR_DEBUG("mon=%p path=%s bus=%s",
2230 2231 2232
          mon, path, bus);

    if (!mon) {
2233 2234
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2235 2236
        return -1;
    }
2237

D
Daniel P. Berrange 已提交
2238
    if (mon->json)
2239
        ret = qemuMonitorJSONAddPCIDisk(mon, path, bus, guestAddr);
D
Daniel P. Berrange 已提交
2240
    else
2241
        ret = qemuMonitorTextAddPCIDisk(mon, path, bus, guestAddr);
D
Daniel P. Berrange 已提交
2242
    return ret;
2243 2244 2245 2246 2247
}


int qemuMonitorAddPCINetwork(qemuMonitorPtr mon,
                             const char *nicstr,
2248
                             virDevicePCIAddress *guestAddr)
2249
{
D
Daniel P. Berrange 已提交
2250
    int ret;
2251
    VIR_DEBUG("mon=%p nicstr=%s", mon, nicstr);
2252 2253

    if (!mon) {
2254 2255
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2256 2257
        return -1;
    }
2258

D
Daniel P. Berrange 已提交
2259
    if (mon->json)
2260
        ret = qemuMonitorJSONAddPCINetwork(mon, nicstr, guestAddr);
D
Daniel P. Berrange 已提交
2261
    else
2262
        ret = qemuMonitorTextAddPCINetwork(mon, nicstr, guestAddr);
D
Daniel P. Berrange 已提交
2263
    return ret;
2264 2265 2266 2267
}


int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon,
2268
                               virDevicePCIAddress *guestAddr)
2269
{
D
Daniel P. Berrange 已提交
2270
    int ret;
2271
    VIR_DEBUG("mon=%p domain=%d bus=%d slot=%d function=%d",
2272
          mon, guestAddr->domain, guestAddr->bus,
2273
          guestAddr->slot, guestAddr->function);
2274

2275
    if (!mon) {
2276 2277
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2278 2279 2280
        return -1;
    }

D
Daniel P. Berrange 已提交
2281
    if (mon->json)
2282
        ret = qemuMonitorJSONRemovePCIDevice(mon, guestAddr);
D
Daniel P. Berrange 已提交
2283
    else
2284
        ret = qemuMonitorTextRemovePCIDevice(mon, guestAddr);
D
Daniel P. Berrange 已提交
2285
    return ret;
2286 2287 2288 2289 2290 2291 2292
}


int qemuMonitorSendFileHandle(qemuMonitorPtr mon,
                              const char *fdname,
                              int fd)
{
D
Daniel P. Berrange 已提交
2293
    int ret;
2294
    VIR_DEBUG("mon=%p, fdname=%s fd=%d",
2295 2296 2297
          mon, fdname, fd);

    if (!mon) {
2298 2299
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2300 2301
        return -1;
    }
2302

2303
    if (fd < 0) {
2304 2305
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("fd must be valid"));
2306 2307 2308 2309
        return -1;
    }

    if (!mon->hasSendFD) {
2310
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
2311 2312
                       _("qemu is not using a unix socket monitor, "
                         "cannot send fd %s"), fdname);
2313 2314 2315
        return -1;
    }

D
Daniel P. Berrange 已提交
2316 2317 2318 2319 2320
    if (mon->json)
        ret = qemuMonitorJSONSendFileHandle(mon, fdname, fd);
    else
        ret = qemuMonitorTextSendFileHandle(mon, fdname, fd);
    return ret;
2321 2322 2323 2324 2325 2326
}


int qemuMonitorCloseFileHandle(qemuMonitorPtr mon,
                               const char *fdname)
{
2327 2328 2329
    int ret = -1;
    virErrorPtr error;

2330
    VIR_DEBUG("mon=%p fdname=%s",
2331 2332
          mon, fdname);

2333 2334
    error = virSaveLastError();

2335
    if (!mon) {
2336 2337
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2338
        goto cleanup;
2339
    }
2340

D
Daniel P. Berrange 已提交
2341 2342 2343 2344
    if (mon->json)
        ret = qemuMonitorJSONCloseFileHandle(mon, fdname);
    else
        ret = qemuMonitorTextCloseFileHandle(mon, fdname);
2345 2346 2347 2348 2349 2350

cleanup:
    if (error) {
        virSetError(error);
        virFreeError(error);
    }
D
Daniel P. Berrange 已提交
2351
    return ret;
2352 2353 2354
}


2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426
/* Add the open file descriptor FD into the non-negative set FDSET.
 * If NAME is present, it will be passed along for logging purposes.
 * Returns the counterpart fd that qemu received, or -1 on error.  */
int
qemuMonitorAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name)
{
    int ret = -1;
    VIR_DEBUG("mon=%p, fdset=%d, fd=%d, name=%s",
              mon, fdset, fd, NULLSTR(name));

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (fd < 0 || fdset < 0) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("fd and fdset must be valid"));
        return -1;
    }

    if (!mon->hasSendFD) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                       _("qemu is not using a unix socket monitor, "
                         "cannot send fd %s"), NULLSTR(name));
        return -1;
    }

    if (mon->json)
        ret = qemuMonitorJSONAddFd(mon, fdset, fd, name);
    else
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("add fd requires JSON monitor"));
    return ret;
}


/* Remove one of qemu's fds from the given FDSET, or if FD is
 * negative, remove the entire set.  Preserve any previous error on
 * entry.  Returns 0 on success, -1 on error.  */
int
qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd)
{
    int ret = -1;
    virErrorPtr error;

    VIR_DEBUG("mon=%p, fdset=%d, fd=%d", mon, fdset, fd);

    error = virSaveLastError();

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        goto cleanup;
    }

    if (mon->json)
        ret = qemuMonitorJSONRemoveFd(mon, fdset, fd);
    else
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("remove fd requires JSON monitor"));

cleanup:
    if (error) {
        virSetError(error);
        virFreeError(error);
    }
    return ret;
}


2427
int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
2428 2429 2430
                              const char *netstr,
                              int tapfd, const char *tapfd_name,
                              int vhostfd, const char *vhostfd_name)
2431
{
2432 2433 2434 2435 2436
    int ret = -1;
    VIR_DEBUG("mon=%p netstr=%s tapfd=%d tapfd_name=%s "
              "vhostfd=%d vhostfd_name=%s",
              mon, netstr, tapfd, NULLSTR(tapfd_name),
              vhostfd, NULLSTR(vhostfd_name));
2437 2438

    if (!mon) {
2439 2440
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2441 2442
        return -1;
    }
2443

2444 2445 2446 2447 2448 2449 2450 2451
    if (tapfd >= 0 && qemuMonitorSendFileHandle(mon, tapfd_name, tapfd) < 0)
        return -1;
    if (vhostfd >= 0 &&
        qemuMonitorSendFileHandle(mon, vhostfd_name, vhostfd) < 0) {
        vhostfd = -1;
        goto cleanup;
    }

D
Daniel P. Berrange 已提交
2452
    if (mon->json)
2453
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2454
                       _("JSON monitor should be using AddNetdev"));
D
Daniel P. Berrange 已提交
2455 2456
    else
        ret = qemuMonitorTextAddHostNetwork(mon, netstr);
2457 2458 2459 2460 2461 2462 2463 2464 2465

cleanup:
    if (ret < 0) {
        if (tapfd >= 0 && qemuMonitorCloseFileHandle(mon, tapfd_name) < 0)
            VIR_WARN("failed to close device handle '%s'", tapfd_name);
        if (vhostfd >= 0 && qemuMonitorCloseFileHandle(mon, vhostfd_name) < 0)
            VIR_WARN("failed to close device handle '%s'", vhostfd_name);
    }

D
Daniel P. Berrange 已提交
2466
    return ret;
2467 2468 2469 2470 2471 2472 2473
}


int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon,
                                 int vlan,
                                 const char *netname)
{
G
Guido Günther 已提交
2474
    int ret = -1;
2475
    VIR_DEBUG("mon=%p netname=%s",
2476 2477 2478
          mon, netname);

    if (!mon) {
2479 2480
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2481 2482
        return -1;
    }
2483

D
Daniel P. Berrange 已提交
2484
    if (mon->json)
2485
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2486
                       _("JSON monitor should be using RemoveNetdev"));
D
Daniel P. Berrange 已提交
2487 2488 2489
    else
        ret = qemuMonitorTextRemoveHostNetwork(mon, vlan, netname);
    return ret;
2490
}
2491

2492 2493

int qemuMonitorAddNetdev(qemuMonitorPtr mon,
2494 2495 2496
                         const char *netdevstr,
                         int tapfd, const char *tapfd_name,
                         int vhostfd, const char *vhostfd_name)
2497
{
2498 2499 2500 2501 2502
    int ret = -1;
    VIR_DEBUG("mon=%p netdevstr=%s tapfd=%d tapfd_name=%s "
              "vhostfd=%d vhostfd_name=%s",
              mon, netdevstr, tapfd, NULLSTR(tapfd_name),
              vhostfd, NULLSTR(vhostfd_name));
2503 2504

    if (!mon) {
2505 2506
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2507 2508
        return -1;
    }
2509

2510 2511 2512 2513 2514 2515 2516 2517
    if (tapfd >= 0 && qemuMonitorSendFileHandle(mon, tapfd_name, tapfd) < 0)
        return -1;
    if (vhostfd >= 0 &&
        qemuMonitorSendFileHandle(mon, vhostfd_name, vhostfd) < 0) {
        vhostfd = -1;
        goto cleanup;
    }

2518 2519 2520 2521
    if (mon->json)
        ret = qemuMonitorJSONAddNetdev(mon, netdevstr);
    else
        ret = qemuMonitorTextAddNetdev(mon, netdevstr);
2522 2523 2524 2525 2526 2527 2528 2529 2530

cleanup:
    if (ret < 0) {
        if (tapfd >= 0 && qemuMonitorCloseFileHandle(mon, tapfd_name) < 0)
            VIR_WARN("failed to close device handle '%s'", tapfd_name);
        if (vhostfd >= 0 && qemuMonitorCloseFileHandle(mon, vhostfd_name) < 0)
            VIR_WARN("failed to close device handle '%s'", vhostfd_name);
    }

2531 2532 2533 2534 2535 2536 2537
    return ret;
}

int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
                            const char *alias)
{
    int ret;
2538
    VIR_DEBUG("mon=%p alias=%s",
2539 2540 2541
          mon, alias);

    if (!mon) {
2542 2543
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2544 2545
        return -1;
    }
2546 2547 2548 2549 2550 2551 2552 2553 2554

    if (mon->json)
        ret = qemuMonitorJSONRemoveNetdev(mon, alias);
    else
        ret = qemuMonitorTextRemoveNetdev(mon, alias);
    return ret;
}


2555 2556 2557
int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
                           virHashTablePtr paths)
{
2558
    int ret;
2559
    VIR_DEBUG("mon=%p",
2560 2561 2562
          mon);

    if (!mon) {
2563 2564
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2565 2566
        return -1;
    }
2567

2568 2569 2570 2571 2572
    if (mon->json)
        ret = qemuMonitorJSONGetPtyPaths(mon, paths);
    else
        ret = qemuMonitorTextGetPtyPaths(mon, paths);
    return ret;
2573
}
2574 2575 2576 2577


int qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon,
                                       const char *bus,
2578
                                       virDevicePCIAddress *guestAddr)
2579
{
2580
    VIR_DEBUG("mon=%p type=%s", mon, bus);
2581 2582
    int ret;

2583
    if (!mon) {
2584 2585
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2586 2587 2588
        return -1;
    }

2589 2590 2591 2592 2593 2594 2595
    if (mon->json)
        ret = qemuMonitorJSONAttachPCIDiskController(mon, bus, guestAddr);
    else
        ret = qemuMonitorTextAttachPCIDiskController(mon, bus, guestAddr);

    return ret;
}
2596 2597 2598 2599


int qemuMonitorAttachDrive(qemuMonitorPtr mon,
                           const char *drivestr,
2600
                           virDevicePCIAddress *controllerAddr,
2601 2602
                           virDomainDeviceDriveAddress *driveAddr)
{
2603
    VIR_DEBUG("mon=%p drivestr=%s domain=%d bus=%d slot=%d function=%d",
2604
          mon, drivestr,
2605 2606
          controllerAddr->domain, controllerAddr->bus,
          controllerAddr->slot, controllerAddr->function);
G
Guido Günther 已提交
2607
    int ret = 1;
2608

2609
    if (!mon) {
2610 2611
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2612 2613 2614
        return -1;
    }

2615
    if (mon->json)
2616
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2617
                       _("JSON monitor should be using AddDrive"));
2618 2619 2620 2621 2622
    else
        ret = qemuMonitorTextAttachDrive(mon, drivestr, controllerAddr, driveAddr);

    return ret;
}
2623 2624 2625 2626

int qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon,
                                  qemuMonitorPCIAddress **addrs)
{
2627
    VIR_DEBUG("mon=%p addrs=%p", mon, addrs);
2628 2629
    int ret;

2630
    if (!mon) {
2631 2632
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2633 2634 2635
        return -1;
    }

2636 2637 2638 2639 2640 2641
    if (mon->json)
        ret = qemuMonitorJSONGetAllPCIAddresses(mon, addrs);
    else
        ret = qemuMonitorTextGetAllPCIAddresses(mon, addrs);
    return ret;
}
2642

2643 2644
int qemuMonitorDriveDel(qemuMonitorPtr mon,
                        const char *drivestr)
2645
{
2646
    VIR_DEBUG("mon=%p drivestr=%s", mon, drivestr);
2647 2648 2649
    int ret;

    if (!mon) {
2650 2651
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2652 2653 2654 2655
        return -1;
    }

    if (mon->json)
2656
        ret = qemuMonitorJSONDriveDel(mon, drivestr);
2657
    else
2658
        ret = qemuMonitorTextDriveDel(mon, drivestr);
2659 2660 2661
    return ret;
}

2662
int qemuMonitorDelDevice(qemuMonitorPtr mon,
2663
                         const char *devalias)
2664
{
2665
    VIR_DEBUG("mon=%p devalias=%s", mon, devalias);
2666 2667
    int ret;

2668
    if (!mon) {
2669 2670
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2671 2672 2673
        return -1;
    }

2674
    if (mon->json)
2675
        ret = qemuMonitorJSONDelDevice(mon, devalias);
2676
    else
2677
        ret = qemuMonitorTextDelDevice(mon, devalias);
2678 2679 2680
    return ret;
}

2681

2682 2683 2684 2685
int qemuMonitorAddDeviceWithFd(qemuMonitorPtr mon,
                               const char *devicestr,
                               int fd,
                               const char *fdname)
2686
{
2687 2688
    VIR_DEBUG("mon=%p device=%s fd=%d fdname=%s", mon, devicestr, fd,
              NULLSTR(fdname));
2689 2690
    int ret;

2691
    if (!mon) {
2692 2693
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2694 2695 2696
        return -1;
    }

2697 2698 2699
    if (fd >= 0 && qemuMonitorSendFileHandle(mon, fdname, fd) < 0)
        return -1;

2700 2701 2702 2703
    if (mon->json)
        ret = qemuMonitorJSONAddDevice(mon, devicestr);
    else
        ret = qemuMonitorTextAddDevice(mon, devicestr);
2704 2705 2706 2707 2708 2709

    if (ret < 0 && fd >= 0) {
        if (qemuMonitorCloseFileHandle(mon, fdname) < 0)
            VIR_WARN("failed to close device handle '%s'", fdname);
    }

2710 2711 2712
    return ret;
}

2713 2714 2715 2716 2717 2718
int qemuMonitorAddDevice(qemuMonitorPtr mon,
                         const char *devicestr)
{
    return qemuMonitorAddDeviceWithFd(mon, devicestr, -1, NULL);
}

2719 2720 2721
int qemuMonitorAddDrive(qemuMonitorPtr mon,
                        const char *drivestr)
{
2722
    VIR_DEBUG("mon=%p drive=%s", mon, drivestr);
2723 2724
    int ret;

2725
    if (!mon) {
2726 2727
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2728 2729 2730
        return -1;
    }

2731 2732 2733 2734 2735 2736
    if (mon->json)
        ret = qemuMonitorJSONAddDrive(mon, drivestr);
    else
        ret = qemuMonitorTextAddDrive(mon, drivestr);
    return ret;
}
2737 2738 2739 2740 2741 2742


int qemuMonitorSetDrivePassphrase(qemuMonitorPtr mon,
                                  const char *alias,
                                  const char *passphrase)
{
2743
    VIR_DEBUG("mon=%p alias=%s passphrase=%p(value hidden)", mon, alias, passphrase);
2744 2745
    int ret;

2746
    if (!mon) {
2747 2748
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2749 2750 2751
        return -1;
    }

2752 2753 2754 2755 2756 2757
    if (mon->json)
        ret = qemuMonitorJSONSetDrivePassphrase(mon, alias, passphrase);
    else
        ret = qemuMonitorTextSetDrivePassphrase(mon, alias, passphrase);
    return ret;
}
C
Chris Lalancette 已提交
2758 2759 2760 2761 2762

int qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name)
{
    int ret;

2763
    VIR_DEBUG("mon=%p, name=%s",mon,name);
C
Chris Lalancette 已提交
2764

2765
    if (!mon) {
2766 2767
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2768 2769 2770
        return -1;
    }

C
Chris Lalancette 已提交
2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781
    if (mon->json)
        ret = qemuMonitorJSONCreateSnapshot(mon, name);
    else
        ret = qemuMonitorTextCreateSnapshot(mon, name);
    return ret;
}

int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name)
{
    int ret;

2782
    VIR_DEBUG("mon=%p, name=%s",mon,name);
C
Chris Lalancette 已提交
2783

2784
    if (!mon) {
2785 2786
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2787 2788 2789
        return -1;
    }

C
Chris Lalancette 已提交
2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800
    if (mon->json)
        ret = qemuMonitorJSONLoadSnapshot(mon, name);
    else
        ret = qemuMonitorTextLoadSnapshot(mon, name);
    return ret;
}

int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name)
{
    int ret;

2801
    VIR_DEBUG("mon=%p, name=%s",mon,name);
C
Chris Lalancette 已提交
2802

2803
    if (!mon) {
2804 2805
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2806 2807 2808
        return -1;
    }

C
Chris Lalancette 已提交
2809 2810 2811 2812 2813 2814
    if (mon->json)
        ret = qemuMonitorJSONDeleteSnapshot(mon, name);
    else
        ret = qemuMonitorTextDeleteSnapshot(mon, name);
    return ret;
}
2815

2816 2817 2818 2819
/* Use the snapshot_blkdev command to convert the existing file for
 * device into a read-only backing file of a new qcow2 image located
 * at file.  */
int
2820
qemuMonitorDiskSnapshot(qemuMonitorPtr mon, virJSONValuePtr actions,
2821 2822
                        const char *device, const char *file,
                        const char *format, bool reuse)
2823
{
2824
    int ret = -1;
2825

2826 2827
    VIR_DEBUG("mon=%p, actions=%p, device=%s, file=%s, format=%s, reuse=%d",
              mon, actions, device, file, format, reuse);
2828 2829

    if (!mon) {
2830 2831
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
2832 2833 2834
        return -1;
    }

2835
    if (mon->json)
2836 2837
        ret = qemuMonitorJSONDiskSnapshot(mon, actions, device, file, format,
                                          reuse);
2838
    else
2839
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2840
                       _("disk snapshot requires JSON monitor"));
2841 2842 2843
    return ret;
}

2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871
/* Start a drive-mirror block job.  bandwidth is in MiB/sec.  */
int
qemuMonitorDriveMirror(qemuMonitorPtr mon,
                       const char *device, const char *file,
                       const char *format, unsigned long bandwidth,
                       unsigned int flags)
{
    int ret = -1;
    unsigned long long speed;

    VIR_DEBUG("mon=%p, device=%s, file=%s, format=%s, bandwidth=%ld, "
              "flags=%x",
              mon, device, file, NULLSTR(format), bandwidth, flags);

    /* Convert bandwidth MiB to bytes */
    speed = bandwidth;
    if (speed > ULLONG_MAX / 1024 / 1024) {
        virReportError(VIR_ERR_OVERFLOW,
                       _("bandwidth must be less than %llu"),
                       ULLONG_MAX / 1024 / 1024);
        return -1;
    }
    speed <<= 20;

    if (mon->json)
        ret = qemuMonitorJSONDriveMirror(mon, device, file, format, speed,
                                         flags);
    else
2872
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2873 2874 2875 2876
                       _("drive-mirror requires JSON monitor"));
    return ret;
}

2877 2878 2879 2880 2881 2882 2883 2884
/* Use the transaction QMP command to run atomic snapshot commands.  */
int
qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
{
    int ret = -1;

    VIR_DEBUG("mon=%p, actions=%p", mon, actions);

2885
    if (mon->json)
2886
        ret = qemuMonitorJSONTransaction(mon, actions);
2887
    else
2888
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2889
                       _("transaction requires JSON monitor"));
2890 2891 2892
    return ret;
}

2893
/* Start a block-commit block job.  bandwidth is in MiB/sec.  */
2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
int
qemuMonitorBlockCommit(qemuMonitorPtr mon, const char *device,
                       const char *top, const char *base,
                       unsigned long bandwidth)
{
    int ret = -1;
    unsigned long long speed;

    VIR_DEBUG("mon=%p, device=%s, top=%s, base=%s, bandwidth=%ld",
              mon, device, NULLSTR(top), NULLSTR(base), bandwidth);

    /* Convert bandwidth MiB to bytes */
    speed = bandwidth;
    if (speed > ULLONG_MAX / 1024 / 1024) {
        virReportError(VIR_ERR_OVERFLOW,
                       _("bandwidth must be less than %llu"),
                       ULLONG_MAX / 1024 / 1024);
        return -1;
    }
    speed <<= 20;

    if (mon->json)
        ret = qemuMonitorJSONBlockCommit(mon, device, top, base, speed);
    else
2918
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2919 2920 2921 2922
                       _("block-commit requires JSON monitor"));
    return ret;
}

2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936
/* Use the block-job-complete monitor command to pivot a block copy
 * job.  */
int
qemuMonitorDrivePivot(qemuMonitorPtr mon, const char *device,
                      const char *file, const char *format)
{
    int ret = -1;

    VIR_DEBUG("mon=%p, device=%s, file=%s, format=%s",
              mon, device, file, NULLSTR(format));

    if (mon->json)
        ret = qemuMonitorJSONDrivePivot(mon, device, file, format);
    else
2937
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2938 2939 2940 2941
                       _("drive pivot requires JSON monitor"));
    return ret;
}

2942 2943 2944 2945
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
                                const char *cmd,
                                char **reply,
                                bool hmp)
2946 2947 2948
{
    int ret;

2949
    VIR_DEBUG("mon=%p, cmd=%s, reply=%p, hmp=%d", mon, cmd, reply, hmp);
2950 2951

    if (mon->json)
2952
        ret = qemuMonitorJSONArbitraryCommand(mon, cmd, reply, hmp);
2953 2954 2955 2956
    else
        ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply);
    return ret;
}
2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970


int qemuMonitorInjectNMI(qemuMonitorPtr mon)
{
    int ret;

    VIR_DEBUG("mon=%p", mon);

    if (mon->json)
        ret = qemuMonitorJSONInjectNMI(mon);
    else
        ret = qemuMonitorTextInjectNMI(mon);
    return ret;
}
2971

2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988
int qemuMonitorSendKey(qemuMonitorPtr mon,
                       unsigned int holdtime,
                       unsigned int *keycodes,
                       unsigned int nkeycodes)
{
    int ret;

    VIR_DEBUG("mon=%p, holdtime=%u, nkeycodes=%u",
              mon, holdtime, nkeycodes);

    if (mon->json)
        ret = qemuMonitorJSONSendKey(mon, holdtime, keycodes, nkeycodes);
    else
        ret = qemuMonitorTextSendKey(mon, holdtime, keycodes, nkeycodes);
    return ret;
}

2989 2990 2991 2992 2993 2994 2995 2996
int qemuMonitorScreendump(qemuMonitorPtr mon,
                          const char *file)
{
    int ret;

    VIR_DEBUG("mon=%p, file=%s", mon, file);

    if (!mon) {
2997 2998
        virReportError(VIR_ERR_INVALID_ARG,"%s",
                       _("monitor must not be NULL"));
2999 3000 3001 3002 3003 3004 3005 3006 3007
        return -1;
    }

    if (mon->json)
        ret = qemuMonitorJSONScreendump(mon, file);
    else
        ret = qemuMonitorTextScreendump(mon, file);
    return ret;
}
3008

3009
/* bandwidth is in MiB/sec */
3010 3011
int qemuMonitorBlockJob(qemuMonitorPtr mon,
                        const char *device,
3012
                        const char *base,
3013 3014
                        unsigned long bandwidth,
                        virDomainBlockJobInfoPtr info,
3015 3016
                        qemuMonitorBlockJobCmd mode,
                        bool modern)
3017
{
E
Eric Blake 已提交
3018
    int ret = -1;
3019
    unsigned long long speed;
3020

3021 3022 3023 3024 3025
    VIR_DEBUG("mon=%p, device=%s, base=%s, bandwidth=%luM, info=%p, mode=%o, "
              "modern=%d", mon, device, NULLSTR(base), bandwidth, info, mode,
              modern);

    /* Convert bandwidth MiB to bytes */
3026 3027
    speed = bandwidth;
    if (speed > ULLONG_MAX / 1024 / 1024) {
3028 3029 3030
        virReportError(VIR_ERR_OVERFLOW,
                       _("bandwidth must be less than %llu"),
                       ULLONG_MAX / 1024 / 1024);
3031 3032
        return -1;
    }
3033
    speed <<= 20;
3034 3035

    if (mon->json)
3036 3037
        ret = qemuMonitorJSONBlockJob(mon, device, base, speed, info, mode,
                                      modern);
3038
    else
3039
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3040
                       _("block jobs require JSON monitor"));
3041 3042
    return ret;
}
3043

3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076
int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
                                  const char *device,
                                  virDomainBlockIoTuneInfoPtr info)
{
    int ret;

    VIR_DEBUG("mon=%p, device=%p, info=%p", mon, device, info);

    if (mon->json) {
        ret = qemuMonitorJSONSetBlockIoThrottle(mon, device, info);
    } else {
        ret = qemuMonitorTextSetBlockIoThrottle(mon, device, info);
    }
    return ret;
}

int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
                                  const char *device,
                                  virDomainBlockIoTuneInfoPtr reply)
{
    int ret;

    VIR_DEBUG("mon=%p, device=%p, reply=%p", mon, device, reply);

    if (mon->json) {
        ret = qemuMonitorJSONGetBlockIoThrottle(mon, device, reply);
    } else {
        ret = qemuMonitorTextGetBlockIoThrottle(mon, device, reply);
    }
    return ret;
}


3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125
int qemuMonitorVMStatusToPausedReason(const char *status)
{
    int st;

    if (!status)
        return VIR_DOMAIN_PAUSED_UNKNOWN;

    if ((st = qemuMonitorVMStatusTypeFromString(status)) < 0) {
        VIR_WARN("Qemu reported unknown VM status: '%s'", status);
        return VIR_DOMAIN_PAUSED_UNKNOWN;
    }

    switch ((qemuMonitorVMStatus) st) {
    case QEMU_MONITOR_VM_STATUS_DEBUG:
    case QEMU_MONITOR_VM_STATUS_INTERNAL_ERROR:
    case QEMU_MONITOR_VM_STATUS_RESTORE_VM:
        return VIR_DOMAIN_PAUSED_UNKNOWN;

    case QEMU_MONITOR_VM_STATUS_INMIGRATE:
    case QEMU_MONITOR_VM_STATUS_POSTMIGRATE:
    case QEMU_MONITOR_VM_STATUS_FINISH_MIGRATE:
        return VIR_DOMAIN_PAUSED_MIGRATION;

    case QEMU_MONITOR_VM_STATUS_IO_ERROR:
        return VIR_DOMAIN_PAUSED_IOERROR;

    case QEMU_MONITOR_VM_STATUS_PAUSED:
    case QEMU_MONITOR_VM_STATUS_PRELAUNCH:
        return VIR_DOMAIN_PAUSED_USER;

    case QEMU_MONITOR_VM_STATUS_RUNNING:
        VIR_WARN("Qemu reports the guest is paused but status is 'running'");
        return VIR_DOMAIN_PAUSED_UNKNOWN;

    case QEMU_MONITOR_VM_STATUS_SAVE_VM:
        return VIR_DOMAIN_PAUSED_SAVE;

    case QEMU_MONITOR_VM_STATUS_SHUTDOWN:
        return VIR_DOMAIN_PAUSED_SHUTTING_DOWN;

    case QEMU_MONITOR_VM_STATUS_WATCHDOG:
        return VIR_DOMAIN_PAUSED_WATCHDOG;

    /* unreachable from this point on */
    case QEMU_MONITOR_VM_STATUS_LAST:
        ;
    }
    return VIR_DOMAIN_PAUSED_UNKNOWN;
}
3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138


int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
                            const char *protocol,
                            int fd,
                            const char *fdname,
                            bool skipauth)
{
    VIR_DEBUG("mon=%p protocol=%s fd=%d fdname=%s skipauth=%d",
              mon, protocol, fd, NULLSTR(fdname), skipauth);
    int ret;

    if (!mon) {
3139 3140
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158
        return -1;
    }

    if (qemuMonitorSendFileHandle(mon, fdname, fd) < 0)
        return -1;

    if (mon->json)
        ret = qemuMonitorJSONOpenGraphics(mon, protocol, fdname, skipauth);
    else
        ret = qemuMonitorTextOpenGraphics(mon, protocol, fdname, skipauth);

    if (ret < 0) {
        if (qemuMonitorCloseFileHandle(mon, fdname) < 0)
            VIR_WARN("failed to close device handle '%s'", fdname);
    }

    return ret;
}
3159 3160 3161 3162 3163 3164

int qemuMonitorSystemWakeup(qemuMonitorPtr mon)
{
    VIR_DEBUG("mon=%p", mon);

    if (!mon) {
3165 3166
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
3167 3168 3169 3170
        return -1;
    }

    if (!mon->json) {
3171
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3172
                       _("JSON monitor is required"));
3173 3174 3175 3176 3177
        return -1;
    }

    return qemuMonitorJSONSystemWakeup(mon);
}
3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194

int qemuMonitorGetVersion(qemuMonitorPtr mon,
                          int *major,
                          int *minor,
                          int *micro,
                          char **package)
{
    VIR_DEBUG("mon=%p major=%p minor=%p micro=%p package=%p",
              mon, major, minor, micro, package);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3195
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3196 3197 3198 3199 3200 3201
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetVersion(mon, major, minor, micro, package);
}
3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215

int qemuMonitorGetMachines(qemuMonitorPtr mon,
                           qemuMonitorMachineInfoPtr **machines)
{
    VIR_DEBUG("mon=%p machines=%p",
              mon, machines);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3216
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetMachines(mon, machines);
}

void qemuMonitorMachineInfoFree(qemuMonitorMachineInfoPtr machine)
{
    if (!machine)
        return;
    VIR_FREE(machine->name);
    VIR_FREE(machine->alias);
    VIR_FREE(machine);
}
3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245

int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
                                 char ***cpus)
{
    VIR_DEBUG("mon=%p cpus=%p",
              mon, cpus);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3246
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3247 3248 3249 3250 3251 3252
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetCPUDefinitions(mon, cpus);
}
3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267


int qemuMonitorGetCommands(qemuMonitorPtr mon,
                           char ***commands)
{
    VIR_DEBUG("mon=%p commands=%p",
              mon, commands);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3268
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3269 3270 3271 3272 3273 3274
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetCommands(mon, commands);
}
3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289


int qemuMonitorGetEvents(qemuMonitorPtr mon,
                         char ***events)
{
    VIR_DEBUG("mon=%p events=%p",
              mon, events);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3290
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3291 3292 3293 3294 3295 3296
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetEvents(mon, events);
}
3297 3298


3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312
int qemuMonitorGetKVMState(qemuMonitorPtr mon,
                           bool *enabled,
                           bool *present)
{
    VIR_DEBUG("mon=%p enabled=%p present=%p",
              mon, enabled, present);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3313
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3314 3315 3316 3317 3318 3319 3320 3321
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetKVMState(mon, enabled, present);
}


3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334
int qemuMonitorGetObjectTypes(qemuMonitorPtr mon,
                              char ***types)
{
    VIR_DEBUG("mon=%p types=%p",
              mon, types);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3335
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3336 3337 3338 3339 3340 3341
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetObjectTypes(mon, types);
}
3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357


int qemuMonitorGetObjectProps(qemuMonitorPtr mon,
                              const char *type,
                              char ***props)
{
    VIR_DEBUG("mon=%p type=%s props=%p",
              mon, type, props);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return -1;
    }

    if (!mon->json) {
3358
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3359 3360 3361 3362 3363 3364
                       _("JSON monitor is required"));
        return -1;
    }

    return qemuMonitorJSONGetObjectProps(mon, type, props);
}
3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378


char *qemuMonitorGetTargetArch(qemuMonitorPtr mon)
{
    VIR_DEBUG("mon=%p",
              mon);

    if (!mon) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("monitor must not be NULL"));
        return NULL;
    }

    if (!mon->json) {
3379
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3380 3381 3382 3383 3384 3385
                       _("JSON monitor is required"));
        return NULL;
    }

    return qemuMonitorJSONGetTargetArch(mon);
}