qemu_driver.c 135.3 KB
Newer Older
D
Daniel P. Berrange 已提交
1 2 3
/*
 * driver.c: core driver methods for managing qemu guests
 *
4
 * Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
D
Daniel P. Berrange 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

24
#include <config.h>
25

D
Daniel P. Berrange 已提交
26 27 28 29 30 31 32 33 34 35 36
#include <sys/types.h>
#include <sys/poll.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <strings.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
37
#include <sys/utsname.h>
38 39 40 41
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
42 43
#include <pwd.h>
#include <stdio.h>
44
#include <sys/wait.h>
45
#include <sys/ioctl.h>
D
Daniel P. Berrange 已提交
46

47
#if HAVE_NUMACTL
48
#define NUMA_VERSION1_COMPATIBILITY 1
49 50 51
#include <numa.h>
#endif

52 53 54 55
#if HAVE_SCHED_H
#include <sched.h>
#endif

56
#include "virterror_internal.h"
57
#include "logging.h"
58
#include "datatypes.h"
59 60
#include "qemu_driver.h"
#include "qemu_conf.h"
J
Jim Meyering 已提交
61
#include "c-ctype.h"
62
#include "event.h"
63
#include "buf.h"
64
#include "util.h"
65
#include "nodeinfo.h"
66
#include "stats_linux.h"
67
#include "capabilities.h"
68
#include "memory.h"
69
#include "uuid.h"
70
#include "domain_conf.h"
71

72 73
#define VIR_FROM_THIS VIR_FROM_QEMU

R
Richard W.M. Jones 已提交
74 75 76
/* For storing short-lived temporary files. */
#define TEMPDIR LOCAL_STATE_DIR "/cache/libvirt"

77 78 79 80
#define QEMU_CMD_PROMPT "\n(qemu) "
#define QEMU_PASSWD_PROMPT "Password: "


81 82
static int qemudShutdown(void);

83 84
#define qemudLog(level, msg...) fprintf(stderr, msg)

85 86
static void qemuDriverLock(struct qemud_driver *driver)
{
87
    virMutexLock(&driver->lock);
88 89 90
}
static void qemuDriverUnlock(struct qemud_driver *driver)
{
91
    virMutexUnlock(&driver->lock);
92 93
}

94 95 96
static void qemuDomainEventFlush(int timer, void *opaque);
static void qemuDomainEventQueue(struct qemud_driver *driver,
                                 virDomainEventPtr event);
97

98 99
static void qemudDispatchVMEvent(int watch,
                                 int fd,
100 101 102
                                 int events,
                                 void *opaque);

103 104
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
105
                              virDomainObjPtr vm,
106 107
                              const char *migrateFrom,
                              int stdin_fd);
108

109 110
static void qemudShutdownVMDaemon(virConnectPtr conn,
                                  struct qemud_driver *driver,
111
                                  virDomainObjPtr vm);
112

113
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
114

115 116 117 118 119 120 121 122
static int qemudMonitorCommand(const virDomainObjPtr vm,
                               const char *cmd,
                               char **reply);
static int qemudMonitorCommandExtra(const virDomainObjPtr vm,
                                    const char *cmd,
                                    const char *extra,
                                    const char *extraPrompt,
                                    char **reply);
123

J
Jim Meyering 已提交
124
static struct qemud_driver *qemu_driver = NULL;
125 126


127 128 129 130 131 132
static int
qemudLogFD(virConnectPtr conn, const char* logDir, const char* name)
{
    char logfile[PATH_MAX];
    mode_t logmode;
    uid_t uid = geteuid();
G
Guido Günther 已提交
133
    int ret, fd = -1;
134

G
Guido Günther 已提交
135 136
    if ((ret = snprintf(logfile, sizeof(logfile), "%s/%s.log", logDir, name))
        < 0 || ret >= sizeof(logfile)) {
137
        virReportOOMError(conn);
138 139 140 141 142 143 144 145 146
        return -1;
    }

    logmode = O_CREAT | O_WRONLY;
    if (uid != 0)
        logmode |= O_TRUNC;
    else
        logmode |= O_APPEND;
    if ((fd = open(logfile, logmode, S_IRUSR | S_IWUSR)) < 0) {
147 148 149
        virReportSystemError(conn, errno,
                             _("failed to create logfile %s"),
                             logfile);
150 151
        return -1;
    }
152
    if (virSetCloseExec(fd) < 0) {
153 154
        virReportSystemError(conn, errno, "%s",
                             _("Unable to set VM logfile close-on-exec flag"));
155 156 157 158 159 160 161
        close(fd);
        return -1;
    }
    return fd;
}


162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
static int
qemudLogReadFD(virConnectPtr conn, const char* logDir, const char* name, off_t pos)
{
    char logfile[PATH_MAX];
    mode_t logmode = O_RDONLY;
    int ret, fd = -1;

    if ((ret = snprintf(logfile, sizeof(logfile), "%s/%s.log", logDir, name))
        < 0 || ret >= sizeof(logfile)) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("failed to build logfile name %s/%s.log"),
                         logDir, name);
        return -1;
    }


    if ((fd = open(logfile, logmode)) < 0) {
179 180 181
        virReportSystemError(conn, errno,
                             _("failed to create logfile %s"),
                             logfile);
182 183
        return -1;
    }
184
    if (virSetCloseExec(fd) < 0) {
185 186
        virReportSystemError(conn, errno, "%s",
                             _("Unable to set VM logfile close-on-exec flag"));
187 188 189 190
        close(fd);
        return -1;
    }
    if (lseek(fd, pos, SEEK_SET) < 0) {
191 192 193
        virReportSystemError(conn, errno,
                             _("Unable to seek to %lld in %s"),
                             (long long) pos, logfile);
194 195 196 197 198 199
        close(fd);
    }
    return fd;
}


200 201 202
static void
qemudAutostartConfigs(struct qemud_driver *driver) {
    unsigned int i;
203 204 205 206 207 208 209 210 211
    /* XXX: Figure out a better way todo this. The domain
     * startup code needs a connection handle in order
     * to lookup the bridge associated with a virtual
     * network
     */
    virConnectPtr conn = virConnectOpen(getuid() ?
                                        "qemu:///session" :
                                        "qemu:///system");
    /* Ignoring NULL conn which is mostly harmless here */
212 213

    for (i = 0 ; i < driver->domains.count ; i++) {
214
        virDomainObjPtr vm = driver->domains.objs[i];
215
        virDomainObjLock(vm);
216 217
        if (vm->autostart &&
            !virDomainIsActive(vm)) {
218
            int ret = qemudStartVMDaemon(conn, driver, vm, NULL, -1);
219 220
            if (ret < 0) {
                virErrorPtr err = virGetLastError();
221
                qemudLog(QEMUD_ERROR, _("Failed to autostart VM '%s': %s\n"),
222 223 224
                         vm->def->name,
                         err ? err->message : NULL);
            } else {
225 226 227 228 229 230
                virDomainEventPtr event =
                    virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STARTED,
                                             VIR_DOMAIN_EVENT_STARTED_BOOTED);
                if (event)
                    qemuDomainEventQueue(driver, event);
231
            }
232
        }
233
        virDomainObjUnlock(vm);
234
    }
235 236

    virConnectClose(conn);
237 238
}

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

/**
 * qemudRemoveDomainStatus
 *
 * remove all state files of a domain from statedir
 *
 * Returns 0 on success
 */
static int
qemudRemoveDomainStatus(virConnectPtr conn,
                        struct qemud_driver *driver,
                        virDomainObjPtr vm)
{
    int rc = -1;
    char *file = NULL;

    if (virAsprintf(&file, "%s/%s.xml", driver->stateDir, vm->def->name) < 0) {
256
        virReportOOMError(conn);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
        goto cleanup;
    }

    if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) {
        qemudReportError(conn, vm, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Failed to unlink status file %s"), file);
        goto cleanup;
    }

    if(virFileDeletePid(driver->stateDir, vm->def->name))
        goto cleanup;

    rc = 0;
cleanup:
    VIR_FREE(file);
    return rc;
}


276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
static int qemudOpenMonitor(virConnectPtr conn,
                            struct qemud_driver* driver,
                            virDomainObjPtr vm,
                            const char *monitor,
                            int reconnect);

/**
 * qemudReconnectVMs
 *
 * Reconnect running vms to the daemon process
 */
static int
qemudReconnectVMs(struct qemud_driver *driver)
{
    int i;

    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjPtr vm = driver->domains.objs[i];
        qemudDomainStatusPtr status = NULL;
        char *config = NULL;
        int rc;

        virDomainObjLock(vm);
        if ((rc = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0)
            DEBUG("Found pid %d for '%s'", vm->pid, vm->def->name);
        else
            goto next;

        if ((config = virDomainConfigFile(NULL,
                                          driver->stateDir,
                                          vm->def->name)) == NULL) {
307
            qemudLog(QEMUD_ERROR, _("Failed to read domain status for %s\n"),
308 309 310 311 312 313 314 315 316
                     vm->def->name);
            goto next_error;
        }

        status = qemudDomainStatusParseFile(NULL, driver->caps, config, 0);
        if (status) {
            vm->newDef = vm->def;
            vm->def = status->def;
        } else {
317
            qemudLog(QEMUD_ERROR, _("Failed to parse domain status for %s\n"),
318 319 320 321 322
                     vm->def->name);
            goto next_error;
        }

        if ((rc = qemudOpenMonitor(NULL, driver, vm, status->monitorpath, 1)) != 0) {
323
            qemudLog(QEMUD_ERROR, _("Failed to reconnect monitor for %s: %d\n"),
324 325
                     vm->def->name, rc);
            goto next_error;
326
        }
327

328
        if ((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0)
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
            return -1;

        if (vm->def->id >= driver->nextvmid)
            driver->nextvmid = vm->def->id + 1;

        vm->state = status->state;
        goto next;

next_error:
        /* we failed to reconnect the vm so remove it's traces */
        vm->def->id = -1;
        qemudRemoveDomainStatus(NULL, driver, vm);
        virDomainDefFree(vm->def);
        vm->def = vm->newDef;
        vm->newDef = NULL;
next:
        virDomainObjUnlock(vm);
346 347
        if (status)
            VIR_FREE(status->monitorpath);
348 349 350 351 352 353 354
        VIR_FREE(status);
        VIR_FREE(config);
    }
    return 0;
}


355 356 357 358 359 360 361
/**
 * qemudStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
qemudStartup(void) {
362 363
    uid_t uid = geteuid();
    char *base = NULL;
D
Daniel P. Berrange 已提交
364
    char driverConf[PATH_MAX];
365

366
    if (VIR_ALLOC(qemu_driver) < 0)
367 368
        return -1;

369 370 371 372 373
    if (virMutexInit(&qemu_driver->lock) < 0) {
        qemudLog(QEMUD_ERROR, "%s", _("cannot initialize mutex"));
        VIR_FREE(qemu_driver);
        return -1;
    }
374 375
    qemuDriverLock(qemu_driver);

376 377 378
    /* Don't have a dom0 so start from 1 */
    qemu_driver->nextvmid = 1;

379 380
    /* Init callback list */
    if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
381
        goto out_of_memory;
382 383 384 385 386 387
    if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew()))
        goto out_of_memory;

    if ((qemu_driver->domainEventTimer =
         virEventAddTimeout(-1, qemuDomainEventFlush, qemu_driver, NULL)) < 0)
        goto error;
388

389
    if (!uid) {
390 391
        if (virAsprintf(&qemu_driver->logDir,
                        "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
392
            goto out_of_memory;
393

D
Daniel P. Berrange 已提交
394
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
395
            goto out_of_memory;
396 397 398 399

        if (virAsprintf(&qemu_driver->stateDir,
                      "%s/run/libvirt/qemu/", LOCAL_STATE_DIR) == -1)
            goto out_of_memory;
400
    } else {
401 402
        char *userdir = virGetUserDirectory(NULL, uid);
        if (!userdir)
403
            goto error;
404

405
        if (virAsprintf(&qemu_driver->logDir,
406 407
                        "%s/.libvirt/qemu/log", userdir) == -1) {
            VIR_FREE(userdir);
408
            goto out_of_memory;
409
        }
410

411 412
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
            VIR_FREE(userdir);
413
            goto out_of_memory;
414 415
        }
        VIR_FREE(userdir);
416 417 418 419 420 421

        if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", base) == -1)
            goto out_of_memory;
    }

    if (virFileMakePath(qemu_driver->stateDir) < 0) {
422
        char ebuf[1024];
423
        qemudLog(QEMUD_ERROR, _("Failed to create state dir '%s': %s\n"),
424
                 qemu_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
425
        goto error;
426 427 428 429 430
    }

    /* Configuration paths are either ~/.libvirt/qemu/... (session) or
     * /etc/libvirt/qemu/... (system).
     */
D
Daniel P. Berrange 已提交
431
    if (snprintf (driverConf, sizeof(driverConf), "%s/qemu.conf", base) == -1)
432
        goto out_of_memory;
D
Daniel P. Berrange 已提交
433
    driverConf[sizeof(driverConf)-1] = '\0';
434

435
    if (virAsprintf(&qemu_driver->configDir, "%s/qemu", base) == -1)
436 437
        goto out_of_memory;

438
    if (virAsprintf(&qemu_driver->autostartDir, "%s/qemu/autostart", base) == -1)
439 440
        goto out_of_memory;

441
    VIR_FREE(base);
442 443 444

    if ((qemu_driver->caps = qemudCapsInit()) == NULL)
        goto out_of_memory;
D
Daniel P. Berrange 已提交
445 446

    if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
447
        goto error;
D
Daniel P. Berrange 已提交
448 449
    }

450 451 452 453
    if (virDomainLoadAllConfigs(NULL,
                                qemu_driver->caps,
                                &qemu_driver->domains,
                                qemu_driver->configDir,
454
                                qemu_driver->autostartDir,
455 456
                                NULL, NULL) < 0)
        goto error;
457
    qemudReconnectVMs(qemu_driver);
458 459
    qemudAutostartConfigs(qemu_driver);

460 461
    qemuDriverUnlock(qemu_driver);

462 463
    return 0;

464
out_of_memory:
465
    virReportOOMError(NULL);
466 467 468
error:
    if (qemu_driver)
        qemuDriverUnlock(qemu_driver);
469
    VIR_FREE(base);
470
    qemudShutdown();
471 472 473
    return -1;
}

474 475 476 477
static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
{
    struct qemud_driver *driver = opaque;

478 479 480 481 482 483 484 485
    if (newVM) {
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }
486 487
}

488 489 490 491 492 493 494 495
/**
 * qemudReload:
 *
 * Function to restart the QEmu daemon, it will recheck the configuration
 * files and update its state and the networking
 */
static int
qemudReload(void) {
496 497 498
    if (!qemu_driver)
        return 0;

499
    qemuDriverLock(qemu_driver);
500 501 502 503
    virDomainLoadAllConfigs(NULL,
                            qemu_driver->caps,
                            &qemu_driver->domains,
                            qemu_driver->configDir,
504 505
                            qemu_driver->autostartDir,
                            qemudNotifyLoadDomain, qemu_driver);
506

507
    qemudAutostartConfigs(qemu_driver);
508
    qemuDriverUnlock(qemu_driver);
509 510

    return 0;
511 512
}

513 514 515 516 517 518 519 520 521 522
/**
 * qemudActive:
 *
 * Checks if the QEmu daemon is active, i.e. has an active domain or
 * an active network
 *
 * Returns 1 if active, 0 otherwise
 */
static int
qemudActive(void) {
523
    unsigned int i;
524
    int active = 0;
525

526 527 528
    if (!qemu_driver)
        return 0;

529 530 531 532 533 534 535 536
    qemuDriverLock(qemu_driver);
    for (i = 0 ; i < qemu_driver->domains.count ; i++) {
        virDomainObjPtr vm = qemu_driver->domains.objs[i];
        virDomainObjLock(vm);
        if (virDomainIsActive(vm))
            active = 1;
        virDomainObjUnlock(vm);
    }
537

538 539
    qemuDriverUnlock(qemu_driver);
    return active;
540 541
}

542 543 544 545 546 547 548
/**
 * qemudShutdown:
 *
 * Shutdown the QEmu daemon, it will stop all active domains and networks
 */
