qemu_monitor_text.c 71.0 KB
Newer Older
1 2 3
/*
 * qemu_monitor_text.c: interaction with QEMU monitor console
 *
4
 * Copyright (C) 2006-2014 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
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <poll.h>
#include <unistd.h>
31
#include <string.h>
32 33

#include "qemu_monitor_text.h"
34
#include "qemu_command.h"
35
#include "c-ctype.h"
36
#include "c-strcasestr.h"
37
#include "viralloc.h"
38
#include "virlog.h"
39 40
#include "driver.h"
#include "datatypes.h"
41
#include "virerror.h"
42
#include "virbuffer.h"
43
#include "virprobe.h"
44
#include "virstring.h"
45

46 47 48 49
#ifdef WITH_DTRACE_PROBES
# include "libvirt_qemu_probes.h"
#endif

50 51
#define VIR_FROM_THIS VIR_FROM_QEMU

52 53
VIR_LOG_INIT("qemu.qemu_monitor_text");

54 55
#define DEBUG_IO 0

56
/* Return -1 for error, 0 for success */
57
typedef int qemuMonitorExtraPromptHandler(qemuMonitorPtr mon,
58 59 60 61 62
                                          const char *buf,
                                          const char *prompt,
                                          void *data);


63 64 65 66 67
/* When connecting to a monitor, QEMU will print a greeting like
 *
 * QEMU 0.11.0 monitor - type 'help' for more information
 *
 * Don't expect the version number bit to be stable :-)
68
 */
69 70 71 72 73 74 75 76 77 78
#define GREETING_PREFIX "QEMU "
#define GREETING_POSTFIX "type 'help' for more information\r\n(qemu) "
#define BASIC_PROMPT "(qemu) "
#define PASSWORD_PROMPT "Password:"
#define DISK_ENCRYPTION_PREFIX "("
#define DISK_ENCRYPTION_POSTFIX ") is encrypted."
#define LINE_ENDING "\r\n"

int qemuMonitorTextIOProcess(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                             const char *data,
79
                             size_t len ATTRIBUTE_UNUSED,
80 81 82
                             qemuMonitorMessagePtr msg)
{
    int used = 0;
83

84 85 86
    /* Check for & discard greeting */
    if (STRPREFIX(data, GREETING_PREFIX)) {
        const char *offset = strstr(data, GREETING_POSTFIX);
87

88 89 90
        /* We see the greeting prefix, but not postfix, so pretend we've
           not consumed anything. We'll restart when more data arrives. */
        if (!offset) {
91
#if DEBUG_IO
92
            VIR_DEBUG("Partial greeting seen, getting out & waiting for more");
93
#endif
94 95
            return 0;
        }
96

97 98
        used = offset - data + strlen(GREETING_POSTFIX);

99
#if DEBUG_IO
100
        VIR_DEBUG("Discarded monitor greeting");
101
#endif
102
    }
103

104 105
    /* Don't print raw data in debug because its full of control chars */
    /*VIR_DEBUG("Process data %d byts of data [%s]", len - used, data + used);*/
106
#if DEBUG_IO
107
    VIR_DEBUG("Process data %d byts of data", (int)(len - used));
108
#endif
109 110 111

    /* Look for a non-zero reply followed by prompt */
    if (msg && !msg->finished) {
112 113 114 115 116 117 118 119 120 121 122
        char *start = NULL;
        char *end = NULL;
        char *skip;

        /* If we're here, we've already sent the command. We now
         * strip the trailing '\r' because it makes the matching
         * code that follows a little easier ie we can just strstr()
         * for the original command
         */
        if (msg->txLength > 0) {
            char *tmp;
123
            if ((tmp = strchr(msg->txBuffer, '\r')))
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
                *tmp = '\0';
        }

        /* QEMU echos the command back to us, full of control
         * character junk that we don't want. We have to skip
         * over this junk by looking for the first complete
         * repetition of our command. Then we can look for
         * the prompt that is supposed to follow
         *
         * NB, we can't optimize by immediately looking for
         * LINE_ENDING, because QEMU 0.10 has bad problems
         * when initially connecting where it might write a
         * prompt in the wrong place. So we must not look
         * for LINE_ENDING, or BASIC_PROMPT until we've
         * seen our original command echod.
         */
        skip = strstr(data + used, msg->txBuffer);

        /* After the junk we should have a line ending... */
143
        if (skip)
144
            start = strstr(skip + strlen(msg->txBuffer), LINE_ENDING);
145

146 147 148 149 150 151 152 153
        /* ... then our command reply data, following by a (qemu) prompt */
        if (start) {
            char *passwd;
            start += strlen(LINE_ENDING);

            /* We might get a prompt for a password before the (qemu) prompt */
            passwd = strstr(start, PASSWORD_PROMPT);
            if (passwd) {
154
#if DEBUG_IO
155
                VIR_DEBUG("Seen a password prompt [%s]", data + used);
156
#endif
157
                if (msg->passwordHandler) {
158
                    size_t i;
159 160
                    /* Try and handle the prompt. The handler is required
                     * to report a normal libvirt error */
161 162 163 164 165 166 167 168
                    if (msg->passwordHandler(mon, msg,
                                             start,
                                             passwd - start + strlen(PASSWORD_PROMPT),
                                             msg->passwordOpaque) < 0)
                        return -1;

                    /* Blank out the password prompt so we don't re-trigger
                     * if we have to go back to sleep for more I/O */
169
                    for (i = 0; i < strlen(PASSWORD_PROMPT); i++)
170 171 172 173 174
                        start[i] = ' ';

                    /* Handled, so skip forward over password prompt */
                    start = passwd;
                } else {
175 176
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("Password request seen, but no handler available"));
177 178
                    return -1;
                }
179
            }
180 181

            end = strstr(start, BASIC_PROMPT);
182
        }
183

184
        if (start && end) {
185 186 187 188 189 190
            int want = end - start;
            /* Annoyingly some commands may not have any reply data
             * at all upon success, but since we've detected the
             * BASIC_PROMPT we can reasonably reliably cope */
            if (want) {
                if (VIR_REALLOC_N(msg->rxBuffer,
191
                                  msg->rxLength + want + 1) < 0)
192 193 194 195
                    return -1;
                memcpy(msg->rxBuffer + msg->rxLength, start, want);
                msg->rxLength += want;
                msg->rxBuffer[msg->rxLength] = '\0';
196
#if DEBUG_IO
197 198
                VIR_DEBUG("Finished %d byte reply [%s]", want, msg->rxBuffer);
            } else {
199
                VIR_DEBUG("Finished 0 byte reply");
200
#endif
201
            }
202 203 204
            PROBE(QEMU_MONITOR_RECV_REPLY,
                  "mon=%p reply=%s",
                  mon, msg->rxBuffer);
205 206 207 208 209 210
            msg->finished = 1;
            used += end - (data + used);
            used += strlen(BASIC_PROMPT);
        }
    }

211
#if DEBUG_IO
212
    VIR_DEBUG("Total used %d", used);
213
#endif
214
    return used;
215 216
}

217
static int
218 219 220 221 222 223 224
qemuMonitorTextCommandWithHandler(qemuMonitorPtr mon,
                                  const char *cmd,
                                  qemuMonitorPasswordHandler passwordHandler,
                                  void *passwordOpaque,
                                  int scm_fd,
                                  char **reply)
{
225 226
    int ret;
    qemuMonitorMessage msg;
227

228
    *reply = NULL;
229

230
    memset(&msg, 0, sizeof(msg));
231

232
    if (virAsprintf(&msg.txBuffer, "%s\r", cmd) < 0)
233 234 235 236 237
        return -1;
    msg.txLength = strlen(msg.txBuffer);
    msg.txFD = scm_fd;
    msg.passwordHandler = passwordHandler;
    msg.passwordOpaque = passwordOpaque;
238

239
    VIR_DEBUG("Send command '%s' for write with FD %d", cmd, scm_fd);
240

241
    ret = qemuMonitorSend(mon, &msg);
242

243 244
    VIR_DEBUG("Receive command reply ret=%d rxLength=%d rxBuffer='%s'",
              ret, msg.rxLength, msg.rxBuffer);
245

246 247 248
    /* Just in case buffer had some passwords in */
    memset(msg.txBuffer, 0, msg.txLength);
    VIR_FREE(msg.txBuffer);
249

250 251 252 253 254
    if (ret >= 0) {
        /* To make life safer for callers, already ensure there's at least an empty string */
        if (msg.rxBuffer) {
            *reply = msg.rxBuffer;
        } else {
255
            if (VIR_STRDUP(*reply, "") < 0)
256
                return -1;
257 258 259
        }
    }

260
    return ret;
261 262
}

263 264 265 266 267 268
int
qemuMonitorTextCommandWithFd(qemuMonitorPtr mon,
                             const char *cmd,
                             int scm_fd,
                             char **reply)
{
269 270
    return qemuMonitorTextCommandWithHandler(mon, cmd, NULL, NULL,
                                             scm_fd, reply);
271 272
}

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
/* Check monitor output for evidence that the command was not recognized.
 * For 'info' commands, qemu returns help text.  For other commands, qemu
 * returns 'unknown command:'.
 */
static int
qemuMonitorTextCommandNotFound(const char *cmd, const char *reply)
{
    if (STRPREFIX(cmd, "info ")) {
        if (strstr(reply, "info version"))
            return 1;
    } else {
        if (strstr(reply, "unknown command:"))
            return 1;
    }

    return 0;
}
290 291

static int
292 293 294 295 296
qemuMonitorSendDiskPassphrase(qemuMonitorPtr mon,
                              qemuMonitorMessagePtr msg,
                              const char *data,
                              size_t len ATTRIBUTE_UNUSED,
                              void *opaque)
297
{
298 299 300 301
    virConnectPtr conn = opaque;
    char *path;
    char *passphrase = NULL;
    size_t passphrase_len = 0;
302
    int res;
303 304
    const char *pathStart;
    const char *pathEnd;
305

306 307 308 309 310 311 312 313 314 315
    /*
     * For disk passwords:
     *
     *    ide0-hd0 (/path/to/volume) is encrypted.
     *    Password:
     *
     */
    pathStart = strstr(data, DISK_ENCRYPTION_PREFIX);
    pathEnd = strstr(data, DISK_ENCRYPTION_POSTFIX);
    if (!pathStart || !pathEnd || pathStart >= pathEnd) {
316 317 318
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unable to extract disk path from %s"),
                       data);
319
        return -1;
320 321 322 323
    }

    /* Extra the path */
    pathStart += strlen(DISK_ENCRYPTION_PREFIX);
324
    if (VIR_STRNDUP(path, pathStart, pathEnd - pathStart) < 0)
325 326
        return -1;

327 328 329 330 331 332
    /* Fetch the disk password if possible */
    res = qemuMonitorGetDiskSecret(mon,
                                   conn,
                                   path,
                                   &passphrase,
                                   &passphrase_len);
333
    VIR_FREE(path);
334
    if (res < 0)
335 336
        return -1;

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
    /* Enlarge transmit buffer to allow for the extra data
     * to be sent back */
    if (VIR_REALLOC_N(msg->txBuffer,
                      msg->txLength + passphrase_len + 1 + 1) < 0) {
        memset(passphrase, 0, passphrase_len);
        VIR_FREE(passphrase);
        return -1;
    }

    /* Queue the password for sending */
    memcpy(msg->txBuffer + msg->txLength,
           passphrase, passphrase_len);
    msg->txLength += passphrase_len;
    msg->txBuffer[msg->txLength] = '\r';
    msg->txLength++;
    msg->txBuffer[msg->txLength] = '\0';
353 354 355 356

    memset(passphrase, 0, passphrase_len);
    VIR_FREE(passphrase);

357
    return 0;
358 359 360
}

int
361
qemuMonitorTextStartCPUs(qemuMonitorPtr mon,
362 363
                         virConnectPtr conn)
{
364 365
    char *reply;

366 367 368 369
    if (qemuMonitorTextCommandWithHandler(mon, "cont",
                                          qemuMonitorSendDiskPassphrase,
                                          conn,
                                          -1, &reply) < 0)
370
        return -1;
371

372 373 374
    VIR_FREE(reply);
    return 0;
}
375 376


377
int
378 379
qemuMonitorTextStopCPUs(qemuMonitorPtr mon)
{
380
    char *info;
381
    int ret;
382

383
    ret = qemuMonitorHMPCommand(mon, "stop", &info);
384
    VIR_FREE(info);
385
    return ret;
386 387
}

388

389
int
390 391 392
qemuMonitorTextGetStatus(qemuMonitorPtr mon,
                         bool *running,
                         virDomainPausedReason *reason)
393 394 395 396
{
    char *reply;
    int ret = -1;

397 398 399
    if (reason)
        *reason = VIR_DOMAIN_PAUSED_UNKNOWN;

400
    if (qemuMonitorHMPCommand(mon, "info status", &reply) < 0)
401 402 403 404 405
        return -1;

    if (strstr(reply, "running")) {
        *running = true;
    } else if (strstr(reply, "paused")) {
406 407 408 409 410 411 412 413 414 415 416 417 418
        char *status;

        if ((status = strchr(reply, '('))) {
            char *end = strchr(status, ')');
            if (end)
                *end = '\0';
            else
                status = NULL;
        }
        if (!status)
            VIR_DEBUG("info status was missing status details");
        else if (reason)
            *reason = qemuMonitorVMStatusToPausedReason(status);
419 420
        *running = false;
    } else {
421 422
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("unexpected reply from info status: %s"), reply);
423 424 425 426 427
        goto cleanup;
    }

    ret = 0;

428
 cleanup:
429 430 431 432 433
    VIR_FREE(reply);
    return ret;
}


434 435
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon)
{
436
    char *info;
437 438 439
    int ret;

    ret = qemuMonitorHMPCommand(mon, "system_powerdown", &info);
440 441

    VIR_FREE(info);
442
    return ret;
443 444
}

445 446 447
int
qemuMonitorTextSetLink(qemuMonitorPtr mon,
                       const char *name,
448
                       virDomainNetInterfaceLinkState state)
449
{
450 451 452 453 454 455 456 457 458 459
    char *info = NULL;
    char *cmd = NULL;
    const char *st_str = NULL;

    /* determine state */
    if (state == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN)
        st_str = "off";
    else
        st_str = "on";

460
    if (virAsprintf(&cmd, "set_link %s %s", name, st_str) < 0)
461
        goto error;
462
    if (qemuMonitorHMPCommand(mon, cmd, &info) < 0)
463 464 465 466
        goto error;

    /* check if set_link command is supported */
    if (strstr(info, "\nunknown ")) {
467
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
468 469
                       "%s",
                       _("\'set_link\' not supported by this qemu"));
470 471 472 473 474
        goto error;
    }

    /* check if qemu didn't reject device name */
    if (strstr(info, "\nDevice ")) {
475 476
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("device name rejected"));
477 478 479 480 481 482 483
        goto error;
    }

    VIR_FREE(info);
    VIR_FREE(cmd);
    return 0;

484
 error:
485 486 487 488 489
    VIR_FREE(info);
    VIR_FREE(cmd);

    return -1;
}
490

491 492
int qemuMonitorTextSystemReset(qemuMonitorPtr mon)
{
493
    char *info;
494 495 496
    int ret;

    ret = qemuMonitorHMPCommand(mon, "system_reset", &info);
497 498

    VIR_FREE(info);
499
    return ret;
500 501 502
}


503 504
int qemuMonitorTextGetCPUInfo(qemuMonitorPtr mon,
                              int **pids)
505 506 507 508 509 510
{
    char *qemucpus = NULL;
    char *line;
    pid_t *cpupids = NULL;
    size_t ncpupids = 0;

511
    if (qemuMonitorHMPCommand(mon, "info cpus", &qemucpus) < 0)
512 513 514 515 516 517 518 519 520 521 522 523 524
        return -1;

    /*
     * This is the gross format we're about to parse :-{
     *
     * (qemu) info cpus
     * * CPU #0: pc=0x00000000000f0c4a thread_id=30019
     *   CPU #1: pc=0x00000000fffffff0 thread_id=30020
     *   CPU #2: pc=0x00000000fffffff0 thread_id=30021
     *
     */
    line = qemucpus;
    do {
525
        char *offset = NULL;
526
        char *end = NULL;
527
        int tid = 0;
528 529 530 531 532 533 534 535 536 537

        /* Extract host Thread ID */
        if ((offset = strstr(line, "thread_id=")) == NULL)
            goto error;

        if (virStrToLong_i(offset + strlen("thread_id="), &end, 10, &tid) < 0)
            goto error;
        if (end == NULL || !c_isspace(*end))
            goto error;

538
        if (VIR_APPEND_ELEMENT_COPY(cpupids, ncpupids, tid) < 0)
539 540
            goto error;

541
        VIR_DEBUG("tid=%d", tid);
542 543 544 545 546 547 548 549 550 551 552 553

        /* Skip to next data line */
        line = strchr(offset, '\r');
        if (line == NULL)
            line = strchr(offset, '\n');
    } while (line != NULL);

    /* Validate we got data for all VCPUs we expected */
    VIR_FREE(qemucpus);
    *pids = cpupids;
    return ncpupids;

554
 error:
555 556 557 558 559 560 561 562 563 564
    VIR_FREE(qemucpus);
    VIR_FREE(cpupids);

    /* Returning 0 to indicate non-fatal failure, since
     * older QEMU does not have VCPU<->PID mapping and
     * we don't want to fail on that
     */
    return 0;
}

565 566

int qemuMonitorTextGetVirtType(qemuMonitorPtr mon,
567
                               virDomainVirtType *virtType)
568 569 570 571 572
{
    char *reply = NULL;

    *virtType = VIR_DOMAIN_VIRT_QEMU;

573
    if (qemuMonitorHMPCommand(mon, "info kvm", &reply) < 0)
574 575 576 577 578 579 580 581 582 583
        return -1;

    if (strstr(reply, "enabled"))
        *virtType = VIR_DOMAIN_VIRT_KVM;

    VIR_FREE(reply);
    return 0;
}


584 585 586 587 588 589
static int parseMemoryStat(char **text, unsigned int tag,
                           const char *search, virDomainMemoryStatPtr stat)
{
    char *dummy;
    unsigned long long value;

590
    if (STRPREFIX(*text, search)) {
591
        *text += strlen(search);
592 593
        if (virStrToLong_ull(*text, &dummy, 10, &value)) {
            VIR_DEBUG("error reading %s: %s", search, *text);
594 595 596 597
            return 0;
        }

        switch (tag) {
598 599 600 601 602
            /* Convert megabytes to kilobytes for libvirt */
            case VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON:
                value <<= 10;
                break;
            /* Convert bytes to kilobytes for libvirt */
603 604 605 606
            case VIR_DOMAIN_MEMORY_STAT_SWAP_IN:
            case VIR_DOMAIN_MEMORY_STAT_SWAP_OUT:
            case VIR_DOMAIN_MEMORY_STAT_UNUSED:
            case VIR_DOMAIN_MEMORY_STAT_AVAILABLE:
607
                value >>= 10;
608 609 610 611 612 613 614 615 616
        }
        stat->tag = tag;
        stat->val = value;
        return 1;
    }
    return 0;
}

/* The reply from the 'info balloon' command may contain additional memory
617
 * statistics in the form: 'actual=<val> [,<tag>=<val>]*'
618
 */
619 620 621
static int qemuMonitorParseBalloonInfo(char *text,
                                       virDomainMemoryStatPtr stats,
                                       unsigned int nr_stats)
622 623 624 625
{
    char *p = text;
    unsigned int nr_stats_found = 0;

626 627 628 629 630 631 632 633 634 635
    /* Since "actual=" always comes first in the returned string,
     * and sometime we only care about the value of "actual", such
     * as qemuMonitorGetBalloonInfo, we parse it outside of the
     * loop.
     */
    if (parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON,
                        "actual=", &stats[nr_stats_found]) == 1) {
        nr_stats_found++;
    }

636 637 638 639 640 641 642 643 644 645 646 647
    while (*p && nr_stats_found < nr_stats) {
        if (parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_SWAP_IN,
                            ",mem_swapped_in=", &stats[nr_stats_found]) ||
            parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_SWAP_OUT,
                            ",mem_swapped_out=", &stats[nr_stats_found]) ||
            parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT,
                            ",major_page_faults=", &stats[nr_stats_found]) ||
            parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT,
                            ",minor_page_faults=", &stats[nr_stats_found]) ||
            parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_UNUSED,
                            ",free_mem=", &stats[nr_stats_found]) ||
            parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_AVAILABLE,