static int
qemudShutdown(void) {
549

550
    if (!qemu_driver)
551
        return -1;
552

553
    qemuDriverLock(qemu_driver);
554 555
    virCapabilitiesFree(qemu_driver->caps);

556
    virDomainObjListFree(&qemu_driver->domains);
557

558
    VIR_FREE(qemu_driver->logDir);
559 560
    VIR_FREE(qemu_driver->configDir);
    VIR_FREE(qemu_driver->autostartDir);
561
    VIR_FREE(qemu_driver->stateDir);
562
    VIR_FREE(qemu_driver->vncTLSx509certdir);
J
Jim Meyering 已提交
563
    VIR_FREE(qemu_driver->vncListen);
564
    VIR_FREE(qemu_driver->vncPassword);
D
Daniel P. Berrange 已提交
565

566 567
    /* Free domain callback list */
    virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
568 569 570 571
    virDomainEventQueueFree(qemu_driver->domainEventQueue);

    if (qemu_driver->domainEventTimer != -1)
        virEventRemoveTimeout(qemu_driver->domainEventTimer);
572

573 574 575
    if (qemu_driver->brctl)
        brShutdown(qemu_driver->brctl);

576
    qemuDriverUnlock(qemu_driver);
577
    virMutexDestroy(&qemu_driver->lock);
578
    VIR_FREE(qemu_driver);
579 580

    return 0;
581 582 583
}

/* Return -1 for error, 1 to continue reading and 0 for success */
584
typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
585
                                      virDomainObjPtr vm,
586 587 588
                                      const char *output,
                                      int fd);

589 590 591
/*
 * Returns -1 for error, 0 on end-of-file, 1 for success
 */
592
static int
593
qemudReadMonitorOutput(virConnectPtr conn,
594
                       virDomainObjPtr vm,
595 596 597 598
                       int fd,
                       char *buf,
                       int buflen,
                       qemudHandlerMonitorOutput func,
599 600
                       const char *what,
                       int timeout)
601 602 603
{
    int got = 0;
    buf[0] = '\0';
604
    timeout *= 1000; /* poll wants milli seconds */
605

606
    /* Consume & discard the initial greeting */
607 608 609 610
    while (got < (buflen-1)) {
        int ret;

        ret = read(fd, buf+got, buflen-got-1);
611

612 613 614 615 616 617
        if (ret < 0) {
            struct pollfd pfd = { .fd = fd, .events = POLLIN };
            if (errno == EINTR)
                continue;

            if (errno != EAGAIN) {
618 619 620
                virReportSystemError(conn, errno,
                                     _("Failure while reading %s startup output"),
                                     what);
621 622 623
                return -1;
            }

624
            ret = poll(&pfd, 1, timeout);
625
            if (ret == 0) {
626
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
627
                                 _("Timed out while reading %s startup output"), what);
628 629 630
                return -1;
            } else if (ret == -1) {
                if (errno != EINTR) {
631 632 633
                    virReportSystemError(conn, errno,
                                         _("Failure while reading %s startup output"),
                                         what);
634 635 636 637 638 639 640 641
                    return -1;
                }
            } else {
                /* Make sure we continue loop & read any further data
                   available before dealing with EOF */
                if (pfd.revents & (POLLIN | POLLHUP))
                    continue;

642
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
643
                                 _("Failure while reading %s startup output"), what);
644 645
                return -1;
            }
646 647
        } else if (ret == 0) {
            return 0;
648 649 650
        } else {
            got += ret;
            buf[got] = '\0';
651 652 653 654 655 656
            ret = func(conn, vm, buf, fd);
            if (ret == -1)
                return -1;
            if (ret == 1)
                continue;
            return 1;
657 658 659
        }
    }

660
    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
661
                     _("Out of space while reading %s startup output"), what);
662 663 664 665
    return -1;

}

666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715

/*
 * Returns -1 for error, 0 on success
 */
static int
qemudReadLogOutput(virConnectPtr conn,
                   virDomainObjPtr vm,
                   int fd,
                   char *buf,
                   int buflen,
                   qemudHandlerMonitorOutput func,
                   const char *what,
                   int timeout)
{
    int got = 0;
    int ret;
    int retries = timeout*10;
    buf[0] = '\0';

    while (retries) {
        while((ret = read(fd, buf+got, buflen-got-1)) > 0) {
            got += ret;
            buf[got] = '\0';
            if ((buflen-got-1) == 0) {
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 _("Out of space while reading %s log output"), what);
                return -1;
            }
        }

        if (ret < 0 && errno != EINTR) {
            virReportSystemError(conn, errno,
                                 _("Failure while reading %s log output"),
                                 what);
            return -1;
        }

        ret = func(conn, vm, buf, fd);
        if (ret <= 0)
            return ret;

        usleep(100*1000);
        retries--;
    }
    if (retries == 0)
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Timed out while reading %s log output"), what);
    return -1;
}

716
static int
717
qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
718
                        virDomainObjPtr vm,
719 720 721 722 723 724 725 726 727 728 729
                        const char *output,
                        int fd)
{
    if (strstr(output, "(qemu) ") == NULL)
        return 1; /* keep reading */

    vm->monitor = fd;

    return 0;
}

730
static int qemudOpenMonitor(virConnectPtr conn,
731
                            struct qemud_driver* driver,
732
                            virDomainObjPtr vm,
733 734
                            const char *monitor,
                            int reconnect) {
735 736 737 738
    int monfd;
    char buf[1024];
    int ret = -1;

D
Daniel Veillard 已提交
739
    if ((monfd = open(monitor, O_RDWR)) < 0) {
740
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
741
                         _("Unable to open monitor path %s"), monitor);
742 743
        return -1;
    }
744
    if (virSetCloseExec(monfd) < 0) {
745
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
746
                         "%s", _("Unable to set monitor close-on-exec flag"));
747 748
        goto error;
    }
749
    if (virSetNonBlock(monfd) < 0) {
750
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
751
                         "%s", _("Unable to put monitor into non-blocking mode"));
752 753 754
        goto error;
    }

755
    if (!reconnect) {
756 757 758 759
        if (qemudReadMonitorOutput(conn,
                                   vm, monfd,
                                   buf, sizeof(buf),
                                   qemudCheckMonitorPrompt,
760
                                   "monitor", 10) <= 0)
761 762 763
            ret = -1;
        else
            ret = 0;
764 765 766 767 768 769 770
    } else {
        vm->monitor = monfd;
        ret = 0;
    }

    if (ret != 0)
         goto error;
771

772
    if (!(vm->monitorpath = strdup(monitor))) {
773
        virReportOOMError(conn);
774 775 776
        goto error;
    }

777 778 779 780 781 782
    if ((vm->monitor_watch = virEventAddHandle(vm->monitor, 0,
                                               qemudDispatchVMEvent,
                                               driver, NULL)) < 0)
        goto error;


783 784 785 786
    /* Keep monitor open upon success */
    if (ret == 0)
        return ret;

787 788 789 790 791
 error:
    close(monfd);
    return ret;
}

792
/* Returns -1 for error, 0 success, 1 continue reading */
793 794
static int qemudExtractMonitorPath(virConnectPtr conn,
                                   const char *haystack,
795
                                   size_t *offset,
796
                                   char **path) {
797
    static const char needle[] = "char device redirected to";
798
    char *tmp, *dev;
799

800
    VIR_FREE(*path);
801
    /* First look for our magic string */
802 803 804 805 806
    if (!(tmp = strstr(haystack + *offset, needle))) {
        return 1;
    }
    tmp += sizeof(needle);
    dev = tmp;
807

808 809 810 811 812
    /*
     * And look for first whitespace character and nul terminate
     * to mark end of the pty path
     */
    while (*tmp) {
813
        if (c_isspace(*tmp)) {
814
            if (VIR_ALLOC_N(*path, (tmp-dev)+1) < 0) {
815
                virReportOOMError(conn);
816 817 818 819
                return -1;
            }
            strncpy(*path, dev, (tmp-dev));
            (*path)[(tmp-dev)] = '\0';
820
            /* ... now further update offset till we get EOL */
821
            *offset = tmp - haystack;
822 823
            return 0;
        }
824
        tmp++;
825 826 827 828 829
    }

    /*
     * We found a path, but didn't find any whitespace,
     * so it must be still incomplete - we should at
830 831
     * least see a \n - indicate that we want to carry
     * on trying again
832
     */
833
    return 1;
834 835 836
}

static int
837
qemudFindCharDevicePTYs(virConnectPtr conn,
838
                        virDomainObjPtr vm,
839 840
                        const char *output,
                        int fd ATTRIBUTE_UNUSED)
841
{
842
    struct qemud_driver* driver = conn->privateData;
843
    char *monitor = NULL;
844
    size_t offset = 0;
845
    int ret, i;
846 847 848 849 850

    /* The order in which QEMU prints out the PTY paths is
       the order in which it procsses its monitor, serial
       and parallel device args. This code must match that
       ordering.... */
851

852
    /* So first comes the monitor device */
853 854
    if ((ret = qemudExtractMonitorPath(conn, output, &offset, &monitor)) != 0)
        goto cleanup;
855

856
    /* then the serial devices */
857 858
    for (i = 0 ; i < vm->def->nserials ; i++) {
        virDomainChrDefPtr chr = vm->def->serials[i];
859 860 861 862
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
863 864 865 866
        }
    }

    /* and finally the parallel devices */
867 868
    for (i = 0 ; i < vm->def->nparallels ; i++) {
        virDomainChrDefPtr chr = vm->def->parallels[i];
869 870 871 872
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
873 874 875 876
        }
    }

    /* Got them all, so now open the monitor console */
877
    ret = qemudOpenMonitor(conn, driver, vm, monitor, 0);
878 879 880 881

cleanup:
    VIR_FREE(monitor);
    return ret;
882 883
}

884
static int qemudWaitForMonitor(virConnectPtr conn,
885 886 887
                               struct qemud_driver* driver,
                               virDomainObjPtr vm, off_t pos)
{
888
    char buf[1024]; /* Plenty of space to get startup greeting */
889 890 891 892 893
    int logfd;
    int ret;

    if ((logfd = qemudLogReadFD(conn, driver->logDir, vm->def->name, pos))
        < 0)
894
        return -1;
895

896 897 898
    ret = qemudReadLogOutput(conn, vm, logfd, buf, sizeof(buf),
                             qemudFindCharDevicePTYs,
                             "console", 3);
899 900
    if (close(logfd) < 0) {
        char ebuf[1024];
901
        qemudLog(QEMUD_WARN, _("Unable to close logfile: %s\n"),
902 903
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
904

905
    if (ret == 0) /* success */
906 907 908 909 910 911
        return 0;

    /* Unexpected end of file - inform user of QEMU log data */
    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                     _("unable to start guest: %s"), buf);
    return -1;
912 913
}

914 915
static int
qemudDetectVcpuPIDs(virConnectPtr conn,
916
                    virDomainObjPtr vm) {
917 918 919 920 921 922
    char *qemucpus = NULL;
    char *line;
    int lastVcpu = -1;

    /* Only KVM has seperate threads for CPUs,
       others just use main QEMU process for CPU */
923
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM)
924 925 926 927 928
        vm->nvcpupids = 1;
    else
        vm->nvcpupids = vm->def->vcpus;

    if (VIR_ALLOC_N(vm->vcpupids, vm->nvcpupids) < 0) {
929
        virReportOOMError(conn);
930 931 932
        return -1;
    }

933
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
934 935 936 937
        vm->vcpupids[0] = vm->pid;
        return 0;
    }

938
    if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) {
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot run monitor command to fetch CPU thread info"));
        VIR_FREE(vm->vcpupids);
        vm->nvcpupids = 0;
        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 {
        char *offset = strchr(line, '#');
        char *end = NULL;
        int vcpu = 0, tid = 0;

        /* See if we're all done */
        if (offset == NULL)
            break;

        /* Extract VCPU number */
        if (virStrToLong_i(offset + 1, &end, 10, &vcpu) < 0)
            goto error;
        if (end == NULL || *end != ':')
            goto error;

        /* 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;

        /* Validate the VCPU is in expected range & order */
        if (vcpu > vm->nvcpupids ||
            vcpu != (lastVcpu + 1))
            goto error;

        lastVcpu = vcpu;
        vm->vcpupids[vcpu] = tid;

        /* 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 */
    if (lastVcpu != (vm->def->vcpus - 1))
        goto error;

997
    VIR_FREE(qemucpus);
998 999 1000 1001
    return 0;

error:
    VIR_FREE(vm->vcpupids);
1002 1003
    vm->nvcpupids = 0;
    VIR_FREE(qemucpus);
1004 1005 1006 1007 1008 1009 1010 1011

    /* Explicitly return success, not error. Older KVM does
       not have vCPU -> Thread mapping info and we don't
       want to break its use. This merely disables ability
       to pin vCPUS with libvirt */
    return 0;
}

1012 1013
static int
qemudInitCpus(virConnectPtr conn,
D
Daniel Veillard 已提交
1014 1015
              virDomainObjPtr vm,
              const char *migrateFrom) {
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
    char *info = NULL;
#if HAVE_SCHED_GETAFFINITY
    cpu_set_t mask;
    int i, maxcpu = QEMUD_CPUMASK_LEN;
    virNodeInfo nodeinfo;

    if (virNodeInfoPopulate(conn, &nodeinfo) < 0)
        return -1;

    /* setaffinity fails if you set bits for CPUs which
     * aren't present, so we have to limit ourselves */
    if (maxcpu > nodeinfo.cpus)
        maxcpu = nodeinfo.cpus;

    CPU_ZERO(&mask);
D
Daniel P. Berrange 已提交
1031 1032 1033 1034 1035 1036
    if (vm->def->cpumask) {
        for (i = 0 ; i < maxcpu ; i++)
            if (vm->def->cpumask[i])
                CPU_SET(i, &mask);
    } else {
        for (i = 0 ; i < maxcpu ; i++)
1037
            CPU_SET(i, &mask);
D
Daniel P. Berrange 已提交
1038
    }
1039 1040 1041 1042

    for (i = 0 ; i < vm->nvcpupids ; i++) {
        if (sched_setaffinity(vm->vcpupids[i],
                              sizeof(mask), &mask) < 0) {
1043 1044
            virReportSystemError(conn, errno, "%s",
                                 _("failed to set CPU affinity"));
1045 1046 1047 1048 1049
            return -1;
        }
    }
#endif /* HAVE_SCHED_GETAFFINITY */

D
Daniel Veillard 已提交
1050 1051
    if (migrateFrom == NULL) {
        /* Allow the CPUS to start executing */
1052
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
D
Daniel Veillard 已提交
1053 1054 1055 1056 1057
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("resume operation failed"));
            return -1;
        }
        VIR_FREE(info);
1058 1059 1060 1061 1062 1063
    }

    return 0;
}


1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
static int
qemudInitPasswords(virConnectPtr conn,
                   struct qemud_driver *driver,
                   virDomainObjPtr vm) {
    char *info = NULL;

    /*
     * NB: Might have more passwords to set in the future. eg a qcow
     * disk decryption password, but there's no monitor command
     * for that yet...
     */

    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
1078
        (vm->def->graphics->data.vnc.passwd || driver->vncPassword)) {
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096

        if (qemudMonitorCommandExtra(vm, "change vnc password",
                                     vm->def->graphics->data.vnc.passwd ?
                                     vm->def->graphics->data.vnc.passwd :
                                     driver->vncPassword,
                                     QEMU_PASSWD_PROMPT,
                                     &info) < 0) {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("setting VNC password failed"));
            return -1;
        }
        VIR_FREE(info);
    }

    return 0;
}


1097
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
    int i;

    for (i = 5900 ; i < 6000 ; i++) {
        int fd;
        int reuse = 1;
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(i);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        fd = socket(PF_INET, SOCK_STREAM, 0);
        if (fd < 0)
            return -1;

        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse)) < 0) {
            close(fd);
            break;
        }

        if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
            /* Not in use, lets grab it */
            close(fd);
            return i;
        }
        close(fd);

        if (errno == EADDRINUSE) {
            /* In use, try next */
            continue;
        }
        /* Some other bad failure, get out.. */
        break;
    }
    return -1;
}

1133 1134 1135
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
                                            const char *name);

1136 1137
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
1138
                              virDomainObjPtr vm,
1139 1140
                              const char *migrateFrom,
                              int stdin_fd) {
1141
    const char **argv = NULL, **tmp;
1142
    const char **progenv = NULL;
1143
    int i, ret;
1144
    struct stat sb;
1145 1146
    int *tapfds = NULL;
    int ntapfds = 0;
1147
    unsigned int qemuCmdFlags;
1148
    fd_set keepfd;
1149
    const char *emulator;
G
Guido Günther 已提交
1150
    pid_t child;
1151
    int pos = -1;
1152
    char ebuf[1024];
1153 1154

    FD_ZERO(&keepfd);
1155

1156
    if (virDomainIsActive(vm)) {
1157
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
1158
                         "%s", _("VM is already active"));
1159 1160 1161
        return -1;
    }

1162 1163 1164
    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics->data.vnc.autoport) {
1165
        int port = qemudNextFreeVNCPort(driver);
1166
        if (port < 0) {
1167
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
1168
                             "%s", _("Unable to find an unused VNC port"));
1169 1170
            return -1;
        }