648
                            ",total_mem=", &stats[nr_stats_found]))
649 650
            nr_stats_found++;

651 652 653 654 655
        /* Skip to the next label.  When *p is ',' the last match attempt
         * failed so try to match the next ','.
         */
        if (*p == ',')
            p++;
656
        p = strchr(p, ',');
657 658 659 660
        if (!p) break;
    }
    return nr_stats_found;
}
661

662 663

/* The reply from QEMU contains 'ballon: actual=421' where value is in MB */
664
#define BALLOON_PREFIX "balloon: "
665

666 667 668
int
qemuMonitorTextGetBalloonInfo(qemuMonitorPtr mon,
                              unsigned long long *currmem)
669 670 671 672 673
{
    char *reply = NULL;
    int ret = -1;
    char *offset;

674
    if (qemuMonitorHMPCommand(mon, "info balloon", &reply) < 0)
675 676 677 678
        return -1;

    if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) {
        offset += strlen(BALLOON_PREFIX);
679
        virDomainMemoryStatStruct stats[1];
680 681

        if (qemuMonitorParseBalloonInfo(offset, stats, 1) == 0) {
682 683
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected balloon information '%s'"), reply);
684 685
            goto cleanup;
        }
686 687

        if (stats[0].tag != VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON) {
688 689
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected balloon information '%s'"), reply);
690 691 692 693
            goto cleanup;
        }

        *currmem = stats[0].val;
694 695 696 697 698 699 700 701
        ret = 1;
    } else {
        /* We don't raise an error here, since its to be expected that
         * many QEMU's don't support ballooning
         */
        ret = 0;
    }

702
 cleanup:
703 704 705 706
    VIR_FREE(reply);
    return ret;
}

707 708 709 710 711 712 713 714
int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
                                  virDomainMemoryStatPtr stats,
                                  unsigned int nr_stats)
{
    char *reply = NULL;
    int ret = 0;
    char *offset;

715
    if (qemuMonitorHMPCommand(mon, "info balloon", &reply) < 0)
716 717 718
        return -1;

    if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) {
719
        offset += strlen(BALLOON_PREFIX);
720
        ret = qemuMonitorParseBalloonInfo(offset, stats, nr_stats);
721 722 723 724 725 726
    }

    VIR_FREE(reply);
    return ret;
}

727

728
int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
729
                                virHashTablePtr table)
730
{
731
    struct qemuDomainDiskInfo *info = NULL;
732 733 734
    char *reply = NULL;
    int ret = -1;
    char *dummy;
735 736
    char *p, *eol;
    char *dev;
737 738
    int tmp;

739
    if (qemuMonitorHMPCommand(mon, "info block", &reply) < 0)
740 741 742
        goto cleanup;

    if (strstr(reply, "\ninfo ")) {
743 744 745
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",
                       _("info block not supported by this qemu"));
746 747 748 749 750 751 752 753 754 755 756 757 758
        goto cleanup;
    }

    /* The output looks like this:
     * drive-ide0-0-0: removable=0 file=<path> ro=0 drv=raw encrypted=0
     * drive-ide0-1-0: removable=1 locked=0 file=<path> ro=1 drv=raw encrypted=0
     */
    p = reply;

    while (*p) {
        if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX))
            p += strlen(QEMU_DRIVE_HOST_PREFIX);

759 760 761
        eol = strchr(p, '\n');
        if (!eol)
            eol = p + strlen(p) - 1;
762

763 764 765
        dev = p;
        p = strchr(p, ':');
        if (p && p < eol && *(p + 1) == ' ') {
766
            if (VIR_ALLOC(info) < 0)
767
                goto cleanup;
768

769 770
            *p = '\0';
            p += 2;
771

772
            while (p < eol) {
773 774 775 776 777
                if (STRPREFIX(p, "removable=")) {
                    p += strlen("removable=");
                    if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
                        VIR_DEBUG("error reading removable: %s", p);
                    else
E
Eric Blake 已提交
778
                        info->removable = (tmp != 0);
779 780 781 782 783
                } else if (STRPREFIX(p, "locked=")) {
                    p += strlen("locked=");
                    if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
                        VIR_DEBUG("error reading locked: %s", p);
                    else
E
Eric Blake 已提交
784
                        info->locked = (tmp != 0);
785 786
                } else if (STRPREFIX(p, "tray-open=")) {
                    p += strlen("tray-open=");
787
                    if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
788
                        VIR_DEBUG("error reading tray-open: %s", p);
789
                    else
E
Eric Blake 已提交
790
                        info->tray_open = (tmp != 0);
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
                } else if (STRPREFIX(p, "io-status=")) {
                    char *end;
                    char c;

                    p += strlen("io-status=");
                    end = strchr(p, ' ');
                    if (!end || end > eol)
                        end = eol;

                    c = *end;
                    *end = '\0';
                    info->io_status = qemuMonitorBlockIOStatusToError(p);
                    *end = c;
                    if (info->io_status < 0)
                        goto cleanup;
806 807 808 809 810 811
                } else {
                    /* ignore because we don't parse all options */
                }

                /* skip to next label */
                p = strchr(p, ' ');
812 813
                if (!p)
                    break;
814 815 816
                p++;
            }

817 818 819 820
            if (virHashAddEntry(table, dev, info) < 0)
                goto cleanup;
            else
                info = NULL;
821 822
        }

823 824
        /* skip to the next line */
        p = eol + 1;
825 826
    }

827
    ret = 0;
828

829
 cleanup:
830
    VIR_FREE(info);
831 832 833 834
    VIR_FREE(reply);
    return ret;
}

835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850

int
qemuMonitorTextGetAllBlockStatsInfo(qemuMonitorPtr mon,
                                    virHashTablePtr hash)
{
    qemuBlockStatsPtr stats = NULL;
    char *info = NULL;
    char *dev_name;
    char **lines = NULL;
    char **values = NULL;
    char *line;
    char *value;
    char *key;
    size_t i;
    size_t j;
    int ret = -1;
851 852
    int nstats;
    int maxstats = 0;
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909

    if (qemuMonitorHMPCommand(mon, "info blockstats", &info) < 0)
        goto cleanup;

    /* If the command isn't supported then qemu prints the supported info
     * commands, so the output starts "info ".  Since this is unlikely to be
     * the name of a block device, we can use this to detect if qemu supports
     * the command. */
    if (strstr(info, "\ninfo ")) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("'info blockstats' not supported by this qemu"));
        goto cleanup;
    }

    /* The output format for both qemu & KVM is:
     *   blockdevice: rd_bytes=% wr_bytes=% rd_operations=% wr_operations=%
     *   (repeated for each block device)
     * where '%' is a 64 bit number.
     */
    if (!(lines = virStringSplit(info, "\n", 0)))
        goto cleanup;

    for (i = 0; lines[i] && *lines[i]; i++) {
        line = lines[i];

        if (VIR_ALLOC(stats) < 0)
            goto cleanup;

        /* set the entries to -1, the JSON monitor enforces them, but it would
         * be overly complex to achieve this here */
        stats->rd_req = -1;
        stats->rd_bytes = -1;
        stats->wr_req = -1;
        stats->wr_bytes = -1;
        stats->rd_total_times = -1;
        stats->wr_total_times = -1;
        stats->flush_req = -1;
        stats->flush_total_times = -1;

        /* extract device name and make sure that it's followed by
         * a colon and space */
        dev_name = line;
        if (!(line = strchr(line, ':')) && line[1] != ' ') {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("info blockstats reply was malformed"));
            goto cleanup;
        }

        *line = '\0';
        line += 2;

        if (STRPREFIX(dev_name, QEMU_DRIVE_HOST_PREFIX))
            dev_name += strlen(QEMU_DRIVE_HOST_PREFIX);

        if (!(values = virStringSplit(line, " ", 0)))
            goto cleanup;

910 911
        nstats = 0;

912 913 914 915 916 917 918 919 920 921 922 923 924 925
        for (j = 0; values[j] && *values[j]; j++) {
            key = values[j];

            if (!(value = strchr(key, '='))) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("info blockstats entry was malformed"));
                goto cleanup;
            }

            *value = '\0';
            value++;

#define QEMU_MONITOR_TEXT_READ_BLOCK_STAT(NAME, VAR)                           \
            if (STREQ(key, NAME)) {                                            \
926
                nstats++;                                                      \
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
                if (virStrToLong_ll(value, NULL, 10, &VAR) < 0) {              \
                    virReportError(VIR_ERR_INTERNAL_ERROR,                     \
                                   _("'info blockstats' contains malformed "   \
                                     "parameter '%s' value '%s'"), NAME, value);\
                    goto cleanup;                                              \
                }                                                              \
                continue;                                                      \
            }

            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("rd_bytes", stats->rd_bytes);
            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("wr_bytes", stats->wr_bytes);
            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("rd_operations", stats->rd_req);
            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("wr_operations", stats->wr_req);
            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("rd_total_time_ns", stats->rd_total_times);
            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("wr_total_time_ns", stats->wr_total_times);
            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("flush_operations", stats->flush_req);
            QEMU_MONITOR_TEXT_READ_BLOCK_STAT("flush_total_time_ns", stats->flush_total_times);
#undef QEMU_MONITOR_TEXT_READ_BLOCK_STAT

            /* log if we get statistic element different from the above */
            VIR_DEBUG("unknown block stat field '%s'", key);
        }

950 951 952
        if (nstats > maxstats)
            maxstats = nstats;

953 954 955 956 957 958 959 960
        if (virHashAddEntry(hash, dev_name, stats) < 0)
            goto cleanup;
        stats = NULL;

        virStringFreeList(values);
        values = NULL;
    }

961
    ret = maxstats;
962 963 964 965 966 967 968 969 970

 cleanup:
    virStringFreeList(lines);
    virStringFreeList(values);
    VIR_FREE(stats);
    VIR_FREE(info);
    return ret;
}

E
Eric Blake 已提交
971 972
/* Return 0 on success, -1 on failure, or -2 if not supported.  Size
 * is in bytes. */
973 974 975 976 977 978 979 980
int qemuMonitorTextBlockResize(qemuMonitorPtr mon,
                               const char *device,
                               unsigned long long size)
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;

981
    if (virAsprintf(&cmd, "block_resize %s %lluB", device, size) < 0)
982 983
        goto cleanup;

984
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
985 986 987 988 989 990 991 992 993
        goto cleanup;

    if (strstr(reply, "unknown command:")) {
        ret = -2;
        goto cleanup;
    }

    ret = 0;

994
 cleanup:
995 996 997 998
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}
999

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
static int
qemuMonitorSendVNCPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                             qemuMonitorMessagePtr msg,
                             const char *data ATTRIBUTE_UNUSED,
                             size_t len ATTRIBUTE_UNUSED,
                             void *opaque)
{
    char *passphrase = opaque;
    size_t passphrase_len = strlen(passphrase);

    /* Enlarge transmit buffer to allow for the extra data
     * to be sent back */
    if (VIR_REALLOC_N(msg->txBuffer,
1013
                      msg->txLength + passphrase_len + 1 + 1) < 0)
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
        return -1;

    /* Queue the password for sending */
    memcpy(msg->txBuffer + msg->txLength,
           passphrase, passphrase_len);
    msg->txLength += passphrase_len;
    msg->txBuffer[msg->txLength] = '\r';
    msg->txLength++;
    msg->txBuffer[msg->txLength] = '\0';

    return 0;
}

1027 1028
int qemuMonitorTextSetVNCPassword(qemuMonitorPtr mon,
                                  const char *password)
1029 1030
{
    char *info = NULL;
1031

1032 1033 1034 1035
    if (qemuMonitorTextCommandWithHandler(mon, "change vnc password",
                                          qemuMonitorSendVNCPassphrase,
                                          (char *)password,
                                          -1, &info) < 0) {
1036 1037
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("setting VNC password failed"));
1038 1039 1040 1041 1042
        return -1;
    }
    VIR_FREE(info);
    return 0;
}
1043

1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
/* Returns -1 on error, -2 if not supported */
int qemuMonitorTextSetPassword(qemuMonitorPtr mon,
                               const char *protocol,
                               const char *password,
                               const char *action_if_connected)
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;

    if (virAsprintf(&cmd, "set_password %s \"%s\" %s",
1055
                    protocol, password, action_if_connected) < 0)
1056 1057
        goto cleanup;

1058
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1059 1060 1061 1062 1063 1064 1065 1066 1067
        goto cleanup;

    if (strstr(reply, "unknown command:")) {
        ret = -2;
        goto cleanup;
    }

    ret = 0;

1068
 cleanup:
1069 1070 1071 1072 1073
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}

1074
/* Returns -1 on error, -2 if not supported */
1075 1076 1077 1078 1079 1080 1081 1082 1083
int qemuMonitorTextExpirePassword(qemuMonitorPtr mon,
                                  const char *protocol,
                                  const char *expire_time)
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;

    if (virAsprintf(&cmd, "expire_password %s %s",
1084
                    protocol, expire_time) < 0)
1085 1086
        goto cleanup;

1087
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1088 1089 1090
        goto cleanup;

    if (strstr(reply, "unknown command:")) {
1091
        ret = -2;
1092 1093 1094 1095 1096
        goto cleanup;
    }

    ret = 0;

1097
 cleanup:
1098 1099 1100 1101 1102
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}

1103 1104 1105 1106

int
qemuMonitorTextSetBalloon(qemuMonitorPtr mon,
                          unsigned long long newmem)
1107 1108 1109 1110 1111 1112 1113 1114 1115
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

    /*
     * 'newmem' is in KB, QEMU monitor works in MB, and we all wish
     * we just worked in bytes with unsigned long long everywhere.
     */
1116
    if (virAsprintf(&cmd, "balloon %llu", VIR_DIV_UP(newmem, 1024)) < 0)
1117 1118
        return -1;

1119
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) {
1120 1121 1122 1123 1124 1125 1126
        VIR_FREE(cmd);
        return -1;
    }
    VIR_FREE(cmd);

    /* If the command failed qemu prints: 'unknown command'
     * No message is printed on success it seems */
1127
    if (strstr(reply, "unknown command:")) {
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
        /* Don't set error - it is expected memory balloon fails on many qemu */
        ret = 0;
    } else {
        ret = 1;
    }

    VIR_FREE(reply);
    return ret;
}

1138

1139
int qemuMonitorTextSetCPU(qemuMonitorPtr mon, int cpu, bool online)
1140 1141 1142 1143 1144
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

1145
    if (virAsprintf(&cmd, "cpu_set %d %s", cpu, online ? "online" : "offline") < 0)
1146 1147
        return -1;

1148 1149
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
        goto cleanup;
1150 1151 1152

    /* If the command failed qemu prints: 'unknown command'
     * No message is printed on success it seems */
1153
    if (strstr(reply, "unknown command:")) {
1154 1155 1156
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot change vcpu count of this domain"));
        goto cleanup;
1157 1158
    }

1159 1160 1161
    ret = 0;

 cleanup:
1162
    VIR_FREE(reply);
1163 1164
    VIR_FREE(cmd);

1165 1166 1167 1168
    return ret;
}


1169 1170 1171 1172
/**
 * Run HMP command to eject a media from ejectable device.
 *
 * Returns:
P
Pavel Hrdina 已提交
1173
 *      -1 on error
1174 1175
 *      0 on success
 */
1176
int qemuMonitorTextEjectMedia(qemuMonitorPtr mon,
1177
                              const char *dev_name,
1178
                              bool force)
1179 1180 1181 1182 1183
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;

1184
    if (virAsprintf(&cmd, "eject %s%s", force ? "-f " : "", dev_name) < 0)
1185 1186
        goto cleanup;

1187
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1188 1189 1190 1191 1192
        goto cleanup;

    /* If the command failed qemu prints:
     * device not found, device is locked ...
     * No message is printed on success it seems */
1193
    if (c_strcasestr(reply, "device ")) {
1194 1195
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("could not eject media on %s: %s"), dev_name, reply);
1196 1197 1198 1199 1200
        goto cleanup;
    }

    ret = 0;

1201
 cleanup:
1202 1203 1204 1205 1206 1207
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}


1208
int qemuMonitorTextChangeMedia(qemuMonitorPtr mon,
1209
                               const char *dev_name,
1210 1211
                               const char *newmedia,
                               const char *format ATTRIBUTE_UNUSED)
1212 1213 1214 1215 1216 1217
{
    char *cmd = NULL;
    char *reply = NULL;
    char *safepath = NULL;
    int ret = -1;

1218
    if (!(safepath = qemuMonitorEscapeArg(newmedia)))
1219 1220
        goto cleanup;

1221
    if (virAsprintf(&cmd, "change %s \"%s\"", dev_name, safepath) < 0)
1222 1223
        goto cleanup;

1224
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1225 1226 1227 1228 1229
        goto cleanup;

    /* If the command failed qemu prints:
     * device not found, device is locked ...
     * No message is printed on success it seems */
1230
    if (c_strcasestr(reply, "device ")) {
1231 1232
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("could not change media on %s: %s"), dev_name, reply);
1233 1234 1235
        goto cleanup;
    }

R
Ryan Harper 已提交
1236
    /* Could not open message indicates bad filename */
1237
    if (strstr(reply, "Could not open ")) {
1238 1239
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("could not change media on %s: %s"), dev_name, reply);
R
Ryan Harper 已提交
1240 1241 1242
        goto cleanup;
    }

1243 1244
    ret = 0;

1245
 cleanup:
1246 1247 1248 1249 1250 1251
    VIR_FREE(reply);
    VIR_FREE(cmd);
    VIR_FREE(safepath);
    return ret;
}

1252 1253 1254 1255 1256
static int qemuMonitorTextSaveMemory(qemuMonitorPtr mon,
                                     const char *cmdtype,
                                     unsigned long long offset,
                                     size_t length,
                                     const char *path)
1257 1258 1259 1260 1261 1262
{
    char *cmd = NULL;
    char *reply = NULL;
    char *safepath = NULL;
    int ret = -1;

1263
    if (!(safepath = qemuMonitorEscapeArg(path)))
1264 1265
        goto cleanup;

1266
    if (virAsprintf(&cmd, "%s %llu %zi \"%s\"", cmdtype, offset, length, safepath) < 0)
1267 1268
        goto cleanup;

1269
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1270 1271 1272 1273 1274 1275
        goto cleanup;

    /* XXX what is printed on failure ? */

    ret = 0;

1276
 cleanup:
1277 1278 1279 1280 1281 1282 1283
    VIR_FREE(cmd);
    VIR_FREE(reply);
    VIR_FREE(safepath);
    return ret;
}


1284 1285 1286 1287
int qemuMonitorTextSaveVirtualMemory(qemuMonitorPtr mon,
                                     unsigned long long offset,
                                     size_t length,
                                     const char *path)
1288
{
1289
    return qemuMonitorTextSaveMemory(mon, "memsave", offset, length, path);
1290 1291
}

1292 1293 1294 1295
int qemuMonitorTextSavePhysicalMemory(qemuMonitorPtr mon,
                                      unsigned long long offset,
                                      size_t length,
                                      const char *path)
1296
{
1297
    return qemuMonitorTextSaveMemory(mon, "pmemsave", offset, length, path);
1298
}
1299 1300


1301 1302
int qemuMonitorTextSetMigrationSpeed(qemuMonitorPtr mon,
                                     unsigned long bandwidth)
1303 1304 1305 1306 1307
{
    char *cmd = NULL;
    char *info = NULL;
    int ret = -1;

1308
    if (virAsprintf(&cmd, "migrate_set_speed %lum", bandwidth) < 0)
1309 1310
        goto cleanup;

1311
    if (qemuMonitorHMPCommand(mon, cmd, &info) < 0)
1312 1313 1314 1315
        goto cleanup;

    ret = 0;

1316
 cleanup:
1317 1318 1319 1320
    VIR_FREE(info);
    VIR_FREE(cmd);
    return ret;
}
1321 1322