1171 1172
        vm->def->graphics->data.vnc.port = port;
    }
1173

1174
    if (virFileMakePath(driver->logDir) < 0) {
1175 1176 1177
        virReportSystemError(conn, errno,
                             _("cannot create log directory %s"),
                             driver->logDir);
1178 1179 1180
        return -1;
    }

1181
    if((vm->logfile = qemudLogFD(conn, driver->logDir, vm->def->name)) < 0)
1182 1183
        return -1;

1184 1185 1186 1187 1188 1189
    emulator = vm->def->emulator;
    if (!emulator)
        emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
    if (!emulator)
        return -1;

1190 1191 1192 1193
    /* Make sure the binary we are about to try exec'ing exists.
     * Technically we could catch the exec() failure, but that's
     * in a sub-process so its hard to feed back a useful error
     */
1194
    if (stat(emulator, &sb) < 0) {
1195 1196 1197
        virReportSystemError(conn, errno,
                             _("Cannot find QEMU binary %s"),
                             emulator);
1198 1199 1200
        return -1;
    }

1201
    if (qemudExtractVersionInfo(emulator,
1202 1203 1204 1205
                                NULL,
                                &qemuCmdFlags) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Cannot determine QEMU argv syntax %s"),
1206
                         emulator);
1207 1208
        return -1;
    }
1209

1210
    vm->def->id = driver->nextvmid++;
1211
    if (qemudBuildCommandLine(conn, driver, vm,
1212
                              qemuCmdFlags, &argv, &progenv,
1213
                              &tapfds, &ntapfds, migrateFrom) < 0) {
1214
        close(vm->logfile);
1215
        vm->def->id = -1;
1216 1217 1218 1219
        vm->logfile = -1;
        return -1;
    }

1220 1221 1222
    tmp = progenv;
    while (*tmp) {
        if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
1223
            qemudLog(QEMUD_WARN, _("Unable to write envv to logfile: %s\n"),
1224
                     virStrerror(errno, ebuf, sizeof ebuf));
1225
        if (safewrite(vm->logfile, " ", 1) < 0)
1226
            qemudLog(QEMUD_WARN, _("Unable to write envv to logfile: %s\n"),
1227
                     virStrerror(errno, ebuf, sizeof ebuf));
1228 1229
        tmp++;
    }
1230 1231
    tmp = argv;
    while (*tmp) {
1232
        if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
1233
            qemudLog(QEMUD_WARN, _("Unable to write argv to logfile: %s\n"),
1234
                     virStrerror(errno, ebuf, sizeof ebuf));
1235
        if (safewrite(vm->logfile, " ", 1) < 0)
1236
            qemudLog(QEMUD_WARN, _("Unable to write argv to logfile: %s\n"),
1237
                     virStrerror(errno, ebuf, sizeof ebuf));
1238 1239
        tmp++;
    }
1240
    if (safewrite(vm->logfile, "\n", 1) < 0)
1241
        qemudLog(QEMUD_WARN, _("Unable to write argv to logfile: %s\n"),
1242
                 virStrerror(errno, ebuf, sizeof ebuf));
1243

1244
    if ((pos = lseek(vm->logfile, 0, SEEK_END)) < 0)
1245
        qemudLog(QEMUD_WARN, _("Unable to seek to end of logfile: %s\n"),
1246
                 virStrerror(errno, ebuf, sizeof ebuf));
1247

1248 1249 1250
    for (i = 0 ; i < ntapfds ; i++)
        FD_SET(tapfds[i], &keepfd);

G
Guido Günther 已提交
1251
    ret = virExec(conn, argv, progenv, &keepfd, &child,
1252
                  stdin_fd, &vm->logfile, &vm->logfile,
G
Guido Günther 已提交
1253 1254 1255 1256 1257
                  VIR_EXEC_NONBLOCK | VIR_EXEC_DAEMON);

    /* wait for qemu process to to show up */
    if (ret == 0) {
        int retries = 100;
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
        int childstat;

        while (waitpid(child, &childstat, 0) == -1 &&
               errno == EINTR);

        if (childstat == 0) {
            while (retries) {
                if ((ret = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0)
                    break;
                usleep(100*1000);
                retries--;
            }
1270 1271 1272 1273 1274
            if (ret) {
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 _("Domain %s didn't show up\n"), vm->def->name);
                ret = -1;
            }
1275 1276
        } else {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1277
                             "%s", _("Unable to daemonize QEMU process"));
1278
            ret = -1;
G
Guido Günther 已提交
1279 1280 1281 1282
        }
    }

    if (ret == 0) {
1283
        vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
G
Guido Günther 已提交
1284
    } else
1285
        vm->def->id = -1;
1286

1287
    for (i = 0 ; argv[i] ; i++)
1288 1289
        VIR_FREE(argv[i]);
    VIR_FREE(argv);
1290

1291 1292 1293 1294
    for (i = 0 ; progenv[i] ; i++)
        VIR_FREE(progenv[i]);
    VIR_FREE(progenv);

1295 1296 1297
    if (tapfds) {
        for (i = 0 ; i < ntapfds ; i++) {
            close(tapfds[i]);
1298
        }
1299
        VIR_FREE(tapfds);
1300 1301
    }

1302
    if (ret == 0) {
1303
        if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
1304
            (qemudDetectVcpuPIDs(conn, vm) < 0) ||
1305
            (qemudInitCpus(conn, vm, migrateFrom) < 0) ||
1306 1307
            (qemudInitPasswords(conn, driver, vm) < 0) ||
            (qemudSaveDomainStatus(conn, qemu_driver, vm) < 0)) {
1308 1309 1310
            qemudShutdownVMDaemon(conn, driver, vm);
            return -1;
        }
1311 1312
    }

1313
    return ret;
1314 1315 1316
}


1317
static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
1318 1319
                                  struct qemud_driver *driver,
                                  virDomainObjPtr vm) {
1320
    if (!virDomainIsActive(vm))
1321
        return;
1322

1323
    qemudLog(QEMUD_DEBUG, _("Shutting down VM '%s'\n"), vm->def->name);
1324

G
Guido Günther 已提交
1325 1326
    if (virKillProcess(vm->pid, 0) == 0 &&
        virKillProcess(vm->pid, SIGTERM) < 0)
1327 1328 1329
        virReportSystemError(conn, errno,
                             _("Failed to send SIGTERM to %s (%d)"),
                             vm->def->name, vm->pid);
1330

1331 1332 1333 1334
    if (vm->monitor_watch != -1) {
        virEventRemoveHandle(vm->monitor_watch);
        vm->monitor_watch = -1;
    }
1335

1336 1337
    if (close(vm->logfile) < 0) {
        char ebuf[1024];
1338
        qemudLog(QEMUD_WARN, _("Unable to close logfile: %s\n"),
1339 1340
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1341 1342 1343 1344 1345
    if (vm->monitor != -1)
        close(vm->monitor);
    vm->logfile = -1;
    vm->monitor = -1;

G
Guido Günther 已提交
1346 1347
    /* shut it off for sure */
    virKillProcess(vm->pid, SIGKILL);
1348

1349 1350 1351 1352
    if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
        qemudLog(QEMUD_WARN, _("Failed to remove domain status for %s"),
                 vm->def->name);
    }
1353
    vm->pid = -1;
1354
    vm->def->id = -1;
1355
    vm->state = VIR_DOMAIN_SHUTOFF;
1356
    VIR_FREE(vm->vcpupids);
1357
    vm->nvcpupids = 0;
1358 1359

    if (vm->newDef) {
1360
        virDomainDefFree(vm->def);
1361
        vm->def = vm->newDef;
1362
        vm->def->id = -1;
1363 1364 1365 1366 1367
        vm->newDef = NULL;
    }
}


1368
static void
1369
qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
1370
    struct qemud_driver *driver = opaque;
1371
    virDomainObjPtr vm = NULL;
1372
    virDomainEventPtr event = NULL;
1373
    unsigned int i;
1374
    int quit = 0, failed = 0;
1375

1376
    qemuDriverLock(driver);
1377
    for (i = 0 ; i < driver->domains.count ; i++) {
1378 1379 1380
        virDomainObjPtr tmpvm = driver->domains.objs[i];
        virDomainObjLock(tmpvm);
        if (virDomainIsActive(tmpvm) &&
1381
            tmpvm->monitor_watch == watch) {
1382
            vm = tmpvm;
1383
            break;
1384
        }
1385
        virDomainObjUnlock(tmpvm);
1386 1387 1388
    }

    if (!vm)
1389
        goto cleanup;
1390

1391
    if (vm->monitor != fd) {
1392 1393
        failed = 1;
    } else {
1394
        if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
1395
            quit = 1;
1396 1397 1398 1399
        else {
            qemudLog(QEMUD_ERROR, _("unhandled fd event %d for %s"),
                                    events, vm->def->name);
            failed = 1;
1400
        }
1401 1402
    }

1403
    if (failed || quit) {
1404 1405 1406 1407 1408
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         quit ?
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419
        qemudShutdownVMDaemon(NULL, driver, vm);
        if (!vm->persistent) {
            virDomainRemoveInactive(&driver->domains,
                                    vm);
            vm = NULL;
        }
    }

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
1420 1421
    if (event)
        qemuDomainEventQueue(driver, event);
1422
    qemuDriverUnlock(driver);
1423 1424
}

1425
static int
1426 1427 1428 1429 1430
qemudMonitorCommandExtra(const virDomainObjPtr vm,
                         const char *cmd,
                         const char *extra,
                         const char *extraPrompt,
                         char **reply) {
D
Daniel P. Berrange 已提交
1431 1432
    int size = 0;
    char *buf = NULL;
1433
    size_t cmdlen = strlen(cmd);
1434
    size_t extralen = extra ? strlen(extra) : 0;
D
Daniel P. Berrange 已提交
1435

1436 1437 1438
    if (safewrite(vm->monitor, cmd, cmdlen) != cmdlen)
        return -1;
    if (safewrite(vm->monitor, "\r", 1) != 1)
D
Daniel P. Berrange 已提交
1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
        return -1;

    *reply = NULL;

    for (;;) {
        struct pollfd fd = { vm->monitor, POLLIN | POLLERR | POLLHUP, 0 };
        char *tmp;

        /* Read all the data QEMU has sent thus far */
        for (;;) {
            char data[1024];
            int got = read(vm->monitor, data, sizeof(data));
D
Daniel P. Berrange 已提交
1451

1452 1453
            if (got == 0)
                goto error;
D
Daniel P. Berrange 已提交
1454 1455 1456 1457 1458
            if (got < 0) {
                if (errno == EINTR)
                    continue;
                if (errno == EAGAIN)
                    break;
1459
                goto error;
1460
            }
1461
            if (VIR_REALLOC_N(buf, size+got+1) < 0)
1462 1463
                goto error;

D
Daniel P. Berrange 已提交
1464 1465 1466 1467
            memmove(buf+size, data, got);
            buf[size+got] = '\0';
            size += got;
        }
1468

D
Daniel P. Berrange 已提交
1469
        /* Look for QEMU prompt to indicate completion */
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
        if (buf) {
            if (extra) {
                if (strstr(buf, extraPrompt) != NULL) {
                    if (safewrite(vm->monitor, extra, extralen) != extralen)
                        return -1;
                    if (safewrite(vm->monitor, "\r", 1) != 1)
                        return -1;
                    extra = NULL;
                }
            } else if ((tmp = strstr(buf, QEMU_CMD_PROMPT)) != NULL) {
                char *commptr = NULL, *nlptr = NULL;
                /* Preserve the newline */
                tmp[1] = '\0';

                /* The monitor doesn't dump clean output after we have written to
                 * it. Every character we write dumps a bunch of useless stuff,
                 * so the result looks like "cXcoXcomXcommXcommaXcommanXcommand"
                 * Try to throw away everything before the first full command
                 * occurence, and inbetween the command and the newline starting
                 * the response
                 */
                if ((commptr = strstr(buf, cmd)))
                    memmove(buf, commptr, strlen(commptr)+1);
                if ((nlptr = strchr(buf, '\n')))
                    memmove(buf+strlen(cmd), nlptr, strlen(nlptr)+1);
C
Cole Robinson 已提交
1495

1496 1497
                break;
            }
D
Daniel P. Berrange 已提交
1498 1499 1500 1501 1502 1503
        }
    pollagain:
        /* Need to wait for more data */
        if (poll(&fd, 1, -1) < 0) {
            if (errno == EINTR)
                goto pollagain;
1504
            goto error;
D
Daniel P. Berrange 已提交
1505 1506 1507
        }
    }

1508
    /* Log, but ignore failures to write logfile for VM */
1509 1510
    if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
        char ebuf[1024];
1511
        qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s\n"),
1512 1513
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1514

D
Daniel P. Berrange 已提交
1515 1516
    *reply = buf;
    return 0;
1517 1518 1519 1520

 error:
    if (buf) {
        /* Log, but ignore failures to write logfile for VM */
1521 1522
        if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
            char ebuf[1024];
1523
            qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s\n"),
1524 1525
                     virStrerror(errno, ebuf, sizeof ebuf));
        }
1526
        VIR_FREE(buf);
1527 1528
    }
    return -1;
D
Daniel P. Berrange 已提交
1529 1530
}

1531 1532 1533 1534 1535 1536 1537 1538
static int
qemudMonitorCommand(const virDomainObjPtr vm,
                    const char *cmd,
                    char **reply) {
    return qemudMonitorCommandExtra(vm, cmd, NULL, NULL, reply);
}


1539 1540 1541 1542 1543 1544
/**
 * qemudProbe:
 *
 * Probe for the availability of the qemu driver, assume the
 * presence of QEmu emulation if the binaries are installed
 */
1545
static int qemudProbe(void)
1546 1547 1548
{
    if ((virFileExists("/usr/bin/qemu")) ||
        (virFileExists("/usr/bin/qemu-kvm")) ||
G
Guido Günther 已提交
1549
        (virFileExists("/usr/bin/kvm")) ||
1550 1551 1552 1553
        (virFileExists("/usr/bin/xenner")))
        return 1;

    return 0;
1554
}
1555

1556
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
1557
                                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1558
                                  int flags ATTRIBUTE_UNUSED) {
1559 1560 1561
    uid_t uid = getuid();

    if (qemu_driver == NULL)
1562
        goto decline;
1563

1564 1565 1566 1567 1568 1569
    if (!qemudProbe())
        goto decline;

    if (conn->uri == NULL) {
        conn->uri = xmlParseURI(uid ? "qemu:///session" : "qemu:///system");
        if (!conn->uri) {
1570
            virReportOOMError(conn);
1571 1572 1573 1574
            return VIR_DRV_OPEN_ERROR;
        }
    } else if (conn->uri->scheme == NULL ||
               conn->uri->path == NULL)
1575 1576
        goto decline;

1577
    if (STRNEQ (conn->uri->scheme, "qemu"))
1578 1579
        goto decline;

1580
    if (uid != 0) {
1581
        if (STRNEQ (conn->uri->path, "/session"))
1582
            goto decline;
1583
    } else { /* root */
1584 1585
        if (STRNEQ (conn->uri->path, "/system") &&
            STRNEQ (conn->uri->path, "/session"))
1586
            goto decline;
1587 1588 1589 1590 1591
    }

    conn->privateData = qemu_driver;

    return VIR_DRV_OPEN_SUCCESS;
1592 1593

 decline:
1594
    return VIR_DRV_OPEN_DECLINED;
1595 1596 1597
}

static int qemudClose(virConnectPtr conn) {
1598
    struct qemud_driver *driver = conn->privateData;
1599 1600 1601

    /* Get rid of callbacks registered for this conn */
    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
1602 1603 1604 1605 1606 1607

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617
/* Which features are supported by this driver? */
static int
qemudSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
{
    switch (feature) {
    case VIR_DRV_FEATURE_MIGRATION_V2: return 1;
    default: return 0;
    }
}

1618
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1619
    return "QEMU";
1620 1621
}

1622 1623 1624 1625 1626

static int kvmGetMaxVCPUs(void) {
    int maxvcpus = 1;

    int r, fd;
1627

1628 1629
    fd = open(KVM_DEVICE, O_RDONLY);
    if (fd < 0) {
1630 1631
        virReportSystemError(NULL, errno, _("Unable to open %s"), KVM_DEVICE);
        return -1;
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642
    }

    r = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_NR_VCPUS);
    if (r > 0)
        maxvcpus = r;

    close(fd);
    return maxvcpus;
}


1643
static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) {
1644 1645 1646
    if (!type)
        return 16;

1647
    if (STRCASEEQ(type, "qemu"))
1648 1649
        return 16;

1650
    if (STRCASEEQ(type, "kvm"))
1651
        return kvmGetMaxVCPUs();
1652

1653
    if (STRCASEEQ(type, "kqemu"))
1654
        return 1;
1655 1656 1657

    qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
                     _("unknown type '%s'"), type);