1323 1324 1325 1326 1327 1328 1329
int qemuMonitorTextSetMigrationDowntime(qemuMonitorPtr mon,
                                        unsigned long long downtime)
{
    char *cmd = NULL;
    char *info = NULL;
    int ret = -1;

1330
    if (virAsprintf(&cmd, "migrate_set_downtime %llums", downtime) < 0)
1331 1332
        goto cleanup;

1333
    if (qemuMonitorHMPCommand(mon, cmd, &info) < 0)
1334 1335 1336 1337
        goto cleanup;

    ret = 0;

1338
 cleanup:
1339 1340 1341 1342 1343 1344
    VIR_FREE(info);
    VIR_FREE(cmd);
    return ret;
}


1345 1346 1347 1348
#define MIGRATION_PREFIX "Migration status: "
#define MIGRATION_TRANSFER_PREFIX "transferred ram: "
#define MIGRATION_REMAINING_PREFIX "remaining ram: "
#define MIGRATION_TOTAL_PREFIX "total ram: "
1349 1350 1351
#define MIGRATION_DISK_TRANSFER_PREFIX "transferred disk: "
#define MIGRATION_DISK_REMAINING_PREFIX "remaining disk: "
#define MIGRATION_DISK_TOTAL_PREFIX "total disk: "
1352

1353 1354
int qemuMonitorTextGetMigrationStats(qemuMonitorPtr mon,
                                     qemuMonitorMigrationStatsPtr stats)
1355
{
1356 1357 1358 1359 1360
    char *reply;
    char *tmp;
    char *end;
    int ret = -1;

1361
    memset(stats, 0, sizeof(*stats));
1362

1363
    if (qemuMonitorHMPCommand(mon, "info migrate", &reply) < 0)
1364 1365 1366 1367
        return -1;

    if ((tmp = strstr(reply, MIGRATION_PREFIX)) != NULL) {
        tmp += strlen(MIGRATION_PREFIX);
P
Paolo Bonzini 已提交
1368
        end = strchr(tmp, '\r');
1369
        if (end == NULL) {
1370 1371
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected migration status in %s"), reply);
1372 1373
            goto cleanup;
        }
1374 1375
        *end = '\0';

1376 1377
        stats->status = qemuMonitorMigrationStatusTypeFromString(tmp);
        if (stats->status < 0) {
1378 1379
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected migration status in %s"), reply);
1380 1381 1382
            goto cleanup;
        }

1383
        if (stats->status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) {
1384 1385 1386 1387 1388 1389
            tmp = end + 1;

            if (!(tmp = strstr(tmp, MIGRATION_TRANSFER_PREFIX)))
                goto done;
            tmp += strlen(MIGRATION_TRANSFER_PREFIX);

1390
            if (virStrToLong_ull(tmp, &end, 10,
1391
                                 &stats->ram_transferred) < 0) {
1392 1393 1394
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot parse migration data transferred "
                                 "statistic %s"), tmp);
1395 1396
                goto cleanup;
            }
1397
            stats->ram_transferred *= 1024;
1398
            tmp = end;
1399 1400 1401 1402 1403

            if (!(tmp = strstr(tmp, MIGRATION_REMAINING_PREFIX)))
                goto done;
            tmp += strlen(MIGRATION_REMAINING_PREFIX);

1404
            if (virStrToLong_ull(tmp, &end, 10, &stats->ram_remaining) < 0) {
1405 1406 1407
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot parse migration data remaining "
                                 "statistic %s"), tmp);
1408 1409
                goto cleanup;
            }
1410
            stats->ram_remaining *= 1024;
1411
            tmp = end;
1412 1413 1414 1415 1416

            if (!(tmp = strstr(tmp, MIGRATION_TOTAL_PREFIX)))
                goto done;
            tmp += strlen(MIGRATION_TOTAL_PREFIX);

1417
            if (virStrToLong_ull(tmp, &end, 10, &stats->ram_total) < 0) {
1418 1419 1420
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot parse migration data total "
                                 "statistic %s"), tmp);
1421 1422
                goto cleanup;
            }
1423
            stats->ram_total *= 1024;
1424 1425 1426
            tmp = end;

            /*
1427
             * Check for Optional Disk Migration stats
1428 1429 1430 1431 1432
             */
            if (!(tmp = strstr(tmp, MIGRATION_DISK_TRANSFER_PREFIX)))
                goto done;
            tmp += strlen(MIGRATION_DISK_TRANSFER_PREFIX);

1433
            if (virStrToLong_ull(tmp, &end, 10,
1434
                                 &stats->disk_transferred) < 0) {
1435 1436 1437
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot parse disk migration data "
                                 "transferred statistic %s"), tmp);
1438 1439
                goto cleanup;
            }
1440
            stats->disk_transferred *= 1024;
1441 1442 1443 1444 1445
            tmp = end;

            if (!(tmp = strstr(tmp, MIGRATION_DISK_REMAINING_PREFIX)))
                goto done;
            tmp += strlen(MIGRATION_DISK_REMAINING_PREFIX);
1446

1447
            if (virStrToLong_ull(tmp, &end, 10, &stats->disk_remaining) < 0) {
1448 1449 1450
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot parse disk migration data remaining "
                                 "statistic %s"), tmp);
1451 1452
                goto cleanup;
            }
1453
            stats->disk_remaining *= 1024;
1454 1455 1456 1457 1458 1459
            tmp = end;

            if (!(tmp = strstr(tmp, MIGRATION_DISK_TOTAL_PREFIX)))
                goto done;
            tmp += strlen(MIGRATION_DISK_TOTAL_PREFIX);

1460
            if (virStrToLong_ull(tmp, &end, 10, &stats->disk_total) < 0) {
1461 1462 1463
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot parse disk migration data total "
                                 "statistic %s"), tmp);
1464 1465
                goto cleanup;
            }
1466
            stats->disk_total *= 1024;
1467 1468 1469
        }
    }

1470
 done:
1471 1472
    ret = 0;

1473
 cleanup:
1474
    VIR_FREE(reply);
1475
    if (ret < 0)
1476
        memset(stats, 0, sizeof(*stats));
1477 1478
    return ret;
}
1479 1480


1481 1482 1483
int qemuMonitorTextMigrate(qemuMonitorPtr mon,
                           unsigned int flags,
                           const char *dest)
1484 1485 1486 1487
{
    char *cmd = NULL;
    char *info = NULL;
    int ret = -1;
1488
    char *safedest = qemuMonitorEscapeArg(dest);
1489
    virBuffer extra = VIR_BUFFER_INITIALIZER;
C
Chris Lalancette 已提交
1490
    char *extrastr = NULL;
1491

1492
    if (!safedest)
1493 1494
        return -1;

1495
    if (flags & QEMU_MONITOR_MIGRATE_BACKGROUND)
1496
        virBufferAddLit(&extra, " -d");
1497
    if (flags & QEMU_MONITOR_MIGRATE_NON_SHARED_DISK)
1498
        virBufferAddLit(&extra, " -b");
1499
    if (flags & QEMU_MONITOR_MIGRATE_NON_SHARED_INC)
1500
        virBufferAddLit(&extra, " -i");
1501
    if (virBufferCheckError(&extra) < 0)
C
Chris Lalancette 已提交
1502 1503 1504 1505
        goto cleanup;

    extrastr = virBufferContentAndReset(&extra);
    if (virAsprintf(&cmd, "migrate %s\"%s\"", extrastr ? extrastr : "",
1506
                    safedest) < 0)
1507 1508
        goto cleanup;

1509
    if (qemuMonitorHMPCommand(mon, cmd, &info) < 0)
1510 1511 1512 1513
        goto cleanup;

    /* Now check for "fail" in the output string */
    if (strstr(info, "fail") != NULL) {
1514 1515
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("migration to '%s' failed: %s"), dest, info);
1516 1517 1518 1519 1520
        goto cleanup;
    }
    /* If the command isn't supported then qemu prints:
     * unknown command: migrate" */
    if (strstr(info, "unknown command:")) {
1521 1522
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("migration to '%s' not supported by this qemu: %s"), dest, info);
1523 1524 1525 1526 1527 1528
        goto cleanup;
    }


    ret = 0;

1529
 cleanup:
C
Chris Lalancette 已提交
1530
    VIR_FREE(extrastr);
1531
    VIR_FREE(safedest);
1532 1533 1534 1535 1536
    VIR_FREE(info);
    VIR_FREE(cmd);
    return ret;
}

1537
int qemuMonitorTextMigrateCancel(qemuMonitorPtr mon)
1538 1539
{
    char *info = NULL;
1540
    int ret;
1541

1542
    ret = qemuMonitorHMPCommand(mon, "migrate_cancel", &info);
1543

1544 1545
    VIR_FREE(info);
    return ret;
1546
}
1547

1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560

int qemuMonitorTextGraphicsRelocate(qemuMonitorPtr mon,
                                    int type,
                                    const char *hostname,
                                    int port,
                                    int tlsPort,
                                    const char *tlsSubject)
{
    char *cmd;
    char *info = NULL;

    if (virAsprintf(&cmd, "client_migrate_info %s %s %d %d %s",
                    type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ? "spice" : "vnc",
1561
                    hostname, port, tlsPort, tlsSubject ? tlsSubject : "") < 0)
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574
        return -1;

    if (qemuMonitorHMPCommand(mon, cmd, &info) < 0) {
        VIR_FREE(cmd);
        return -1;
    }
    VIR_FREE(cmd);
    VIR_FREE(info);

    return 0;
}


1575 1576 1577
int qemuMonitorTextSendFileHandle(qemuMonitorPtr mon,
                                  const char *fdname,
                                  int fd)
1578 1579 1580 1581 1582
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

1583
    if (virAsprintf(&cmd, "getfd %s", fdname) < 0)
1584 1585
        return -1;

1586
    if (qemuMonitorHMPCommandWithFd(mon, cmd, fd, &reply) < 0)
1587 1588 1589 1590 1591
        goto cleanup;

    /* If the command isn't supported then qemu prints:
     * unknown command: getfd" */
    if (strstr(reply, "unknown command:")) {
1592 1593 1594
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("qemu does not support sending of file handles: %s"),
                       reply);
1595 1596 1597
        goto cleanup;
    }

1598
    if (STRNEQ(reply, "")) {
1599 1600
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unable to send file handle '%s': %s"),
1601
                        fdname, reply);
1602 1603 1604
        goto cleanup;
    }