1658 1659 1660
    return -1;
}

1661 1662 1663
static int qemudGetNodeInfo(virConnectPtr conn,
                            virNodeInfoPtr nodeinfo) {
    return virNodeInfoPopulate(conn, nodeinfo);
1664 1665 1666
}


1667
static char *qemudGetCapabilities(virConnectPtr conn) {
1668
    struct qemud_driver *driver = conn->privateData;
1669
    char *xml;
1670

1671
    qemuDriverLock(driver);
1672
    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
1673
        virReportOOMError(conn);
1674
    qemuDriverUnlock(driver);
1675

1676
    return xml;
1677 1678 1679
}


1680 1681 1682 1683 1684 1685 1686 1687
#if HAVE_NUMACTL
static int
qemudNodeGetCellsFreeMemory(virConnectPtr conn,
                            unsigned long long *freeMems,
                            int startCell,
                            int maxCells)
{
    int n, lastCell, numCells;
1688
    int ret = -1;
1689 1690 1691 1692

    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1693
        goto cleanup;
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703
    }
    lastCell = startCell + maxCells - 1;
    if (lastCell > numa_max_node())
        lastCell = numa_max_node();

    for (numCells = 0, n = startCell ; n <= lastCell ; n++) {
        long long mem;
        if (numa_node_size64(n, &mem) < 0) {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("Failed to query NUMA free memory"));
1704
            goto cleanup;
1705 1706 1707
        }
        freeMems[numCells++] = mem;
    }
1708 1709 1710 1711
    ret = numCells;

cleanup:
    return ret;
1712 1713 1714 1715 1716
}

static unsigned long long
qemudNodeGetFreeMemory (virConnectPtr conn)
{
1717
    unsigned long long freeMem = -1;
1718
    int n;
1719

1720 1721 1722
    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1723
        goto cleanup;
1724 1725 1726 1727 1728 1729 1730
    }

    for (n = 0 ; n <= numa_max_node() ; n++) {
        long long mem;
        if (numa_node_size64(n, &mem) < 0) {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("Failed to query NUMA free memory"));
1731
            goto cleanup;
1732 1733 1734 1735
        }
        freeMem += mem;
    }

1736
cleanup:
1737 1738 1739 1740
    return freeMem;
}

#endif
1741

D
Daniel P. Berrange 已提交
1742 1743 1744
static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) {
    char proc[PATH_MAX];
    FILE *pidinfo;
1745
    unsigned long long usertime, systime;
D
Daniel P. Berrange 已提交
1746 1747 1748 1749 1750 1751

    if (snprintf(proc, sizeof(proc), "/proc/%d/stat", pid) >= (int)sizeof(proc)) {
        return -1;
    }

    if (!(pidinfo = fopen(proc, "r"))) {
1752
        /*printf("cannot read pid info");*/
D
Daniel P. Berrange 已提交
1753 1754 1755 1756 1757
        /* VM probably shut down, so fake 0 */
        *cpuTime = 0;
        return 0;
    }

1758
    if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
1759
        qemudDebug("not enough arg");
D
Daniel P. Berrange 已提交
1760 1761 1762 1763 1764 1765 1766 1767
        return -1;
    }

    /* We got jiffies
     * We want nanoseconds
     * _SC_CLK_TCK is jiffies per second
     * So calulate thus....
     */
1768
    *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
D
Daniel P. Berrange 已提交
1769

1770
    qemudDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
D
Daniel P. Berrange 已提交
1771 1772 1773 1774 1775 1776 1777

    fclose(pidinfo);

    return 0;
}


1778
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
1779
                                          int id) {
1780 1781 1782 1783
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

1784
    qemuDriverLock(driver);
1785
    vm  = virDomainFindByID(&driver->domains, id);
1786
    qemuDriverUnlock(driver);
1787 1788

    if (!vm) {
1789
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
1790
        goto cleanup;
1791 1792
    }

1793
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1794
    if (dom) dom->id = vm->def->id;
1795 1796

cleanup:
1797 1798
    if (vm)
        virDomainObjUnlock(vm);
1799 1800
    return dom;
}
1801

1802
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
1803
                                            const unsigned char *uuid) {
1804 1805 1806
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1807

1808
    qemuDriverLock(driver);
1809
    vm = virDomainFindByUUID(&driver->domains, uuid);
1810 1811
    qemuDriverUnlock(driver);

1812
    if (!vm) {
1813
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
1814
        goto cleanup;
1815 1816
    }

1817
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1818
    if (dom) dom->id = vm->def->id;
1819 1820

cleanup:
1821 1822
    if (vm)
        virDomainObjUnlock(vm);
1823 1824
    return dom;
}
1825

1826
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
1827
                                            const char *name) {
1828 1829 1830
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1831

1832
    qemuDriverLock(driver);
1833
    vm = virDomainFindByName(&driver->domains, name);
1834 1835
    qemuDriverUnlock(driver);

1836
    if (!vm) {
1837
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
1838
        goto cleanup;
1839 1840
    }

1841
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1842
    if (dom) dom->id = vm->def->id;
1843 1844

cleanup:
1845 1846
    if (vm)
        virDomainObjUnlock(vm);
1847 1848 1849
    return dom;
}

1850
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
1851 1852 1853
    struct qemud_driver *driver = conn->privateData;
    int ret = -1;

1854
    qemuDriverLock(driver);
1855
    if (qemudExtractVersion(conn, driver) < 0)
1856
        goto cleanup;
1857

1858
    *version = qemu_driver->qemuVersion;
1859 1860 1861
    ret = 0;

cleanup:
1862
    qemuDriverUnlock(driver);
1863
    return ret;
D
Daniel P. Berrange 已提交
1864 1865
}

1866 1867 1868
static char *
qemudGetHostname (virConnectPtr conn)
{
1869
    char *result;
1870

1871 1872
    result = virGetHostname();
    if (result == NULL) {
1873 1874
        virReportSystemError (conn, errno,
                              "%s", _("failed to determine host name"));
1875 1876 1877
        return NULL;
    }
    /* Caller frees this string. */
1878
    return result;
1879 1880
}

1881
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
1882
    struct qemud_driver *driver = conn->privateData;
1883 1884
    int got = 0, i;

1885 1886 1887
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count && got < nids ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1888 1889
        if (virDomainIsActive(driver->domains.objs[i]))
            ids[got++] = driver->domains.objs[i]->def->id;
1890 1891 1892
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
1893

D
Daniel P. Berrange 已提交
1894 1895
    return got;
}
1896

1897
static int qemudNumDomains(virConnectPtr conn) {
1898
    struct qemud_driver *driver = conn->privateData;
1899 1900
    int n = 0, i;

1901 1902 1903
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1904
        if (virDomainIsActive(driver->domains.objs[i]))
1905
            n++;
1906 1907 1908
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
1909

1910
    return n;
D
Daniel P. Berrange 已提交
1911
}
1912

1913
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
1914
                                      unsigned int flags) {
1915
    struct qemud_driver *driver = conn->privateData;
1916
    virDomainDefPtr def;
1917
    virDomainObjPtr vm = NULL;
1918
    virDomainPtr dom = NULL;
1919
    virDomainEventPtr event = NULL;
D
Daniel P. Berrange 已提交
1920

1921
    qemuDriverLock(driver);
1922 1923
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
1924
        goto cleanup;
1925

1926
    vm = virDomainFindByName(&driver->domains, def->name);
1927
    if (vm) {
1928
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
1929
                         _("domain '%s' is already defined"),
1930
                         def->name);
1931
        goto cleanup;
1932
    }
1933
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
1934 1935 1936 1937 1938
    if (vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(def->uuid, uuidstr);
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
1939
                         _("domain with uuid '%s' is already defined"),
1940
                         uuidstr);
1941
        goto cleanup;
1942
    }
1943

1944 1945
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
1946 1947 1948 1949
                                  def)))
        goto cleanup;

    def = NULL;
D
Daniel P. Berrange 已提交
1950

1951
    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
1952 1953
        virDomainRemoveInactive(&driver->domains,
                                vm);
1954
        vm = NULL;
1955
        goto cleanup;
D
Daniel P. Berrange 已提交
1956
    }
1957 1958 1959 1960

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
D
Daniel P. Berrange 已提交
1961

1962
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1963
    if (dom) dom->id = vm->def->id;
1964 1965 1966

cleanup:
    virDomainDefFree(def);
1967 1968
    if (vm)
        virDomainObjUnlock(vm);
1969 1970
    if (event)
        qemuDomainEventQueue(driver, event);
1971
    qemuDriverUnlock(driver);
1972
    return dom;
D
Daniel P. Berrange 已提交
1973 1974 1975
}


1976
static int qemudDomainSuspend(virDomainPtr dom) {
1977
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
1978
    char *info;
1979 1980
    virDomainObjPtr vm;
    int ret = -1;
1981
    virDomainEventPtr event = NULL;
1982

1983
    qemuDriverLock(driver);
1984
    vm = virDomainFindByID(&driver->domains, dom->id);
1985 1986
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
1987
    if (!vm) {
1988
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
1989
        goto cleanup;
D
Daniel P. Berrange 已提交
1990
    }
1991
    if (!virDomainIsActive(vm)) {
1992 1993
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
1994
        goto cleanup;
D
Daniel P. Berrange 已提交
1995
    }
1996
    if (vm->state != VIR_DOMAIN_PAUSED) {
1997
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
1998 1999 2000 2001 2002 2003
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("suspend operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
2004 2005 2006
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
2007
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
2008
    }
2009 2010
    if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        goto cleanup;
2011 2012 2013
    ret = 0;

cleanup:
2014 2015
    if (vm)
        virDomainObjUnlock(vm);
2016 2017 2018 2019 2020 2021

    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2022
    return ret;
D
Daniel P. Berrange 已提交
2023 2024 2025
}


2026
static int qemudDomainResume(virDomainPtr dom) {
2027
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
2028
    char *info;
2029 2030
    virDomainObjPtr vm;
    int ret = -1;
2031
    virDomainEventPtr event = NULL;
2032

2033
    qemuDriverLock(driver);
2034
    vm = virDomainFindByID(&driver->domains, dom->id);
2035 2036
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
2037
    if (!vm) {
2038 2039
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         _("no domain with matching id %d"), dom->id);
2040
        goto cleanup;
D
Daniel P. Berrange 已提交
2041
    }
2042
    if (!virDomainIsActive(vm)) {
2043 2044
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
2045
        goto cleanup;
D
Daniel P. Berrange 已提交
2046
    }
2047
    if (vm->state == VIR_DOMAIN_PAUSED) {
2048
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
2049 2050 2051 2052 2053 2054
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("resume operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_RUNNING;
        qemudDebug("Reply %s", info);
2055 2056 2057
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
2058
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
2059
    }
2060 2061
    if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        goto cleanup;
2062 2063 2064
    ret = 0;

cleanup:
2065 2066
    if (vm)
        virDomainObjUnlock(vm);
2067 2068 2069 2070 2071
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2072
    return ret;
D
Daniel P. Berrange 已提交
2073 2074 2075
}


2076
static int qemudDomainShutdown(virDomainPtr dom) {
2077 2078
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2079
    char* info;
2080
    int ret = -1;
2081

2082
    qemuDriverLock(driver);
2083
    vm = virDomainFindByID(&driver->domains, dom->id);
2084 2085
    qemuDriverUnlock(driver);

2086 2087
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2088
                         _("no domain with matching id %d"), dom->id);
2089
        goto cleanup;
2090 2091
    }

2092
    if (qemudMonitorCommand(vm, "system_powerdown", &info) < 0) {
2093
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2094
                         "%s", _("shutdown operation failed"));
2095
        goto cleanup;
2096
    }
D
Daniel Veillard 已提交
2097
    VIR_FREE(info);
2098 2099 2100
    ret = 0;

cleanup:
2101 2102
    if (vm)
        virDomainObjUnlock(vm);
2103
    return ret;
2104 2105 2106
}


2107
static int qemudDomainDestroy(virDomainPtr dom) {
2108 2109 2110
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2111
    virDomainEventPtr event = NULL;
2112

2113
    qemuDriverLock(driver);
2114
    vm  = virDomainFindByID(&driver->domains, dom->id);
D
Daniel P. Berrange 已提交
2115
    if (!vm) {
2116
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2117
                         _("no domain with matching id %d"), dom->id);
2118
        goto cleanup;
D
Daniel P. Berrange 已提交
2119
    }
2120

2121
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2122 2123 2124
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2125
    if (!vm->persistent) {
2126 2127
        virDomainRemoveInactive(&driver->domains,
                                vm);
2128 2129
        vm = NULL;
    }
2130 2131 2132
    ret = 0;

cleanup:
2133 2134
    if (vm)
        virDomainObjUnlock(vm);
2135 2136
    if (event)
        qemuDomainEventQueue(driver, event);
2137
    qemuDriverUnlock(driver);
2138
    return ret;
D
Daniel P. Berrange 已提交
2139 2140 2141
}


2142
static char *qemudDomainGetOSType(virDomainPtr dom) {
2143 2144 2145
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *type = NULL;
2146

2147
    qemuDriverLock(driver);
2148
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2149
    qemuDriverUnlock(driver);
2150 2151
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2152
                         "%s", _("no domain with matching uuid"));
2153
        goto cleanup;
2154 2155
    }

2156
    if (!(type = strdup(vm->def->os.type)))
2157
        virReportOOMError(dom->conn);
2158 2159

cleanup:
2160 2161
    if (vm)
        virDomainObjUnlock(vm);
2162 2163 2164
    return type;
}

2165 2166
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
2167 2168 2169
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    unsigned long ret = 0;
2170

2171
    qemuDriverLock(driver);
2172
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2173 2174
    qemuDriverUnlock(driver);

2175
    if (!vm) {
2176 2177 2178
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2179
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2180
                         _("no domain with matching uuid '%s'"), uuidstr);
2181
        goto cleanup;
2182 2183
    }

2184 2185 2186
    ret = vm->def->maxmem;

cleanup:
2187 2188
    if (vm)
        virDomainObjUnlock(vm);
2189
    return ret;
2190 2191 2192
}

static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
2193 2194 2195
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2196

2197
    qemuDriverLock(driver);
2198
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2199 2200
    qemuDriverUnlock(driver);

2201
    if (!vm) {
2202 2203 2204
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2205
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2206
                         _("no domain with matching uuid '%s'"), uuidstr);
2207
        goto cleanup;
2208 2209 2210 2211
    }

    if (newmax < vm->def->memory) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2212
                         "%s", _("cannot set max memory lower than current memory"));
2213
        goto cleanup;;
2214 2215 2216
    }

    vm->def->maxmem = newmax;
2217 2218 2219
    ret = 0;

cleanup:
2220 2221
    if (vm)
        virDomainObjUnlock(vm);
2222
    return ret;
2223 2224 2225
}

static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
2226 2227 2228
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2229

2230
    qemuDriverLock(driver);
2231
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2232
    qemuDriverUnlock(driver);
2233
    if (!vm) {
2234 2235 2236
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2237
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2238
                         _("no domain with matching uuid '%s'"), uuidstr);
2239
        goto cleanup;
2240 2241
    }

2242
    if (virDomainIsActive(vm)) {
2243
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
2244
                         "%s", _("cannot set memory of an active domain"));
2245
        goto cleanup;
2246 2247 2248 2249
    }

    if (newmem > vm->def->maxmem) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2250
                         "%s", _("cannot set memory higher than max memory"));
2251
        goto cleanup;
2252 2253 2254
    }

    vm->def->memory = newmem;
2255 2256 2257
    ret = 0;

cleanup:
2258 2259
    if (vm)
        virDomainObjUnlock(vm);
2260
    return ret;
2261 2262
}

2263
static int qemudDomainGetInfo(virDomainPtr dom,
2264
                              virDomainInfoPtr info) {
2265 2266 2267 2268
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

2269
    qemuDriverLock(driver);
2270
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2271
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
2272
    if (!vm) {
2273 2274
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
2275
        goto cleanup;
D
Daniel P. Berrange 已提交
2276 2277
    }

2278
    info->state = vm->state;
D
Daniel P. Berrange 已提交
2279

2280
    if (!virDomainIsActive(vm)) {
2281
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
2282
    } else {
2283
        if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
2284
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
2285
            goto cleanup;
D
Daniel P. Berrange 已提交
2286 2287 2288
        }
    }

2289 2290 2291
    info->maxMem = vm->def->maxmem;
    info->memory = vm->def->memory;
    info->nrVirtCpu = vm->def->vcpus;
2292 2293 2294
    ret = 0;

cleanup:
2295 2296
    if (vm)
        virDomainObjUnlock(vm);
2297
    return ret;
D
Daniel P. Berrange 已提交
2298 2299 2300
}