1605 1606
    ret = 0;

1607
 cleanup:
1608 1609 1610 1611 1612 1613
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}


1614 1615
int qemuMonitorTextCloseFileHandle(qemuMonitorPtr mon,
                                   const char *fdname)
1616 1617 1618 1619 1620
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

1621
    if (virAsprintf(&cmd, "closefd %s", fdname) < 0)
1622 1623
        return -1;

1624
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1625 1626 1627 1628 1629
        goto cleanup;

    /* If the command isn't supported then qemu prints:
     * unknown command: getfd" */
    if (strstr(reply, "unknown command:")) {
1630 1631 1632
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("qemu does not support closing of file handles: %s"),
                       reply);
1633 1634 1635 1636 1637
        goto cleanup;
    }

    ret = 0;

1638
 cleanup:
1639 1640 1641 1642 1643
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}

1644

1645 1646
int qemuMonitorTextAddHostNetwork(qemuMonitorPtr mon,
                                  const char *netstr)
1647 1648 1649 1650 1651
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

1652
    if (virAsprintf(&cmd, "host_net_add %s", netstr) < 0)
1653 1654
        return -1;

1655
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1656 1657
        goto cleanup;

1658
    if (STRNEQ(reply, "")) {
1659 1660 1661
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unable to add host net: %s"),
                       reply);
1662 1663
        goto cleanup;
    }
1664 1665 1666

    ret = 0;

1667
 cleanup:
1668 1669 1670 1671
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}
1672 1673


1674 1675 1676
int qemuMonitorTextRemoveHostNetwork(qemuMonitorPtr mon,
                                     int vlan,
                                     const char *netname)
1677 1678 1679 1680 1681
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

1682
    if (virAsprintf(&cmd, "host_net_remove %d %s", vlan, netname) < 0)
1683 1684
        return -1;

1685
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1686 1687 1688 1689 1690 1691
        goto cleanup;

    /* XXX error messages here ? */

    ret = 0;

1692
 cleanup:
1693 1694 1695 1696
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}
1697 1698


1699 1700 1701 1702 1703 1704 1705
int qemuMonitorTextAddNetdev(qemuMonitorPtr mon,
                             const char *netdevstr)
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

1706
    if (virAsprintf(&cmd, "netdev_add %s", netdevstr) < 0)
1707 1708
        return -1;

1709
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1710 1711 1712 1713 1714 1715
        goto cleanup;

    /* XXX error messages here ? */

    ret = 0;

1716
 cleanup:
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}


int qemuMonitorTextRemoveNetdev(qemuMonitorPtr mon,
                                const char *alias)
{
    char *cmd;
    char *reply = NULL;
    int ret = -1;

1730
    if (virAsprintf(&cmd, "netdev_del %s", alias) < 0)
1731 1732
        return -1;

1733
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1734 1735 1736 1737 1738 1739
        goto cleanup;

    /* XXX error messages here ? */

    ret = 0;

1740
 cleanup:
1741 1742 1743 1744 1745 1746
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}


1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758
/* Parse the output of "info chardev" and return a hash of pty paths.
 *
 * Output is:
 * foo: filename=pty:/dev/pts/7
 * monitor: filename=stdio
 * serial0: filename=vc
 * parallel0: filename=vc
 *
 * Non-pty lines are ignored. In the above example, key is 'foo', value is
 * '/dev/pty/7'. The hash will contain only a single value.
 */

1759 1760
int qemuMonitorTextGetChardevInfo(qemuMonitorPtr mon,
                                  virHashTablePtr info)
1761 1762
{
    char *reply = NULL;
1763
    qemuMonitorChardevInfoPtr entry = NULL;
1764 1765
    int ret = -1;

1766
    if (qemuMonitorHMPCommand(mon, "info chardev", &reply) < 0)
1767
        return -1;
1768

1769 1770
    char *pos;                          /* The current start of searching */
    char *next = reply;                 /* The start of the next line */
1771
    char *eol;                   /* The character which ends the current line */
1772 1773 1774 1775
    char *end = reply + strlen(reply);  /* The end of the reply string */

    while (next) {
        pos = next;
1776 1777 1778

        /* Split the output into lines */
        eol = memchr(pos, '\n', end - pos);
1779
        if (eol == NULL) {
1780
            eol = end;
1781 1782 1783 1784 1785 1786 1787 1788
            next = NULL;
        } else {
            next = eol + 1;
        }

        /* Ignore all whitespace immediately before eol */
        while (eol > pos && c_isspace(*(eol-1)))
            eol -= 1;
1789 1790 1791 1792 1793 1794 1795

        /* Look for 'filename=pty:' */
#define NEEDLE "filename=pty:"
        char *needle = memmem(pos, eol - pos, NEEDLE, strlen(NEEDLE));

        /* If it's not there we can ignore this line */
        if (!needle)
1796
            continue;
1797

J
Ján Tomko 已提交
1798
        /* id is everything from the beginning of the line to the ':'
1799 1800 1801
         * find ':' and turn it into a terminator */
        char *colon = memchr(pos, ':', needle - pos);
        if (colon == NULL)
1802
            continue;
1803 1804 1805 1806 1807
        *colon = '\0';
        char *id = pos;

        /* Path is everything after needle to the end of the line */
        *eol = '\0';
1808 1809 1810 1811 1812

        if (VIR_ALLOC(entry) < 0)
            goto cleanup;

        if (VIR_STRDUP(entry->ptyPath, needle + strlen(NEEDLE)) < 0)
1813
            goto cleanup;
1814

1815
        if (virHashAddEntry(info, id, entry) < 0) {
1816 1817
            virReportError(VIR_ERR_OPERATION_FAILED,
                           _("failed to save chardev path '%s'"),
1818 1819
                           entry->ptyPath);
            VIR_FREE(entry->ptyPath);
1820 1821
            goto cleanup;
        }
1822 1823

        entry = NULL;
1824 1825 1826 1827 1828
#undef NEEDLE
    }

    ret = 0;

1829
 cleanup:
1830
    VIR_FREE(reply);
1831
    VIR_FREE(entry);
1832 1833 1834 1835
    return ret;
}


1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875
/*
 * The format we're after looks like this
 *
 *   (qemu) info pci
 *   Bus  0, device   0, function 0:
 *     Host bridge: PCI device 8086:1237
 *       id ""
 *   Bus  0, device   1, function 0:
 *     ISA bridge: PCI device 8086:7000
 *       id ""
 *   Bus  0, device   1, function 1:
 *     IDE controller: PCI device 8086:7010
 *       BAR4: I/O at 0xc000 [0xc00f].
 *       id ""
 *   Bus  0, device   1, function 3:
 *     Bridge: PCI device 8086:7113
 *       IRQ 9.
 *       id ""
 *   Bus  0, device   2, function 0:
 *     VGA controller: PCI device 1013:00b8
 *       BAR0: 32 bit prefetchable memory at 0xf0000000 [0xf1ffffff].
 *       BAR1: 32 bit memory at 0xf2000000 [0xf2000fff].
 *       id ""
 *   Bus  0, device   3, function 0:
 *     Ethernet controller: PCI device 8086:100e
 *      IRQ 11.
 *      BAR0: 32 bit memory at 0xf2020000 [0xf203ffff].
 *      BAR1: I/O at 0xc040 [0xc07f].
 *       id ""
 *
 * Of this, we're interesting in the vendor/product ID
 * and the bus/device/function data.
 */
#define CHECK_END(p) if (!(p)) break;
#define SKIP_TO(p, lbl)                                            \
    (p) = strstr((p), (lbl));                                      \
    if (p)                                                         \
        (p) += strlen(lbl);
#define GET_INT(p, base, val)                                           \
    if (virStrToLong_ui((p), &(p), (base), &(val)) < 0) {               \
1876 1877
        virReportError(VIR_ERR_OPERATION_FAILED,                       \
                       _("cannot parse value for %s"), #val);           \
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
        break;                                                          \
    }
#define SKIP_SPACE(p)                           \
    while (*(p) == ' ') (p)++;

int qemuMonitorTextGetAllPCIAddresses(qemuMonitorPtr mon,
                                      qemuMonitorPCIAddress **retaddrs)
{
    char *reply;
    qemuMonitorPCIAddress *addrs = NULL;
    int naddrs = 0;
    char *p;

    *retaddrs = NULL;

1893
    if (qemuMonitorHMPCommand(mon, "info pci", &reply) < 0)
1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
        return -1;

    p = reply;


    while (p) {
        unsigned int bus, slot, func, vendor, product;

        SKIP_TO(p, "  Bus");
        CHECK_END(p);
        SKIP_SPACE(p);
        GET_INT(p, 10, bus);
        CHECK_END(p);

        SKIP_TO(p, ", device");
        CHECK_END(p);
        SKIP_SPACE(p);
        GET_INT(p, 10, slot);
        CHECK_END(p);

        SKIP_TO(p, ", function");
        CHECK_END(p);
        SKIP_SPACE(p);
        GET_INT(p, 10, func);
        CHECK_END(p);

        SKIP_TO(p, "PCI device");
        CHECK_END(p);
        SKIP_SPACE(p);
        GET_INT(p, 16, vendor);
        CHECK_END(p);

        if (*p != ':')
            break;
        p++;
        GET_INT(p, 16, product);

1931
        if (VIR_REALLOC_N(addrs, naddrs+1) < 0)
1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950
            goto error;

        addrs[naddrs].addr.domain = 0;
        addrs[naddrs].addr.bus = bus;
        addrs[naddrs].addr.slot = slot;
        addrs[naddrs].addr.function = func;
        addrs[naddrs].vendor = vendor;
        addrs[naddrs].product = product;
        naddrs++;

        VIR_DEBUG("Got dev %d:%d:%d   %x:%x", bus, slot, func, vendor, product);
    }

    VIR_FREE(reply);

    *retaddrs = addrs;

    return naddrs;

1951
 error:
1952 1953 1954 1955 1956 1957 1958 1959
    VIR_FREE(addrs);
    VIR_FREE(reply);
    return -1;
}
#undef GET_INT
#undef SKIP_SPACE
#undef CHECK_END
#undef SKIP_TO
1960 1961


1962
int qemuMonitorTextDelDevice(qemuMonitorPtr mon,
1963
                             const char *devalias)
1964 1965 1966 1967 1968 1969
{
    char *cmd = NULL;
    char *reply = NULL;
    char *safedev;
    int ret = -1;

1970
    if (!(safedev = qemuMonitorEscapeArg(devalias)))
1971 1972
        goto cleanup;

1973
    if (virAsprintf(&cmd, "device_del %s", safedev) < 0)
1974 1975
        goto cleanup;

1976
    VIR_DEBUG("TextDelDevice devalias=%s", devalias);
1977
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
1978 1979 1980
        goto cleanup;

    if (STRNEQ(reply, "")) {
1981 1982
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("detaching %s device failed: %s"), devalias, reply);
1983 1984 1985 1986 1987
        goto cleanup;
    }

    ret = 0;

1988
 cleanup:
1989 1990 1991 1992 1993 1994 1995
    VIR_FREE(cmd);
    VIR_FREE(reply);
    VIR_FREE(safedev);
    return ret;
}