D
Daniel P. Berrange 已提交
2301
static char *qemudEscape(const char *in, int shell)
2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322
{
    int len = 0;
    int i, j;
    char *out;

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

       To pass through both QEMU + the shell, we need to escape
       the single character ' as the five characters '\\''
    */

    for (i = 0; in[i] != '\0'; i++) {
        switch(in[i]) {
        case '\r':
        case '\n':
        case '"':
        case '\\':
            len += 2;
            break;
        case '\'':
D
Daniel P. Berrange 已提交
2323 2324 2325 2326
            if (shell)
                len += 5;
            else
                len += 1;
2327 2328 2329 2330 2331 2332 2333
            break;
        default:
            len += 1;
            break;
        }
    }

2334
    if (VIR_ALLOC_N(out, len + 1) < 0)
2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352
        return NULL;

    for (i = j = 0; in[i] != '\0'; i++) {
        switch(in[i]) {
        case '\r':
            out[j++] = '\\';
            out[j++] = 'r';
            break;
        case '\n':
            out[j++] = '\\';
            out[j++] = 'n';
            break;
        case '"':
        case '\\':
            out[j++] = '\\';
            out[j++] = in[i];
            break;
        case '\'':
D
Daniel P. Berrange 已提交
2353 2354 2355 2356 2357 2358 2359 2360 2361
            if (shell) {
                out[j++] = '\'';
                out[j++] = '\\';
                out[j++] = '\\';
                out[j++] = '\'';
                out[j++] = '\'';
            } else {
                out[j++] = in[i];
            }
2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372
            break;
        default:
            out[j++] = in[i];
            break;
        }
    }
    out[j] = '\0';

    return out;
}

2373 2374 2375 2376 2377
static char *qemudEscapeMonitorArg(const char *in)
{
    return qemudEscape(in, 0);
}

D
Daniel P. Berrange 已提交
2378 2379 2380 2381
static char *qemudEscapeShellArg(const char *in)
{
    return qemudEscape(in, 1);
}
2382

2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave"
#define QEMUD_SAVE_VERSION 1

struct qemud_save_header {
    char magic[sizeof(QEMUD_SAVE_MAGIC)-1];
    int version;
    int xml_len;
    int was_running;
    int unused[16];
};

2394
static int qemudDomainSave(virDomainPtr dom,
2395
                           const char *path) {
2396 2397 2398 2399 2400 2401 2402
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *command = NULL;
    char *info = NULL;
    int fd = -1;
    char *safe_path = NULL;
    char *xml = NULL;
2403
    struct qemud_save_header header;
2404
    int ret = -1;
2405
    virDomainEventPtr event = NULL;
2406 2407 2408 2409 2410

    memset(&header, 0, sizeof(header));
    memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
    header.version = QEMUD_SAVE_VERSION;

2411
    qemuDriverLock(driver);
2412 2413
    vm = virDomainFindByID(&driver->domains, dom->id);

D
Daniel P. Berrange 已提交
2414
    if (!vm) {
2415
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2416
                         _("no domain with matching id %d"), dom->id);
2417
        goto cleanup;
D
Daniel P. Berrange 已提交
2418
    }
2419

2420
    if (!virDomainIsActive(vm)) {
2421
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2422
                         "%s", _("domain is not running"));
2423
        goto cleanup;
D
Daniel P. Berrange 已提交
2424
    }
2425 2426 2427 2428

    /* Pause */
    if (vm->state == VIR_DOMAIN_RUNNING) {
        header.was_running = 1;
2429
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
2430
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2431
                             "%s", _("suspend operation failed"));
2432
            goto cleanup;
2433
        }
2434 2435 2436
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
        VIR_FREE(info);
2437 2438 2439
    }

    /* Get XML for the domain */
2440
    xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE);
2441 2442
    if (!xml) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2443
                         "%s", _("failed to get domain xml"));
2444
        goto cleanup;
2445 2446 2447 2448 2449 2450
    }
    header.xml_len = strlen(xml) + 1;

    /* Write header to file, followed by XML */
    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2451
                         _("failed to create '%s'"), path);
2452
        goto cleanup;
2453 2454 2455 2456
    }

    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2457
                         "%s", _("failed to write save header"));
2458
        goto cleanup;
2459 2460 2461 2462
    }

    if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2463
                         "%s", _("failed to write xml"));
2464
        goto cleanup;
2465 2466
    }

2467
    if (close(fd) < 0) {
2468 2469 2470
        virReportSystemError(dom->conn, errno,
                             _("unable to save file %s"),
                             path);
2471 2472 2473
        goto cleanup;
    }
    fd = -1;
2474 2475 2476 2477

    /* Migrate to file */
    safe_path = qemudEscapeShellArg(path);
    if (!safe_path) {
2478
        virReportOOMError(dom->conn);
2479
        goto cleanup;
2480
    }
2481
    if (virAsprintf(&command, "migrate \"exec:"
2482
                  "dd of='%s' oflag=append conv=notrunc 2>/dev/null"
2483
                  "\"", safe_path) == -1) {
2484
        virReportOOMError(dom->conn);
2485 2486
        command = NULL;
        goto cleanup;
2487 2488
    }

2489
    if (qemudMonitorCommand(vm, command, &info) < 0) {
2490
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2491
                         "%s", _("migrate operation failed"));
2492
        goto cleanup;
2493 2494
    }

2495 2496 2497 2498 2499 2500 2501 2502
    DEBUG ("migrate reply: %s", info);

    /* If the command isn't supported then qemu prints:
     * unknown command: migrate" */
    if (strstr(info, "unknown command:")) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s",
                          _("'migrate' not supported by this qemu"));
2503
        goto cleanup;
2504 2505
    }

2506 2507
    /* Shut it down */
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2508 2509 2510
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2511
    if (!vm->persistent) {
2512 2513
        virDomainRemoveInactive(&driver->domains,
                                vm);
2514 2515
        vm = NULL;
    }
2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526
    ret = 0;

cleanup:
    if (fd != -1)
        close(fd);
    VIR_FREE(xml);
    VIR_FREE(safe_path);
    VIR_FREE(command);
    VIR_FREE(info);
    if (ret != 0)
        unlink(path);
2527 2528
    if (vm)
        virDomainObjUnlock(vm);
2529 2530
    if (event)
        qemuDomainEventQueue(driver, event);
2531
    qemuDriverUnlock(driver);
2532
    return ret;
D
Daniel P. Berrange 已提交
2533 2534 2535
}


2536
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
2537 2538
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2539
    int max;
2540
    int ret = -1;
2541

2542
    qemuDriverLock(driver);
2543
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2544 2545
    qemuDriverUnlock(driver);

2546
    if (!vm) {
2547 2548 2549
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2550
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2551
                         _("no domain with matching uuid '%s'"), uuidstr);
2552
        goto cleanup;
2553 2554
    }

2555
    if (virDomainIsActive(vm)) {
2556
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
2557
                         _("cannot change vcpu count of an active domain"));
2558
        goto cleanup;
2559 2560 2561 2562 2563
    }

    if ((max = qemudDomainGetMaxVcpus(dom)) < 0) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                         _("could not determine max vcpus for the domain"));
2564
        goto cleanup;
2565 2566 2567 2568 2569 2570
    }

    if (nvcpus > max) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         _("requested vcpus is greater than max allowable"
                           " vcpus for the domain: %d > %d"), nvcpus, max);
2571
        goto cleanup;
2572 2573 2574
    }

    vm->def->vcpus = nvcpus;
2575 2576 2577
    ret = 0;

cleanup:
2578 2579
    if (vm)
        virDomainObjUnlock(vm);
2580
    return ret;
2581 2582
}

2583 2584 2585 2586 2587 2588 2589

#if HAVE_SCHED_GETAFFINITY
static int
qemudDomainPinVcpu(virDomainPtr dom,
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
2590 2591
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2592 2593 2594
    cpu_set_t mask;
    int i, maxcpu;
    virNodeInfo nodeinfo;
2595
    int ret = -1;
2596

2597
    qemuDriverLock(driver);
2598
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2599 2600
    qemuDriverUnlock(driver);

2601
    if (!virDomainIsActive(vm)) {
2602 2603
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         "%s",_("cannot pin vcpus on an inactive domain"));
2604
        goto cleanup;
2605 2606 2607 2608 2609 2610
    }

    if (vcpu > (vm->nvcpupids-1)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         _("vcpu number out of range %d > %d"),
                         vcpu, vm->nvcpupids);
2611
        goto cleanup;
2612 2613 2614
    }

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2615
        goto cleanup;
2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628

    maxcpu = maplen * 8;
    if (maxcpu > nodeinfo.cpus)
        maxcpu = nodeinfo.cpus;

    CPU_ZERO(&mask);
    for (i = 0 ; i < maxcpu ; i++) {
        if ((cpumap[i/8] >> (i % 8)) & 1)
            CPU_SET(i, &mask);
    }

    if (vm->vcpupids != NULL) {
        if (sched_setaffinity(vm->vcpupids[vcpu], sizeof(mask), &mask) < 0) {
2629 2630
            virReportSystemError(dom->conn, errno, "%s",
                                 _("cannot set affinity"));
2631
            goto cleanup;
2632 2633 2634 2635
        }
    } else {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("cpu affinity is not supported"));
2636
        goto cleanup;
2637
    }
2638
    ret = 0;
2639

2640
cleanup:
2641 2642
    if (vm)
        virDomainObjUnlock(vm);
2643
    return ret;
2644 2645 2646 2647 2648 2649 2650 2651
}

static int
qemudDomainGetVcpus(virDomainPtr dom,
                    virVcpuInfoPtr info,
                    int maxinfo,
                    unsigned char *cpumaps,
                    int maplen) {
2652 2653
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2654 2655
    virNodeInfo nodeinfo;
    int i, v, maxcpu;
2656
    int ret = -1;
2657

2658
    qemuDriverLock(driver);
2659
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2660 2661
    qemuDriverUnlock(driver);

2662
    if (!virDomainIsActive(vm)) {
2663 2664
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         "%s",_("cannot pin vcpus on an inactive domain"));
2665
        goto cleanup;
2666 2667 2668
    }

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2669
        goto cleanup;
2670 2671 2672 2673 2674 2675 2676 2677 2678

    maxcpu = maplen * 8;
    if (maxcpu > nodeinfo.cpus)
        maxcpu = nodeinfo.cpus;

    /* Clamp to actual number of vcpus */
    if (maxinfo > vm->nvcpupids)
        maxinfo = vm->nvcpupids;

2679 2680 2681 2682 2683 2684 2685 2686
    if (maxinfo >= 1) {
        if (info != NULL) {
            memset(info, 0, sizeof(*info) * maxinfo);
            for (i = 0 ; i < maxinfo ; i++) {
                info[i].number = i;
                info[i].state = VIR_VCPU_RUNNING;
                /* XXX cpu time, current pCPU mapping */
            }
2687 2688
        }

2689 2690 2691 2692 2693 2694 2695 2696 2697
        if (cpumaps != NULL) {
            memset(cpumaps, 0, maplen * maxinfo);
            if (vm->vcpupids != NULL) {
                for (v = 0 ; v < maxinfo ; v++) {
                    cpu_set_t mask;
                    unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
                    CPU_ZERO(&mask);

                    if (sched_getaffinity(vm->vcpupids[v], sizeof(mask), &mask) < 0) {
2698 2699
                        virReportSystemError(dom->conn, errno, "%s",
                                             _("cannot get affinity"));
2700 2701 2702 2703 2704 2705
                        goto cleanup;
                    }

                    for (i = 0 ; i < maxcpu ; i++)
                        if (CPU_ISSET(i, &mask))
                            VIR_USE_CPU(cpumap, i);
2706
                }
2707 2708 2709 2710
            } else {
                qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                                 "%s", _("cpu affinity is not available"));
                goto cleanup;
2711 2712 2713
            }
        }
    }
2714
    ret = maxinfo;
2715

2716
cleanup:
2717 2718
    if (vm)
        virDomainObjUnlock(vm);
2719
    return ret;
2720 2721 2722 2723
}
#endif /* HAVE_SCHED_GETAFFINITY */


2724
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
2725 2726
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2727
    const char *type;
2728
    int ret = -1;
2729

2730
    qemuDriverLock(driver);
2731
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2732 2733
    qemuDriverUnlock(driver);

2734
    if (!vm) {
2735 2736 2737
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2738
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2739
                         _("no domain with matching uuid '%s'"), uuidstr);
2740
        goto cleanup;
2741 2742
    }

2743
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
2744 2745 2746
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("unknown virt type in domain definition '%d'"),
                         vm->def->virtType);
2747
        goto cleanup;
2748 2749
    }

2750
    ret = qemudGetMaxVCPUs(dom->conn, type);
2751

2752
cleanup:
2753 2754
    if (vm)
        virDomainObjUnlock(vm);
2755 2756 2757 2758
    return ret;
}


2759
static int qemudDomainRestore(virConnectPtr conn,
2760 2761 2762
                              const char *path) {
    struct qemud_driver *driver = conn->privateData;
    virDomainDefPtr def = NULL;
2763
    virDomainObjPtr vm = NULL;
2764 2765 2766
    int fd = -1;
    int ret = -1;
    char *xml = NULL;
2767
    struct qemud_save_header header;
2768
    virDomainEventPtr event = NULL;
2769

2770
    qemuDriverLock(driver);
2771 2772 2773
    /* Verify the header and read the XML */
    if ((fd = open(path, O_RDONLY)) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2774
                         "%s", _("cannot read domain image"));
2775
        goto cleanup;
2776 2777 2778 2779
    }

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2780
                         "%s", _("failed to read qemu header"));
2781
        goto cleanup;
2782 2783 2784 2785
    }

    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2786
                         "%s", _("image magic is incorrect"));
2787
        goto cleanup;
2788 2789 2790 2791
    }

    if (header.version > QEMUD_SAVE_VERSION) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2792
                         _("image version is not supported (%d > %d)"),
2793
                         header.version, QEMUD_SAVE_VERSION);
2794
        goto cleanup;
2795 2796
    }

2797
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
2798
        virReportOOMError(conn);
2799
        goto cleanup;
2800 2801 2802 2803
    }

    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2804
                         "%s", _("failed to read XML"));
2805
        goto cleanup;
2806 2807 2808
    }

    /* Create a domain from this XML */
2809 2810
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
2811
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2812
                         "%s", _("failed to parse XML"));
2813
        goto cleanup;
2814 2815 2816
    }

    /* Ensure the name and UUID don't already exist in an active VM */
2817
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
2818
    if (!vm)
2819
        vm = virDomainFindByName(&driver->domains, def->name);
2820 2821 2822 2823 2824 2825 2826 2827
    if (vm) {
        if (virDomainIsActive(vm)) {
            qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                             _("domain is already active as '%s'"), vm->def->name);
            goto cleanup;
        } else {
            virDomainObjUnlock(vm);
        }
2828 2829
    }

2830 2831 2832
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
2833
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2834
                         "%s", _("failed to assign new VM"));
2835
        goto cleanup;
2836
    }
2837
    def = NULL;
2838 2839

    /* Set the migration source and start it up. */
2840
    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
2841
    close(fd);
2842
    fd = -1;
2843
    if (ret < 0) {
2844
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2845
                         "%s", _("failed to start VM"));
2846
        if (!vm->persistent) {
2847 2848
            virDomainRemoveInactive(&driver->domains,
                                    vm);
2849 2850
            vm = NULL;
        }
2851
        goto cleanup;
2852 2853
    }

2854 2855 2856
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2857

2858 2859 2860
    /* If it was running before, resume it now. */
    if (header.was_running) {
        char *info;
2861
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
2862
            qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2863
                             "%s", _("failed to resume domain"));
2864
            goto cleanup;
2865
        }
2866
        VIR_FREE(info);
2867 2868
        vm->state = VIR_DOMAIN_RUNNING;
    }
2869
    ret = 0;
2870

2871 2872 2873 2874 2875
cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
2876 2877
    if (vm)
        virDomainObjUnlock(vm);
2878 2879
    if (event)
        qemuDomainEventQueue(driver, event);
2880
    qemuDriverUnlock(driver);
2881
    return ret;
D
Daniel P. Berrange 已提交
2882 2883 2884
}


2885
static char *qemudDomainDumpXML(virDomainPtr dom,
2886
                                int flags ATTRIBUTE_UNUSED) {
2887 2888 2889 2890
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;

2891
    qemuDriverLock(driver);
2892
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2893 2894
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
2895
    if (!vm) {
2896 2897
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
2898
        goto cleanup;
D
Daniel P. Berrange 已提交
2899 2900
    }

2901 2902 2903 2904 2905 2906
    ret = virDomainDefFormat(dom->conn,
                             (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
                             vm->newDef : vm->def,
                             flags);

cleanup:
2907 2908
    if (vm)
        virDomainObjUnlock(vm);
2909
    return ret;
D
Daniel P. Berrange 已提交
2910 2911 2912
}


2913
static int qemudListDefinedDomains(virConnectPtr conn,
2914
                            char **const names, int nnames) {
2915
    struct qemud_driver *driver = conn->privateData;
2916
    int got = 0, i;
2917

2918
    qemuDriverLock(driver);
2919
    for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
2920
        virDomainObjLock(driver->domains.objs[i]);
2921 2922
        if (!virDomainIsActive(driver->domains.objs[i])) {
            if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) {
2923
                virReportOOMError(conn);
2924
                virDomainObjUnlock(driver->domains.objs[i]);
2925 2926
                goto cleanup;
            }
2927
        }
2928
        virDomainObjUnlock(driver->domains.objs[i]);
D
Daniel P. Berrange 已提交
2929
    }
2930

2931
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
2932
    return got;
2933 2934 2935

 cleanup:
    for (i = 0 ; i < got ; i++)
2936
        VIR_FREE(names[i]);
2937
    qemuDriverUnlock(driver);
2938
    return -1;
D
Daniel P. Berrange 已提交
2939 2940
}

2941
static int qemudNumDefinedDomains(virConnectPtr conn) {
2942
    struct qemud_driver *driver = conn->privateData;
2943 2944
    int n = 0, i;

2945
    qemuDriverLock(driver);
2946 2947
    for (i = 0 ; i < driver->domains.count ; i++)
        if (!virDomainIsActive(driver->domains.objs[i]))
2948
            n++;
2949
    qemuDriverUnlock(driver);
2950

2951
    return n;
D
Daniel P. Berrange 已提交
2952 2953 2954
}


2955
static int qemudDomainStart(virDomainPtr dom) {
2956 2957 2958
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2959
    virDomainEventPtr event = NULL;
2960

2961
    qemuDriverLock(driver);
2962
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2963 2964
    qemuDriverUnlock(driver);

2965
    if (!vm) {
2966
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2967
                         "%s", _("no domain with matching uuid"));
2968
        goto cleanup;
2969 2970
    }

2971
    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
2972
    if (ret != -1)
2973 2974 2975
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
2976 2977

cleanup:
2978 2979
    if (vm)
        virDomainObjUnlock(vm);
2980 2981 2982 2983 2984
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2985
    return ret;
D
Daniel P. Berrange 已提交
2986 2987 2988
}


2989
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
2990
    struct qemud_driver *driver = conn->privateData;
2991
    virDomainDefPtr def;
2992
    virDomainObjPtr vm = NULL;
2993
    virDomainPtr dom = NULL;
2994
    virDomainEventPtr event = NULL;
2995
    int newVM = 1;
2996

2997
    qemuDriverLock(driver);
2998 2999
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
3000
        goto cleanup;
3001

3002
    vm = virDomainFindByName(&driver->domains, def->name);
3003 3004
    if (vm) {
        virDomainObjUnlock(vm);
3005
        newVM = 0;
3006
    }
3007

3008 3009 3010 3011
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
        virDomainDefFree(def);
3012
        goto cleanup;
3013
    }
3014
    vm->persistent = 1;
3015

3016 3017
    if (virDomainSaveConfig(conn,
                            driver->configDir,
3018
                            vm->newDef ? vm->newDef : vm->def) < 0) {
3019 3020
        virDomainRemoveInactive(&driver->domains,
                                vm);
3021
        vm = NULL;
3022
        goto cleanup;
3023 3024
    }

3025 3026 3027 3028 3029
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     newVM ?
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
3030

3031
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3032
    if (dom) dom->id = vm->def->id;
3033 3034

cleanup:
3035 3036
    if (vm)
        virDomainObjUnlock(vm);
3037 3038
    if (event)
        qemuDomainEventQueue(driver, event);
3039
    qemuDriverUnlock(driver);
3040
    return dom;
D
Daniel P. Berrange 已提交
3041 3042
}

3043
static int qemudDomainUndefine(virDomainPtr dom) {
3044 3045
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3046
    virDomainEventPtr event = NULL;
3047
    int ret = -1;
D
Daniel P. Berrange 已提交
3048

3049
    qemuDriverLock(driver);
3050
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3051

D
Daniel P. Berrange 已提交
3052
    if (!vm) {
3053 3054
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3055
        goto cleanup;
D
Daniel P. Berrange 已提交
3056 3057
    }

3058
    if (virDomainIsActive(vm)) {
3059 3060
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot delete active domain"));
3061
        goto cleanup;
D
Daniel P. Berrange 已提交
3062 3063
    }

3064 3065 3066
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot undefine transient domain"));
3067
        goto cleanup;
3068 3069 3070
    }

    if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0)
3071
        goto cleanup;
D
Daniel P. Berrange 已提交
3072

3073 3074 3075
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
3076

3077 3078
    virDomainRemoveInactive(&driver->domains,
                            vm);
3079
    vm = NULL;
3080
    ret = 0;
D
Daniel P. Berrange 已提交
3081

3082
cleanup:
3083 3084
    if (vm)
        virDomainObjUnlock(vm);
3085 3086
    if (event)
        qemuDomainEventQueue(driver, event);
3087
    qemuDriverUnlock(driver);
3088
    return ret;
D
Daniel P. Berrange 已提交
3089 3090
}

3091
/* Return the disks name for use in monitor commands */
3092
static char *qemudDiskDeviceName(const virConnectPtr conn,
3093
                                 const virDomainDiskDefPtr disk) {
3094 3095 3096 3097 3098 3099

    int busid, devid;
    int ret;
    char *devname;

    if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) {
3100
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
3101 3102 3103 3104 3105 3106 3107
                         _("cannot convert disk '%s' to bus/device index"),
                         disk->dst);
        return NULL;
    }

    switch (disk->bus) {
        case VIR_DOMAIN_DISK_BUS_IDE:
3108
            if (disk->device== VIR_DOMAIN_DISK_DEVICE_DISK)
3109
                ret = virAsprintf(&devname, "ide%d-hd%d", busid, devid);
3110
            else
3111
                ret = virAsprintf(&devname, "ide%d-cd%d", busid, devid);
3112 3113
            break;
        case VIR_DOMAIN_DISK_BUS_SCSI:
3114
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
3115
                ret = virAsprintf(&devname, "scsi%d-hd%d", busid, devid);
3116
            else
3117
                ret = virAsprintf(&devname, "scsi%d-cd%d", busid, devid);
3118 3119
            break;
        case VIR_DOMAIN_DISK_BUS_FDC:
3120
            ret = virAsprintf(&devname, "floppy%d", devid);
3121 3122
            break;
        case VIR_DOMAIN_DISK_BUS_VIRTIO:
3123
            ret = virAsprintf(&devname, "virtio%d", devid);
3124 3125
            break;
        default:
3126
            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
3127 3128 3129 3130 3131 3132
                             _("Unsupported disk name mapping for bus '%s'"),
                             virDomainDiskBusTypeToString(disk->bus));
            return NULL;
    }

    if (ret == -1) {
3133
        virReportOOMError(conn);
3134 3135 3136 3137 3138 3139
        return NULL;
    }

    return devname;
}

3140 3141
static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
                                           virDomainObjPtr vm,
3142 3143
                                           virDomainDeviceDefPtr dev)
{
3144
    virDomainDiskDefPtr origdisk = NULL, newdisk;
3145
    char *cmd, *reply, *safe_path;
3146
    char *devname = NULL;
3147
    unsigned int qemuCmdFlags;
3148
    int i;
3149

3150
    origdisk = NULL;
3151
    newdisk = dev->data.disk;
3152 3153 3154 3155
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (vm->def->disks[i]->bus == newdisk->bus &&
            STREQ(vm->def->disks[i]->dst, newdisk->dst)) {
            origdisk = vm->def->disks[i];
3156
            break;
3157
        }
3158 3159 3160
    }

    if (!origdisk) {
3161
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3162 3163 3164 3165 3166 3167 3168 3169 3170
                         _("No device with bus '%s' and target '%s'"),
                         virDomainDiskBusTypeToString(newdisk->bus),
                         newdisk->dst);
        return -1;
    }

    if (qemudExtractVersionInfo(vm->def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0) {
3171
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3172 3173 3174 3175 3176 3177
                         _("Cannot determine QEMU argv syntax %s"),
                         vm->def->emulator);
        return -1;
    }

    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
3178
        if (!(devname = qemudDiskDeviceName(conn, newdisk)))
3179 3180 3181 3182 3183 3184 3185 3186 3187
            return -1;
    } else {
        /* Back compat for no -drive option */
        if (newdisk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
            devname = strdup(newdisk->dst);
        else if (newdisk->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
                 STREQ(newdisk->dst, "hdc"))
            devname = strdup("cdrom");
        else {
3188
            qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3189 3190 3191 3192 3193 3194 3195 3196
                             _("Emulator version does not support removable "
                               "media for device '%s' and target '%s'"),
                               virDomainDiskDeviceTypeToString(newdisk->device),
                               newdisk->dst);
            return -1;
        }

        if (!devname) {
3197
            virReportOOMError(conn);
3198 3199 3200
            return -1;
        }
    }
3201

3202
    if (newdisk->src) {
3203 3204
        safe_path = qemudEscapeMonitorArg(newdisk->src);
        if (!safe_path) {
3205
            virReportOOMError(conn);
3206
            VIR_FREE(devname);
3207 3208
            return -1;
        }
3209
        if (virAsprintf(&cmd, "change %s \"%s\"", devname, safe_path) == -1) {
3210
            virReportOOMError(conn);
3211
            VIR_FREE(safe_path);
3212
            VIR_FREE(devname);
3213 3214
            return -1;
        }
3215
        VIR_FREE(safe_path);
3216

3217
    } else if (virAsprintf(&cmd, "eject %s", devname) == -1) {
3218
        virReportOOMError(conn);
3219
        VIR_FREE(devname);
3220 3221
        return -1;
    }
3222
    VIR_FREE(devname);
3223

3224
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3225
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3226
                         "%s", _("could not change cdrom media"));
3227
        VIR_FREE(cmd);
3228 3229
        return -1;
    }
3230 3231 3232 3233

    /* If the command failed qemu prints:
     * device not found, device is locked ...
     * No message is printed on success it seems */
3234
    DEBUG ("ejectable media change reply: %s", reply);
3235
    if (strstr(reply, "\ndevice ")) {
3236
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3237
                          _("changing cdrom media failed: %s"), reply);
3238 3239 3240 3241
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3242 3243
    VIR_FREE(reply);
    VIR_FREE(cmd);
3244

3245 3246
    VIR_FREE(origdisk->src);
    origdisk->src = newdisk->src;
3247
    newdisk->src = NULL;
3248
    origdisk->type = newdisk->type;
3249 3250 3251
    return 0;
}

3252 3253 3254
static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm,
                                          virDomainDeviceDefPtr dev)
3255 3256
{
    int ret, i;
3257
    char *cmd, *reply, *s;
3258 3259 3260 3261 3262
    char *safe_path;
    const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);

    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
3263
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3264 3265 3266 3267 3268 3269
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3270
        virReportOOMError(conn);
3271 3272 3273 3274 3275
        return -1;
    }

    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3276
        virReportOOMError(conn);
3277 3278 3279
        return -1;
    }

3280 3281
    ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
                      safe_path, type);
3282 3283
    VIR_FREE(safe_path);
    if (ret == -1) {
3284
        virReportOOMError(conn);
3285 3286 3287
        return ret;
    }

3288
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3289
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3290 3291 3292 3293 3294 3295 3296 3297
                         _("cannot attach %s disk"), type);
        VIR_FREE(cmd);
        return -1;
    }

    DEBUG ("pci_add reply: %s", reply);
    /* If the command succeeds qemu prints:
     * OK bus 0... */
3298 3299 3300 3301 3302 3303
#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
    if ((s=strstr(reply, PCI_ATTACH_OK_MSG))) {
        char* dummy = s;
        s += strlen(PCI_ATTACH_OK_MSG);

        if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
J
Jim Meyering 已提交
3304
            qemudLog(QEMUD_WARN, "%s", _("Unable to parse slot number\n"));
3305
    } else {
3306
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320
                          _("adding %s disk failed"), type);
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }

    vm->def->disks[vm->def->ndisks++] = dev->data.disk;
    qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
          virDomainDiskQSort);

    VIR_FREE(reply);
    VIR_FREE(cmd);
    return 0;
}
3321

3322 3323 3324
static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
                                                 virDomainObjPtr vm,
                                                 virDomainDeviceDefPtr dev)
3325
{
3326 3327
    int ret, i;
    char *safe_path;
3328 3329
    char *cmd, *reply;

3330 3331
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
3332
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3333 3334 3335 3336 3337
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

3338
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3339
        virReportOOMError(conn);
3340
        return -1;
3341 3342
    }

3343 3344
    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3345
        virReportOOMError(conn);
3346 3347 3348
        return -1;
    }

3349
    ret = virAsprintf(&cmd, "usb_add disk:%s", safe_path);
3350
    VIR_FREE(safe_path);
3351
    if (ret == -1) {
3352
        virReportOOMError(conn);
3353 3354 3355
        return ret;
    }

3356
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3357
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3358
                         "%s", _("cannot attach usb disk"));
3359 3360 3361 3362 3363 3364 3365 3366
        VIR_FREE(cmd);
        return -1;
    }

    DEBUG ("attach_usb reply: %s", reply);
    /* If the command failed qemu prints:
     * Could not add ... */
    if (strstr(reply, "Could not add ")) {
3367
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3368
                          "%s",
3369
                          _("adding usb disk failed"));
3370 3371 3372 3373
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3374

3375 3376 3377
    vm->def->disks[vm->def->ndisks++] = dev->data.disk;
    qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
          virDomainDiskQSort);
3378

3379 3380 3381 3382 3383
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return 0;
}

3384 3385 3386
static int qemudDomainAttachHostDevice(virConnectPtr conn,
                                       virDomainObjPtr vm,
                                       virDomainDeviceDefPtr dev)
3387 3388 3389 3390
{
    int ret;
    char *cmd, *reply;

3391
    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
3392
        virReportOOMError(conn);
3393 3394
        return -1;
    }
3395

3396
    if (dev->data.hostdev->source.subsys.u.usb.vendor) {
3397 3398 3399
        ret = virAsprintf(&cmd, "usb_add host:%.4x:%.4x",
                          dev->data.hostdev->source.subsys.u.usb.vendor,
                          dev->data.hostdev->source.subsys.u.usb.product);
3400
    } else {
3401 3402 3403
        ret = virAsprintf(&cmd, "usb_add host:%.3d.%.3d",
                          dev->data.hostdev->source.subsys.u.usb.bus,
                          dev->data.hostdev->source.subsys.u.usb.device);
3404 3405
    }
    if (ret == -1) {
3406
        virReportOOMError(conn);
3407 3408 3409
        return -1;
    }

3410
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3411
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3412 3413 3414 3415 3416 3417 3418 3419 3420
                         "%s", _("cannot attach usb device"));
        VIR_FREE(cmd);
        return -1;
    }

    DEBUG ("attach_usb reply: %s", reply);
    /* If the command failed qemu prints:
     * Could not add ... */
    if (strstr(reply, "Could not add ")) {
3421
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3422 3423 3424 3425 3426 3427
                          "%s",
                          _("adding usb device failed"));
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3428

3429
    vm->def->hostdevs[vm->def->nhostdevs++] = dev->data.hostdev;
3430

3431 3432
    VIR_FREE(reply);
    VIR_FREE(cmd);
3433 3434 3435
    return 0;
}

3436 3437
static int qemudDomainAttachDevice(virDomainPtr dom,
                                   const char *xml) {
3438 3439 3440 3441
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
3442

3443
    qemuDriverLock(driver);
3444
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3445
    if (!vm) {
3446
        qemuDriverUnlock(driver);
3447 3448
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3449
        goto cleanup;
3450 3451 3452
    }

    if (!virDomainIsActive(vm)) {
3453
        qemuDriverUnlock(driver);
3454 3455
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot attach device on inactive domain"));
3456
        goto cleanup;
3457 3458
    }

3459 3460
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
3461
    qemuDriverUnlock(driver);
3462 3463 3464
    if (dev == NULL)
        goto cleanup;

3465

3466 3467
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        switch (dev->data.disk->device) {
3468 3469
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
        case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
3470
            ret = qemudDomainChangeEjectableMedia(dom->conn, vm, dev);
3471 3472 3473
            break;
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
3474
                ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, vm, dev);
3475 3476
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
                       dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
3477
                ret = qemudDomainAttachPciDiskDevice(dom->conn, vm, dev);
3478 3479 3480 3481 3482 3483
            }
            break;
        default:
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                             "%s", _("this disk device type cannot be attached"));
            goto cleanup;