1996 1997 1998 1999 2000 2001 2002 2003
int qemuMonitorTextAddDevice(qemuMonitorPtr mon,
                             const char *devicestr)
{
    char *cmd = NULL;
    char *reply = NULL;
    char *safedev;
    int ret = -1;

2004
    if (!(safedev = qemuMonitorEscapeArg(devicestr)))
2005 2006
        goto cleanup;

2007
    if (virAsprintf(&cmd, "device_add %s", safedev) < 0)
2008 2009
        goto cleanup;

2010
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
2011 2012
        goto cleanup;

2013 2014 2015 2016 2017 2018 2019 2020 2021
    /* If the host device is hotpluged first time, qemu will output
     * husb: using %s file-system with %s if the command succeeds.
     */
    if (STRPREFIX(reply, "husb: using")) {
        ret = 0;
        goto cleanup;
    }

    /* Otherwise, if the command succeeds, no output is sent. So
2022 2023
     * any non-empty string shows an error */
    if (STRNEQ(reply, "")) {
2024 2025
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("adding %s device failed: %s"), devicestr, reply);
2026 2027 2028 2029 2030
        goto cleanup;
    }

    ret = 0;

2031
 cleanup:
2032 2033
    VIR_FREE(cmd);
    VIR_FREE(reply);
2034
    VIR_FREE(safedev);
2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047
    return ret;
}


int qemuMonitorTextAddDrive(qemuMonitorPtr mon,
                            const char *drivestr)
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;
    char *safe_str;

    safe_str = qemuMonitorEscapeArg(drivestr);
2048
    if (!safe_str)
2049 2050 2051 2052
        return -1;

    /* 'dummy' here is just a placeholder since there is no PCI
     * address required when attaching drives to a controller */
2053
    if (virAsprintf(&cmd, "drive_add dummy %s", safe_str) < 0)
2054 2055
        goto cleanup;

2056
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
2057 2058
        goto cleanup;

2059
    if (strstr(reply, "unknown command:")) {
2060 2061
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("drive hotplug is not supported"));
2062 2063 2064
        goto cleanup;
    }

2065
    if (strstr(reply, "could not open disk image")) {
2066 2067
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("open disk image file failed"));
2068 2069 2070
        goto cleanup;
    }

2071 2072
    ret = 0;

2073
 cleanup:
2074 2075 2076 2077 2078
    VIR_FREE(cmd);
    VIR_FREE(reply);
    VIR_FREE(safe_str);
    return ret;
}
2079

2080

2081 2082
int qemuMonitorTextDriveDel(qemuMonitorPtr mon,
                            const char *drivestr)
2083 2084 2085 2086 2087 2088
{
    char *cmd = NULL;
    char *reply = NULL;
    char *safedev;
    int ret = -1;

2089
    if (!(safedev = qemuMonitorEscapeArg(drivestr)))
2090 2091
        goto cleanup;

2092
    if (virAsprintf(&cmd, "drive_del %s", safedev) < 0)
2093 2094
        goto cleanup;

2095
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
2096 2097 2098
        goto cleanup;

    if (strstr(reply, "unknown command:")) {
2099
        VIR_ERROR(_("deleting drive is not supported.  "
2100 2101 2102
                    "This may leak data if disk is reassigned"));
        ret = 1;
        goto cleanup;
2103 2104 2105

    /* (qemu) drive_del wark
     * Device 'wark' not found */
2106
    } else if (strstr(reply, "Device '") && strstr(reply, "not found")) {
2107 2108
        /* NB: device not found errors mean the drive was auto-deleted and we
         * ignore the error */
2109
    } else if (STRNEQ(reply, "")) {
2110 2111
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("deleting %s drive failed: %s"), drivestr, reply);
2112 2113 2114 2115 2116
        goto cleanup;
    }

    ret = 0;

2117
 cleanup:
2118 2119 2120 2121 2122
    VIR_FREE(cmd);
    VIR_FREE(reply);
    VIR_FREE(safedev);
    return ret;
}
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133

int qemuMonitorTextSetDrivePassphrase(qemuMonitorPtr mon,
                                      const char *alias,
                                      const char *passphrase)
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;
    char *safe_str;

    safe_str = qemuMonitorEscapeArg(passphrase);
2134
    if (!safe_str)
2135 2136
        return -1;

2137
    if (virAsprintf(&cmd, "block_passwd %s%s \"%s\"",
2138
                    QEMU_DRIVE_HOST_PREFIX, alias, safe_str) < 0)
2139 2140
        goto cleanup;

2141
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
2142 2143
        goto cleanup;

2144
    if (strstr(reply, "unknown command:")) {
2145 2146
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("setting disk password is not supported"));
2147 2148
        goto cleanup;
    } else if (strstr(reply, "The entered password is invalid")) {
2149 2150
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("the disk password is incorrect"));
2151 2152 2153 2154 2155
        goto cleanup;
    }

    ret = 0;

2156
 cleanup:
2157 2158 2159 2160 2161
    VIR_FREE(cmd);
    VIR_FREE(reply);
    VIR_FREE(safe_str);
    return ret;
}
C
Chris Lalancette 已提交
2162

2163 2164 2165 2166

int
qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon,
                              const char *name)
C
Chris Lalancette 已提交
2167
{
2168
    char *cmd = NULL;
C
Chris Lalancette 已提交
2169 2170
    char *reply = NULL;
    int ret = -1;
2171
    char *safename;
C
Chris Lalancette 已提交
2172

2173
    if (!(safename = qemuMonitorEscapeArg(name)) ||
2174
        virAsprintf(&cmd, "savevm \"%s\"", safename) < 0)
2175
        goto cleanup;
C
Chris Lalancette 已提交
2176

2177
    if (qemuMonitorHMPCommand(mon, cmd, &reply))
C
Chris Lalancette 已提交
2178 2179
        goto cleanup;

2180 2181
    if (strstr(reply, "Error while creating snapshot") ||
        strstr(reply, "Could not open VM state file") ||
2182
        strstr(reply, "State blocked by non-migratable device") ||
2183
        (strstr(reply, "Error") && strstr(reply, "while writing VM"))) {
2184 2185
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("Failed to take snapshot: %s"), reply);
C
Chris Lalancette 已提交
2186
        goto cleanup;
2187
    } else if (strstr(reply, "No block device can accept snapshots")) {
2188 2189
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("this domain does not have a device to take snapshots"));
C
Chris Lalancette 已提交
2190 2191 2192 2193 2194
        goto cleanup;
    }

    ret = 0;

2195
 cleanup:
2196
    VIR_FREE(safename);
C
Chris Lalancette 已提交
2197 2198 2199 2200 2201 2202 2203
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}

int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name)
{
2204
    char *cmd = NULL;
C
Chris Lalancette 已提交
2205 2206
    char *reply = NULL;
    int ret = -1;
2207
    char *safename;
C
Chris Lalancette 已提交
2208

2209
    if (!(safename = qemuMonitorEscapeArg(name)) ||
2210
        virAsprintf(&cmd, "loadvm \"%s\"", safename) < 0)
2211
        goto cleanup;
C
Chris Lalancette 已提交
2212

2213
    if (qemuMonitorHMPCommand(mon, cmd, &reply))
C
Chris Lalancette 已提交
2214 2215 2216
        goto cleanup;

    if (strstr(reply, "No block device supports snapshots") != NULL) {
2217 2218
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("this domain does not have a device to load snapshots"));
C
Chris Lalancette 已提交
2219
        goto cleanup;
2220
    } else if (strstr(reply, "Could not find snapshot") != NULL) {
2221 2222 2223
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("the snapshot '%s' does not exist, and was not loaded"),
                       name);
C
Chris Lalancette 已提交
2224
        goto cleanup;
2225
    } else if (strstr(reply, "Snapshots not supported on device") != NULL) {
2226
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", reply);
C
Chris Lalancette 已提交
2227
        goto cleanup;
2228
    } else if (strstr(reply, "Could not open VM state file") != NULL) {
2229
        virReportError(VIR_ERR_OPERATION_FAILED, "%s", reply);
C
Chris Lalancette 已提交
2230
        goto cleanup;
2231
    } else if (strstr(reply, "Error") != NULL
C
Chris Lalancette 已提交
2232
             && strstr(reply, "while loading VM state") != NULL) {
2233
        virReportError(VIR_ERR_OPERATION_FAILED, "%s", reply);
C
Chris Lalancette 已提交
2234
        goto cleanup;
2235
    } else if (strstr(reply, "Error") != NULL
C
Chris Lalancette 已提交
2236
             && strstr(reply, "while activating snapshot on") != NULL) {
2237
        virReportError(VIR_ERR_OPERATION_FAILED, "%s", reply);
C
Chris Lalancette 已提交
2238 2239 2240 2241 2242
        goto cleanup;
    }

    ret = 0;

2243
 cleanup:
2244
    VIR_FREE(safename);
C
Chris Lalancette 已提交
2245 2246 2247 2248 2249 2250 2251
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}