3484
        }
3485
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
3486 3487
               dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
               dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
3488
        ret = qemudDomainAttachHostDevice(dom->conn, vm, dev);
3489
    } else {
3490
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
3491
                         "%s", _("this device type cannot be attached"));
3492
        goto cleanup;
3493 3494
    }

3495 3496 3497
    if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        ret = -1;

3498
cleanup:
G
Guido Günther 已提交
3499 3500
    if (ret < 0)
        virDomainDeviceDefFree(dev);
3501 3502
    if (vm)
        virDomainObjUnlock(vm);
3503 3504 3505
    return ret;
}

3506 3507
static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3508 3509
{
    int i, ret = -1;
3510 3511
    char *cmd = NULL;
    char *reply = NULL;
3512 3513 3514 3515 3516 3517 3518 3519 3520 3521
    virDomainDiskDefPtr detach = NULL;

    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
            detach = vm->def->disks[i];
            break;
        }
    }

    if (!detach) {
3522
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3523
                         _("disk %s not found"), dev->data.disk->dst);
3524
        goto cleanup;
3525 3526 3527
    }

    if (detach->slotnum < 1) {
3528
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3529
                         _("disk %s cannot be detached - invalid slot number %d"),
3530
                           detach->dst, detach->slotnum);
3531
        goto cleanup;
3532 3533
    }

3534
    if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
3535
        virReportOOMError(conn);
3536
        goto cleanup;
3537 3538
    }

3539
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3540
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3541
                          _("failed to execute detach disk %s command"), detach->dst);
3542
        goto cleanup;
3543 3544 3545 3546 3547 3548
    }

    DEBUG ("pci_del reply: %s", reply);
    /* If the command fails due to a wrong slot qemu prints: invalid slot,
     * nothing is printed on success */
    if (strstr(reply, "invalid slot")) {
3549
        qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3550
                          _("failed to detach disk %s: invalid slot %d"),
3551 3552
                          detach->dst, detach->slotnum);
        goto cleanup;
3553 3554 3555 3556 3557
    }

    if (vm->def->ndisks > 1) {
        vm->def->disks[i] = vm->def->disks[--vm->def->ndisks];
        if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
3558
            virReportOOMError(conn);
3559
            goto cleanup;
3560 3561 3562 3563 3564 3565 3566 3567
        }
        qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
              virDomainDiskQSort);
    } else {
        VIR_FREE(vm->def->disks[0]);
        vm->def->ndisks = 0;
    }
    ret = 0;
3568 3569

cleanup:
3570 3571 3572 3573 3574 3575 3576
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}

static int qemudDomainDetachDevice(virDomainPtr dom,
                                   const char *xml) {
3577 3578 3579 3580
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
3581

3582
    qemuDriverLock(driver);
3583
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3584
    if (!vm) {
3585
        qemuDriverUnlock(driver);
3586 3587
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3588
        goto cleanup;
3589 3590 3591
    }

    if (!virDomainIsActive(vm)) {
3592
        qemuDriverUnlock(driver);
3593
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
G
Guido Günther 已提交
3594
                         "%s", _("cannot detach device on inactive domain"));
3595
        goto cleanup;
3596 3597
    }

3598 3599
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
3600
    qemuDriverUnlock(driver);
3601 3602 3603
    if (dev == NULL)
        goto cleanup;

3604 3605 3606 3607 3608

    if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
        dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
        (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
         dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO))
3609
        ret = qemudDomainDetachPciDiskDevice(dom->conn, vm, dev);
3610
    else
3611 3612 3613
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("only SCSI or virtio disk device can be detached dynamically"));

3614 3615 3616
    if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        ret = -1;

3617 3618
cleanup:
    virDomainDeviceDefFree(dev);
3619 3620
    if (vm)
        virDomainObjUnlock(vm);
3621 3622 3623
    return ret;
}

3624
static int qemudDomainGetAutostart(virDomainPtr dom,
3625
                                   int *autostart) {
3626 3627 3628
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3629

3630
    qemuDriverLock(driver);
3631
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3632 3633
    qemuDriverUnlock(driver);

3634
    if (!vm) {
3635 3636
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3637
        goto cleanup;
3638 3639 3640
    }

    *autostart = vm->autostart;
3641
    ret = 0;
3642

3643
cleanup:
3644 3645
    if (vm)
        virDomainObjUnlock(vm);
3646
    return ret;
3647 3648
}

3649
static int qemudDomainSetAutostart(virDomainPtr dom,
3650
                                   int autostart) {
3651 3652
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3653 3654
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
3655

3656
    qemuDriverLock(driver);
3657
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3658 3659
    qemuDriverUnlock(driver);

3660
    if (!vm) {
3661 3662
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3663
        goto cleanup;
3664 3665
    }

3666 3667 3668
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot set autostart for transient domain"));
3669
        goto cleanup;
3670 3671
    }

3672 3673
    autostart = (autostart != 0);

3674 3675 3676 3677 3678
    if (vm->autostart != autostart) {
        if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL)
            goto cleanup;
        if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL)
            goto cleanup;
3679

3680 3681
        if (autostart) {
            int err;
3682

3683
            if ((err = virFileMakePath(driver->autostartDir))) {
3684 3685 3686
                virReportSystemError(dom->conn, err,
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
3687 3688
                goto cleanup;
            }
3689

3690
            if (symlink(configFile, autostartLink) < 0) {
3691 3692 3693
                virReportSystemError(dom->conn, errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
3694 3695 3696 3697
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
3698 3699 3700
                virReportSystemError(dom->conn, errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
3701 3702
                goto cleanup;
            }
3703 3704
        }

3705
        vm->autostart = autostart;
3706
    }
3707
    ret = 0;
3708

3709 3710 3711
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
3712 3713
    if (vm)
        virDomainObjUnlock(vm);
3714
    return ret;
3715 3716
}

3717 3718 3719 3720 3721 3722 3723 3724 3725
/* This uses the 'info blockstats' monitor command which was
 * integrated into both qemu & kvm in late 2007.  If the command is
 * not supported we detect this and return the appropriate error.
 */
static int
qemudDomainBlockStats (virDomainPtr dom,
                       const char *path,
                       struct _virDomainBlockStats *stats)
{
3726
    struct qemud_driver *driver = dom->conn->privateData;
3727
    char *dummy, *info = NULL;
3728
    const char *p, *eol;
3729
    const char *qemu_dev_name = NULL;
3730
    size_t len;
3731
    int i, ret = -1;
3732
    virDomainObjPtr vm;
3733
    virDomainDiskDefPtr disk = NULL;
3734

3735
    qemuDriverLock(driver);
3736
    vm = virDomainFindByID(&driver->domains, dom->id);
3737
    qemuDriverUnlock(driver);
3738 3739 3740
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
3741
        goto cleanup;
3742
    }
3743
    if (!virDomainIsActive (vm)) {
3744 3745
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
3746
        goto cleanup;
3747 3748
    }

3749 3750 3751 3752 3753 3754 3755 3756
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(path, vm->def->disks[i]->dst)) {
            disk = vm->def->disks[i];
            break;
        }
    }

    if (!disk) {
3757 3758
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          _("invalid path: %s"), path);
3759
        goto cleanup;
3760 3761
    }

3762
    qemu_dev_name = qemudDiskDeviceName(dom->conn, disk);
3763
    if (!qemu_dev_name)
3764
        goto cleanup;
3765 3766
    len = strlen (qemu_dev_name);

3767
    if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) {
3768 3769
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("'info blockstats' command failed"));
3770
        goto cleanup;
3771 3772 3773 3774 3775 3776 3777 3778
    }
    DEBUG ("info blockstats reply: %s", info);

    /* 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.
     */
C
Cole Robinson 已提交
3779
    if (strstr(info, "\ninfo ")) {
3780 3781 3782
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s",
                          _("'info blockstats' not supported by this qemu"));
3783
        goto cleanup;
3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809
    }

    stats->rd_req = -1;
    stats->rd_bytes = -1;
    stats->wr_req = -1;
    stats->wr_bytes = -1;
    stats->errs = -1;

    /* 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.
     */
    p = info;

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

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

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

            while (*p) {
3810
                if (STRPREFIX (p, "rd_bytes=")) {
3811 3812 3813
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1)
                        DEBUG ("error reading rd_bytes: %s", p);
3814
                } else if (STRPREFIX (p, "wr_bytes=")) {
3815 3816 3817
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1)
                        DEBUG ("error reading wr_bytes: %s", p);
3818
                } else if (STRPREFIX (p, "rd_operations=")) {
3819 3820 3821
                    p += 14;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1)
                        DEBUG ("error reading rd_req: %s", p);
3822
                } else if (STRPREFIX (p, "wr_operations=")) {
3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833
                    p += 14;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->wr_req) == -1)
                        DEBUG ("error reading wr_req: %s", p);
                } else
                    DEBUG ("unknown block stat near %s", p);

                /* Skip to next label. */
                p = strchr (p, ' ');
                if (!p || p >= eol) break;
                p++;
            }
3834
            ret = 0;
3835
            goto cleanup;
3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846
        }

        /* Skip to next line. */
        p = strchr (p, '\n');
        if (!p) break;
        p++;
    }

    /* If we reach here then the device was not found. */
    qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                      _("device not found: %s (%s)"), path, qemu_dev_name);
3847
 cleanup:
3848 3849
    VIR_FREE(qemu_dev_name);
    VIR_FREE(info);
3850 3851
    if (vm)
        virDomainObjUnlock(vm);
3852
    return ret;
3853 3854
}

3855
#ifdef __linux__
3856 3857 3858 3859 3860
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path,
                           struct _virDomainInterfaceStats *stats)
{
3861 3862
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3863
    int i;
3864
    int ret = -1;
3865

3866
    qemuDriverLock(driver);
3867
    vm = virDomainFindByID(&driver->domains, dom->id);
3868 3869
    qemuDriverUnlock(driver);

3870 3871
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
3872
                          _("no domain with matching id %d"), dom->id);
3873
        goto cleanup;
3874 3875
    }

3876
    if (!virDomainIsActive(vm)) {
3877
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3878
                         "%s", _("domain is not running"));
3879
        goto cleanup;
3880 3881 3882 3883
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
3884
                         "%s", _("NULL or empty path"));
3885
        goto cleanup;
3886 3887 3888
    }

    /* Check the path is one of the domain's network interfaces. */
3889 3890
    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (vm->def->nets[i]->ifname &&
3891 3892 3893 3894
            STREQ (vm->def->nets[i]->ifname, path)) {
            ret = 0;
            break;
        }
3895 3896
    }

3897 3898 3899 3900 3901
    if (ret == 0)
        ret = linuxDomainInterfaceStats (dom->conn, path, stats);
    else
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          _("invalid path, '%s' is not a known interface"), path);
3902

3903
cleanup:
3904 3905
    if (vm)
        virDomainObjUnlock(vm);
3906 3907
    return ret;
}
3908
#else
3909 3910 3911 3912
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path ATTRIBUTE_UNUSED,
                           struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
3913 3914 3915 3916
    qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                      "%s", __FUNCTION__);
    return -1;
}
3917
#endif
3918

3919 3920 3921 3922 3923 3924 3925
static int
qemudDomainBlockPeek (virDomainPtr dom,
                      const char *path,
                      unsigned long long offset, size_t size,
                      void *buffer,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
3926 3927 3928
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int fd = -1, ret = -1, i;
3929

3930
    qemuDriverLock(driver);
3931
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3932 3933
    qemuDriverUnlock(driver);

3934 3935
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
3936
                          "%s", _("no domain with matching uuid"));
3937
        goto cleanup;
3938 3939 3940 3941
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
3942
                         "%s", _("NULL or empty path"));
3943
        goto cleanup;
3944 3945 3946
    }

    /* Check the path belongs to this domain. */
3947 3948
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (vm->def->disks[i]->src != NULL &&
3949 3950 3951 3952
            STREQ (vm->def->disks[i]->src, path)) {
            ret = 0;
            break;
        }
3953 3954
    }

3955 3956 3957 3958 3959
    if (ret == 0) {
        ret = -1;
        /* The path is correct, now try to open it and get its size. */
        fd = open (path, O_RDONLY);
        if (fd == -1) {
3960 3961
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to open"), path);
3962 3963
            goto cleanup;
        }
3964

3965 3966 3967 3968 3969 3970
        /* Seek and read. */
        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
         * be 64 bits on all platforms.
         */
        if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
            saferead (fd, buffer, size) == (ssize_t) -1) {
3971 3972
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to seek or read"), path);
3973 3974 3975 3976 3977 3978 3979
            goto cleanup;
        }

        ret = 0;
    } else {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          "%s", _("invalid path"));
3980 3981
    }

3982 3983 3984
cleanup:
    if (fd >= 0)
        close (fd);
3985 3986
    if (vm)
        virDomainObjUnlock(vm);
3987 3988 3989
    return ret;
}

R
Richard W.M. Jones 已提交
3990 3991 3992 3993 3994 3995
static int
qemudDomainMemoryPeek (virDomainPtr dom,
                       unsigned long long offset, size_t size,
                       void *buffer,
                       unsigned int flags)
{
3996 3997 3998
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char cmd[256], *info = NULL;
R
Richard W.M. Jones 已提交
3999 4000 4001
    char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
    int fd = -1, ret = -1;

4002
    qemuDriverLock(driver);
4003
    vm = virDomainFindByID(&driver->domains, dom->id);
4004
    qemuDriverUnlock(driver);
R
Richard W.M. Jones 已提交
4005 4006 4007 4008

    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4009 4010 4011 4012 4013 4014 4015
        goto cleanup;
    }

    if (flags != VIR_MEMORY_VIRTUAL) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          "%s", _("QEMU driver only supports virtual memory addrs"));
        goto cleanup;
R
Richard W.M. Jones 已提交
4016 4017
    }

4018
    if (!virDomainIsActive(vm)) {
R
Richard W.M. Jones 已提交
4019 4020
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
4021
        goto cleanup;
R
Richard W.M. Jones 已提交
4022 4023 4024 4025
    }

    /* Create a temporary filename. */
    if ((fd = mkstemp (tmp)) == -1) {
4026 4027
        virReportSystemError (dom->conn, errno,
                              _("mkstemp(\"%s\") failed"), tmp);
4028
        goto cleanup;
R
Richard W.M. Jones 已提交
4029 4030 4031 4032
    }

    /* Issue the memsave command. */
    snprintf (cmd, sizeof cmd, "memsave %llu %zi \"%s\"", offset, size, tmp);
4033
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
R
Richard W.M. Jones 已提交
4034
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
4035
                          "%s", _("'memsave' command failed"));
4036
        goto cleanup;
R
Richard W.M. Jones 已提交
4037 4038 4039 4040 4041 4042
    }

    DEBUG ("memsave reply: %s", info);

    /* Read the memory file into buffer. */
    if (saferead (fd, buffer, size) == (ssize_t) -1) {
4043 4044 4045
        virReportSystemError (dom->conn, errno,
                              _("failed to read temporary file "
                                "created with template %s"), tmp);
4046
        goto cleanup;
R
Richard W.M. Jones 已提交
4047 4048 4049
    }

    ret = 0;
4050 4051 4052

cleanup:
    VIR_FREE(info);
R
Richard W.M. Jones 已提交
4053 4054
    if (fd >= 0) close (fd);
    unlink (tmp);
4055 4056
    if (vm)
        virDomainObjUnlock(vm);
R
Richard W.M. Jones 已提交
4057 4058 4059
    return ret;
}

4060

4061 4062
static int
qemudDomainEventRegister (virConnectPtr conn,
4063
                          virConnectDomainEventCallback callback,
4064 4065
                          void *opaque,
                          virFreeCallback freecb)
4066
{
4067 4068 4069
    struct qemud_driver *driver = conn->privateData;
    int ret;

4070
    qemuDriverLock(driver);
4071 4072
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
4073
    qemuDriverUnlock(driver);
4074

4075
    return ret;
4076 4077 4078 4079
}

static int
qemudDomainEventDeregister (virConnectPtr conn,
4080
                            virConnectDomainEventCallback callback)
4081
{
4082 4083 4084
    struct qemud_driver *driver = conn->privateData;
    int ret;

4085
    qemuDriverLock(driver);
4086 4087 4088 4089 4090 4091
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
4092
    qemuDriverUnlock(driver);
4093

4094
    return ret;
4095 4096
}

4097 4098 4099 4100 4101
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
                                        virConnectDomainEventCallback cb,
                                        void *cbopaque,
                                        void *opaque)
4102
{
4103
    struct qemud_driver *driver = opaque;
4104

4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148
    /* Drop the lock whle dispatching, for sake of re-entrancy */
    qemuDriverUnlock(driver);
    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
    qemuDriverLock(driver);
}

static void qemuDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
{
    struct qemud_driver *driver = opaque;
    virDomainEventQueue tempQueue;

    qemuDriverLock(driver);

    driver->domainEventDispatching = 1;

    /* Copy the queue, so we're reentrant safe */
    tempQueue.count = driver->domainEventQueue->count;
    tempQueue.events = driver->domainEventQueue->events;
    driver->domainEventQueue->count = 0;
    driver->domainEventQueue->events = NULL;

    virEventUpdateTimeout(driver->domainEventTimer, -1);
    virDomainEventQueueDispatch(&tempQueue,
                                driver->domainEventCallbacks,
                                qemuDomainEventDispatchFunc,
                                driver);

    /* Purge any deleted callbacks */
    virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks);

    driver->domainEventDispatching = 0;
    qemuDriverUnlock(driver);
}


/* driver must be locked before calling */
static void qemuDomainEventQueue(struct qemud_driver *driver,
                                 virDomainEventPtr event)
{
    if (virDomainEventQueuePush(driver->domainEventQueue,
                                event) < 0)
        virDomainEventFree(event);
    if (qemu_driver->domainEventQueue->count == 1)
        virEventUpdateTimeout(driver->domainEventTimer, 0);
4149 4150
}

D
Daniel Veillard 已提交
4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168
/* Migration support. */

/* Prepare is the first step, and it runs on the destination host.
 *
 * This starts an empty VM listening on a TCP port.
 */
static int
qemudDomainMigratePrepare2 (virConnectPtr dconn,
                            char **cookie ATTRIBUTE_UNUSED,
                            int *cookielen ATTRIBUTE_UNUSED,
                            const char *uri_in,
                            char **uri_out,
                            unsigned long flags ATTRIBUTE_UNUSED,
                            const char *dname,
                            unsigned long resource ATTRIBUTE_UNUSED,
                            const char *dom_xml)
{
    static int port = 0;
4169 4170
    struct qemud_driver *driver = dconn->privateData;
    virDomainDefPtr def = NULL;
D
Daniel Veillard 已提交
4171 4172 4173 4174 4175
    virDomainObjPtr vm = NULL;
    int this_port;
    char hostname [HOST_NAME_MAX+1];
    char migrateFrom [64];
    const char *p;
4176
    virDomainEventPtr event = NULL;
4177 4178 4179
    int ret = -1;;

    *uri_out = NULL;
D
Daniel Veillard 已提交
4180

4181
    qemuDriverLock(driver);
D
Daniel Veillard 已提交
4182 4183 4184
    if (!dom_xml) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          "%s", _("no domain XML passed"));
4185
        goto cleanup;
D
Daniel Veillard 已提交
4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203
    }

    /* The URI passed in may be NULL or a string "tcp://somehostname:port".
     *
     * If the URI passed in is NULL then we allocate a port number
     * from our pool of port numbers and return a URI of
     * "tcp://ourhostname:port".
     *
     * If the URI passed in is not NULL then we try to parse out the
     * port number and use that (note that the hostname is assumed
     * to be a correct hostname which refers to the target machine).
     */
    if (uri_in == NULL) {
        this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
        if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;

        /* Get hostname */
        if (gethostname (hostname, HOST_NAME_MAX+1) == -1) {
4204 4205
            virReportSystemError (dconn, errno,
                                  "%s", _("failed to determine host name"));
4206
            goto cleanup;
D
Daniel Veillard 已提交
4207 4208 4209
        }

        /* Caller frees */
4210
        if (virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) {
4211
            virReportOOMError (dconn);
4212
            goto cleanup;
D
Daniel Veillard 已提交
4213 4214 4215 4216 4217 4218 4219 4220 4221
        }
    } else {
        /* Check the URI starts with "tcp:".  We will escape the
         * URI when passing it to the qemu monitor, so bad
         * characters in hostname part don't matter.
         */
        if (!STREQLEN (uri_in, "tcp:", 6)) {
            qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG,
                  "%s", _("only tcp URIs are supported for KVM migrations"));
4222
            goto cleanup;
D
Daniel Veillard 已提交
4223 4224 4225 4226 4227 4228 4229 4230 4231
        }

        /* Get the port number. */
        p = strrchr (uri_in, ':');
        p++; /* definitely has a ':' in it, see above */
        this_port = virParseNumber (&p);
        if (this_port == -1 || p-uri_in != strlen (uri_in)) {
            qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG,
                              "%s", _("URI did not have ':port' at the end"));
4232
            goto cleanup;
D
Daniel Veillard 已提交
4233 4234 4235 4236
        }
    }

    /* Parse the domain XML. */
4237 4238
    if (!(def = virDomainDefParseString(dconn, driver->caps, dom_xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
D
Daniel Veillard 已提交
4239 4240
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to parse XML"));
4241
        goto cleanup;
D
Daniel Veillard 已提交
4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257
    }

    /* Target domain name, maybe renamed. */
    dname = dname ? dname : def->name;

#if 1
    /* Ensure the name and UUID don't already exist in an active VM */
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
#else
    /* For TESTING ONLY you can change #if 1 -> #if 0 above and use
     * this code which lets you do localhost migrations.  You must still
     * supply a fresh 'dname' but this code assigns a random UUID.
     */
    if (virUUIDGenerate (def->uuid) == -1) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
            _("could not generate random UUID"));
4258
        goto cleanup;
D
Daniel Veillard 已提交
4259 4260 4261 4262 4263 4264 4265 4266 4267
    }
#endif

    if (!vm) vm = virDomainFindByName(&driver->domains, dname);
    if (vm) {
        if (virDomainIsActive(vm)) {
            qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                              _("domain with the same name or UUID already exists as '%s'"),
                              vm->def->name);
4268
            goto cleanup;
D
Daniel Veillard 已提交
4269 4270 4271 4272 4273 4274 4275 4276
        }
    }

    if (!(vm = virDomainAssignDef(dconn,
                                  &driver->domains,
                                  def))) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to assign new VM"));
4277
        goto cleanup;
D
Daniel Veillard 已提交
4278
    }
4279
    def = NULL;
D
Daniel Veillard 已提交
4280 4281 4282 4283 4284 4285 4286 4287

    /* Domain starts inactive, even if the domain XML had an id field. */
    vm->def->id = -1;

    /* Start the QEMU daemon, with the same command-line arguments plus
     * -incoming tcp:0.0.0.0:port
     */
    snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d", this_port);
4288
    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
D
Daniel Veillard 已提交
4289 4290
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to start listening VM"));
4291
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4292
            virDomainRemoveInactive(&driver->domains, vm);
4293 4294
            vm = NULL;
        }
4295
        goto cleanup;
D
Daniel Veillard 已提交
4296
    }
4297 4298 4299 4300

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_MIGRATED);
4301
    ret = 0;
D
Daniel Veillard 已提交
4302

4303 4304 4305 4306 4307
cleanup:
    virDomainDefFree(def);
    if (ret != 0) {
        VIR_FREE(*uri_out);
    }
4308 4309
    if (vm)
        virDomainObjUnlock(vm);
4310 4311
    if (event)
        qemuDomainEventQueue(driver, event);
4312
    qemuDriverUnlock(driver);
4313
    return ret;
D
Daniel Veillard 已提交
4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325
}

/* Perform is the second step, and it runs on the source host. */
static int
qemudDomainMigratePerform (virDomainPtr dom,
                           const char *cookie ATTRIBUTE_UNUSED,
                           int cookielen ATTRIBUTE_UNUSED,
                           const char *uri,
                           unsigned long flags ATTRIBUTE_UNUSED,
                           const char *dname ATTRIBUTE_UNUSED,
                           unsigned long resource)
{
4326 4327
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4328
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4329 4330
    char *safe_uri;
    char cmd[HOST_NAME_MAX+50];
4331 4332
    char *info = NULL;
    int ret = -1;
D
Daniel Veillard 已提交
4333

4334
    qemuDriverLock(driver);
4335
    vm = virDomainFindByID(&driver->domains, dom->id);
D
Daniel Veillard 已提交
4336 4337 4338
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4339
        goto cleanup;
D
Daniel Veillard 已提交
4340 4341 4342 4343 4344
    }

    if (!virDomainIsActive(vm)) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
4345
        goto cleanup;
D
Daniel Veillard 已提交
4346 4347
    }

4348 4349 4350
    if (!(flags & VIR_MIGRATE_LIVE)) {
        /* Pause domain for non-live migration */
        snprintf(cmd, sizeof cmd, "%s", "stop");
4351
        qemudMonitorCommand (vm, cmd, &info);
4352 4353 4354
        DEBUG ("stop reply: %s", info);
        VIR_FREE(info);

4355 4356 4357 4358 4359 4360
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
        event = NULL;
4361 4362
    }

D
Daniel Veillard 已提交
4363 4364 4365
    if (resource > 0) {
        /* Issue migrate_set_speed command.  Don't worry if it fails. */
        snprintf (cmd, sizeof cmd, "migrate_set_speed %lum", resource);
4366
        qemudMonitorCommand (vm, cmd, &info);
D
Daniel Veillard 已提交
4367 4368 4369 4370 4371 4372 4373 4374

        DEBUG ("migrate_set_speed reply: %s", info);
        VIR_FREE (info);
    }

    /* Issue the migrate command. */
    safe_uri = qemudEscapeMonitorArg (uri);
    if (!safe_uri) {
4375
        virReportOOMError (dom->conn);
4376
        goto cleanup;
D
Daniel Veillard 已提交
4377 4378 4379 4380
    }
    snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri);
    VIR_FREE (safe_uri);

4381
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
D
Daniel Veillard 已提交
4382 4383
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("migrate operation failed"));
4384
        goto cleanup;
D
Daniel Veillard 已提交
4385 4386 4387 4388 4389 4390 4391 4392
    }

    DEBUG ("migrate reply: %s", info);

    /* Now check for "fail" in the output string */
    if (strstr(info, "fail") != NULL) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          _("migrate failed: %s"), info);
4393
        goto cleanup;
D
Daniel Veillard 已提交
4394 4395 4396 4397
    }

    /* Clean up the source domain. */
    qemudShutdownVMDaemon (dom->conn, driver, vm);
4398 4399 4400 4401

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
4402
    if (!vm->persistent) {
D
Daniel Veillard 已提交
4403
        virDomainRemoveInactive(&driver->domains, vm);
4404 4405
        vm = NULL;
    }
4406
    ret = 0;
D
Daniel Veillard 已提交
4407

4408 4409
cleanup:
    VIR_FREE(info);
4410 4411
    if (vm)
        virDomainObjUnlock(vm);
4412 4413
    if (event)
        qemuDomainEventQueue(driver, event);
4414
    qemuDriverUnlock(driver);
4415
    return ret;
D
Daniel Veillard 已提交
4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427
}

/* Finish is the third and final step, and it runs on the destination host. */
static virDomainPtr
qemudDomainMigrateFinish2 (virConnectPtr dconn,
                           const char *dname,
                           const char *cookie ATTRIBUTE_UNUSED,
                           int cookielen ATTRIBUTE_UNUSED,
                           const char *uri ATTRIBUTE_UNUSED,
                           unsigned long flags ATTRIBUTE_UNUSED,
                           int retcode)
{
4428 4429 4430
    struct qemud_driver *driver = dconn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
4431
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4432 4433
    char *info = NULL;

4434
    qemuDriverLock(driver);
4435
    vm = virDomainFindByName(&driver->domains, dname);
D
Daniel Veillard 已提交
4436 4437 4438
    if (!vm) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching name %s"), dname);
4439
        goto cleanup;
D
Daniel Veillard 已提交
4440 4441 4442 4443 4444 4445 4446 4447 4448
    }

    /* Did the migration go as planned?  If yes, return the domain
     * object, but if no, clean up the empty qemu process.
     */
    if (retcode == 0) {
        dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
        VIR_FREE(info);
        vm->state = VIR_DOMAIN_RUNNING;
4449 4450 4451
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
D
Daniel Veillard 已提交
4452 4453
    } else {
        qemudShutdownVMDaemon (dconn, driver, vm);
4454 4455 4456
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
4457
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4458
            virDomainRemoveInactive(&driver->domains, vm);
4459 4460
            vm = NULL;
        }
D
Daniel Veillard 已提交
4461
    }
4462 4463

cleanup:
4464 4465
    if (vm)
        virDomainObjUnlock(vm);
4466 4467
    if (event)
        qemuDomainEventQueue(driver, event);
4468
    qemuDriverUnlock(driver);
4469
    return dom;
D
Daniel Veillard 已提交
4470 4471
}

4472 4473 4474 4475 4476
static virDriver qemuDriver = {
    VIR_DRV_QEMU,
    "QEMU",
    qemudOpen, /* open */
    qemudClose, /* close */
D
Daniel Veillard 已提交
4477
    qemudSupportsFeature, /* supports_feature */
4478 4479
    qemudGetType, /* type */
    qemudGetVersion, /* version */
4480
    qemudGetHostname, /* hostname */
4481
    NULL, /* URI  */
4482 4483 4484 4485 4486
    qemudGetMaxVCPUs, /* getMaxVcpus */
    qemudGetNodeInfo, /* nodeGetInfo */
    qemudGetCapabilities, /* getCapabilities */
    qemudListDomains, /* listDomains */
    qemudNumDomains, /* numOfDomains */
4487
    qemudDomainCreate, /* domainCreateXML */
4488 4489 4490 4491 4492
    qemudDomainLookupByID, /* domainLookupByID */
    qemudDomainLookupByUUID, /* domainLookupByUUID */
    qemudDomainLookupByName, /* domainLookupByName */
    qemudDomainSuspend, /* domainSuspend */
    qemudDomainResume, /* domainResume */
4493
    qemudDomainShutdown, /* domainShutdown */
4494 4495 4496
    NULL, /* domainReboot */
    qemudDomainDestroy, /* domainDestroy */
    qemudDomainGetOSType, /* domainGetOSType */
4497 4498 4499
    qemudDomainGetMaxMemory, /* domainGetMaxMemory */
    qemudDomainSetMaxMemory, /* domainSetMaxMemory */
    qemudDomainSetMemory, /* domainSetMemory */
4500 4501 4502 4503
    qemudDomainGetInfo, /* domainGetInfo */
    qemudDomainSave, /* domainSave */
    qemudDomainRestore, /* domainRestore */
    NULL, /* domainCoreDump */
4504
    qemudDomainSetVcpus, /* domainSetVcpus */
4505 4506 4507 4508
#if HAVE_SCHED_GETAFFINITY
    qemudDomainPinVcpu, /* domainPinVcpu */
    qemudDomainGetVcpus, /* domainGetVcpus */
#else
4509 4510
    NULL, /* domainPinVcpu */
    NULL, /* domainGetVcpus */
4511
#endif
4512
    qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
4513 4514 4515 4516 4517 4518
    qemudDomainDumpXML, /* domainDumpXML */
    qemudListDefinedDomains, /* listDomains */
    qemudNumDefinedDomains, /* numOfDomains */
    qemudDomainStart, /* domainCreate */
    qemudDomainDefine, /* domainDefineXML */
    qemudDomainUndefine, /* domainUndefine */
4519
    qemudDomainAttachDevice, /* domainAttachDevice */
4520
    qemudDomainDetachDevice, /* domainDetachDevice */
4521 4522 4523 4524 4525
    qemudDomainGetAutostart, /* domainGetAutostart */
    qemudDomainSetAutostart, /* domainSetAutostart */
    NULL, /* domainGetSchedulerType */
    NULL, /* domainGetSchedulerParameters */
    NULL, /* domainSetSchedulerParameters */
D
Daniel Veillard 已提交
4526 4527
    NULL, /* domainMigratePrepare (v1) */
    qemudDomainMigratePerform, /* domainMigratePerform */
4528
    NULL, /* domainMigrateFinish */
4529
    qemudDomainBlockStats, /* domainBlockStats */
4530
    qemudDomainInterfaceStats, /* domainInterfaceStats */
4531
    qemudDomainBlockPeek, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
4532
    qemudDomainMemoryPeek, /* domainMemoryPeek */
4533 4534 4535 4536
#if HAVE_NUMACTL
    qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    qemudNodeGetFreeMemory,  /* getFreeMemory */
#else
4537
    NULL, /* nodeGetCellsFreeMemory */
4538
    NULL, /* getFreeMemory */
4539
#endif
4540 4541
    qemudDomainEventRegister, /* domainEventRegister */
    qemudDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
4542 4543
    qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
    qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
4544 4545 4546
};


4547
static virStateDriver qemuStateDriver = {
4548 4549 4550 4551
    .initialize = qemudStartup,
    .cleanup = qemudShutdown,
    .reload = qemudReload,
    .active = qemudActive,
4552
};
4553

4554
int qemuRegister(void) {
4555 4556 4557 4558
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}