int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name)
{
2252
    char *cmd = NULL;
C
Chris Lalancette 已提交
2253 2254
    char *reply = NULL;
    int ret = -1;
2255
    char *safename;
C
Chris Lalancette 已提交
2256

2257
    if (!(safename = qemuMonitorEscapeArg(name)) ||
2258
        virAsprintf(&cmd, "delvm \"%s\"", safename) < 0)
2259
        goto cleanup;
2260
    if (qemuMonitorHMPCommand(mon, cmd, &reply))
C
Chris Lalancette 已提交
2261 2262 2263
        goto cleanup;

    if (strstr(reply, "No block device supports snapshots") != NULL) {
2264 2265
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("this domain does not have a device to delete snapshots"));
C
Chris Lalancette 已提交
2266
        goto cleanup;
2267
    } else if (strstr(reply, "Snapshots not supported on device") != NULL) {
2268
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", reply);
C
Chris Lalancette 已提交
2269
        goto cleanup;
2270
    } else if (strstr(reply, "Error") != NULL
C
Chris Lalancette 已提交
2271
             && strstr(reply, "while deleting snapshot") != NULL) {
2272
        virReportError(VIR_ERR_OPERATION_FAILED, "%s", reply);
C
Chris Lalancette 已提交
2273 2274 2275 2276 2277
        goto cleanup;
    }

    ret = 0;

2278
 cleanup:
2279
    VIR_FREE(safename);
C
Chris Lalancette 已提交
2280 2281 2282 2283
    VIR_FREE(cmd);
    VIR_FREE(reply);
    return ret;
}
2284

2285

2286 2287 2288 2289 2290 2291
int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
                                    char **reply)
{
    char *safecmd = NULL;
    int ret;

2292
    if (!(safecmd = qemuMonitorEscapeArg(cmd)))
2293 2294
        return -1;

2295
    ret = qemuMonitorHMPCommand(mon, safecmd, reply);
2296 2297 2298 2299 2300

    VIR_FREE(safecmd);

    return ret;
}
2301 2302 2303 2304 2305

int qemuMonitorTextInjectNMI(qemuMonitorPtr mon)
{
    char *reply = NULL;

2306 2307
    if (qemuMonitorHMPCommand(mon, "inject-nmi", &reply) < 0)
        return -1;
2308 2309 2310 2311 2312

    if (strstr(reply, "unknown command") != NULL) {
        VIR_FREE(reply);

        /* fallback to 'nmi' if qemu has not supported "inject-nmi" yet. */
2313 2314
        if (qemuMonitorHMPCommand(mon, "nmi 0", &reply) < 0)
            return -1;
2315 2316 2317 2318 2319
    }

    VIR_FREE(reply);
    return 0;
}
2320

2321 2322 2323 2324 2325
int qemuMonitorTextSendKey(qemuMonitorPtr mon,
                           unsigned int holdtime,
                           unsigned int *keycodes,
                           unsigned int nkeycodes)
{
2326
    size_t i;
2327 2328
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *cmd, *reply = NULL;
2329
    int ret = -1;
2330 2331 2332 2333 2334 2335 2336

    if (nkeycodes > VIR_DOMAIN_SEND_KEY_MAX_KEYS || nkeycodes == 0)
        return -1;

    virBufferAddLit(&buf, "sendkey ");
    for (i = 0; i < nkeycodes; i++) {
        if (keycodes[i] > 0xffff) {
2337
            virReportError(VIR_ERR_OPERATION_FAILED,
2338
                           _("keycode %zu is invalid: 0x%X"),
2339
                           i, keycodes[i]);
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351
            virBufferFreeAndReset(&buf);
            return -1;
        }

        if (i)
            virBufferAddChar(&buf, '-');
        virBufferAsprintf(&buf, "0x%02X", keycodes[i]);
    }

    if (holdtime)
        virBufferAsprintf(&buf, " %u", holdtime);

2352
    if (virBufferCheckError(&buf) < 0)
2353 2354 2355
        return -1;

    cmd = virBufferContentAndReset(&buf);
2356
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
2357 2358 2359
        goto cleanup;

    if (STRNEQ(reply, "")) {
2360 2361
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("failed to send key '%s'"), reply);
2362
        goto cleanup;
2363 2364
    }

2365 2366
    ret = 0;

2367
 cleanup:
2368 2369
    VIR_FREE(cmd);
    VIR_FREE(reply);
2370
    return ret;
2371 2372
}

2373 2374 2375 2376 2377 2378 2379
/* Returns -1 on error, -2 if not supported */
int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file)
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;

2380
    if (virAsprintf(&cmd, "screendump %s", file) < 0)
2381 2382
        goto cleanup;

2383
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
2384 2385 2386 2387 2388 2389 2390 2391 2392
        goto cleanup;

    if (strstr(reply, "unknown command:")) {
        ret = -2;
        goto cleanup;
    }

    ret = 0;

2393
 cleanup:
2394 2395 2396 2397
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}
2398

2399 2400 2401 2402 2403 2404 2405 2406 2407 2408

int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon,
                                const char *protocol,
                                const char *fdname,
                                bool skipauth)
{
    char *cmd = NULL;
    char *reply = NULL;
    int ret = -1;

2409
    if (virAsprintf(&cmd, "add_client %s %s %d", protocol, fdname, skipauth ? 0 : 1) < 0)
2410 2411
        goto cleanup;

2412
    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
2413 2414 2415 2416 2417 2418 2419
        goto cleanup;

    if (STRNEQ(reply, ""))
        goto cleanup;

    ret = 0;

2420
 cleanup:
2421 2422 2423 2424
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}
2425 2426 2427 2428 2429 2430 2431 2432


int qemuMonitorTextSetBlockIoThrottle(qemuMonitorPtr mon,
                                      const char *device,
                                      virDomainBlockIoTuneInfoPtr info)
{
    char *cmd = NULL;
    char *result = NULL;
2433
    int ret = -1;
2434 2435 2436 2437
    const char *cmd_name = NULL;

    /* For the not specified fields, 0 by default */
    cmd_name = "block_set_io_throttle";
2438 2439 2440
    if (virAsprintf(&cmd, "%s %s %llu %llu %llu %llu %llu %llu", cmd_name,
                    device, info->total_bytes_sec, info->read_bytes_sec,
                    info->write_bytes_sec, info->total_iops_sec,
2441
                    info->read_iops_sec, info->write_iops_sec) < 0)
2442
        goto cleanup;
2443

2444
    if (qemuMonitorHMPCommand(mon, cmd, &result) < 0)
2445 2446 2447
        goto cleanup;

    if (qemuMonitorTextCommandNotFound(cmd_name, result)) {
2448 2449
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Command '%s' is not found"), cmd_name);
2450 2451
        goto cleanup;
    }
2452
    ret = 0;
2453

2454
 cleanup:
2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511
    VIR_FREE(cmd);
    VIR_FREE(result);
    return ret;
}

static int
qemuMonitorTextParseBlockIoThrottle(const char *result,
                                    const char *device,
                                    virDomainBlockIoTuneInfoPtr reply)
{
    char *dummy = NULL;
    int ret = -1;
    const char *p, *eol;
    int devnamelen = strlen(device);

    p = result;

    while (*p) {
        if (STREQLEN(p, device, devnamelen) &&
            p[devnamelen] == ':' && p[devnamelen+1] == ' ') {

            eol = strchr(p, '\n');
            if (!eol)
                eol = p + strlen(p);

            p += devnamelen + 2; /* Skip to first label. */

            while (*p) {
                if (STRPREFIX(p, "bps=")) {
                    p += strlen("bps=");
                    if (virStrToLong_ull(p, &dummy, 10, &reply->total_bytes_sec) == -1)
                        VIR_DEBUG("error reading total_bytes_sec: %s", p);
                } else if (STRPREFIX(p, "bps_rd=")) {
                    p += strlen("bps_rd=");
                    if (virStrToLong_ull(p, &dummy, 10, &reply->read_bytes_sec)  == -1)
                        VIR_DEBUG("error reading read_bytes_sec: %s", p);
                } else if (STRPREFIX(p, "bps_wr=")) {
                    p += strlen("bps_wr=");
                    if (virStrToLong_ull(p, &dummy, 10, &reply->write_bytes_sec) == -1)
                        VIR_DEBUG("error reading write_bytes_sec: %s", p);
                } else if (STRPREFIX(p, "iops=")) {
                    p += strlen("iops=");
                    if (virStrToLong_ull(p, &dummy, 10, &reply->total_iops_sec) == -1)
                        VIR_DEBUG("error reading total_iops_sec: %s", p);
                } else if (STRPREFIX(p, "iops_rd=")) {
                    p += strlen("iops_rd=");
                    if (virStrToLong_ull(p, &dummy, 10, &reply->read_iops_sec) == -1)
                        VIR_DEBUG("error reading read_iops_sec: %s", p);
                } else if (STRPREFIX(p, "iops_wr=")) {
                    p += strlen("iops_wr=");
                    if (virStrToLong_ull(p, &dummy, 10, &reply->write_iops_sec) == -1)
                        VIR_DEBUG("error reading write_iops_sec: %s", p);
                } else {
                    VIR_DEBUG(" unknown block info %s", p);
                }

                /* Skip to next label. */
2512
                p = strchr(p, ' ');
2513 2514 2515 2516 2517 2518 2519 2520 2521
                if (!p || p >= eol)
                    break;
                p++;
            }
            ret = 0;
            goto cleanup;
        }

        /* Skip to next line. */
2522
        p = strchr(p, '\n');
2523 2524 2525 2526 2527
        if (!p)
            break;
        p++;
    }

2528 2529
    virReportError(VIR_ERR_INVALID_ARG,
                   _("No info for device '%s'"), device);
2530

2531
 cleanup:
2532 2533 2534 2535 2536 2537 2538 2539
    return ret;
}

int qemuMonitorTextGetBlockIoThrottle(qemuMonitorPtr mon,
                                      const char *device,
                                      virDomainBlockIoTuneInfoPtr reply)
{
    char *result = NULL;
2540
    int ret = -1;
2541 2542
    const char *cmd_name = "info block";

2543
    if (qemuMonitorHMPCommand(mon, cmd_name, &result) < 0)
2544 2545 2546
        goto cleanup;

    if (qemuMonitorTextCommandNotFound(cmd_name, result)) {
2547 2548
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Command '%s' is not found"), cmd_name);
2549 2550 2551 2552 2553
        goto cleanup;
    }

    ret = qemuMonitorTextParseBlockIoThrottle(result, device, reply);

2554
 cleanup:
2555 2556 2557
    VIR_FREE(result);
    return ret;
}