qemu_driver.c 153.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
#include "node_device_conf.h"
#include "pci.h"
73 74
#include "security.h"

75

76 77
#define VIR_FROM_THIS VIR_FROM_QEMU

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

81 82 83 84
#define QEMU_CMD_PROMPT "\n(qemu) "
#define QEMU_PASSWD_PROMPT "Password: "


85 86
static int qemudShutdown(void);

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

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

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

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

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

115
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
116

117 118 119 120 121 122 123 124
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);
125 126 127
static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
                                       virDomainObjPtr vm,
                                       unsigned long newmem);
128

J
Jim Meyering 已提交
129
static struct qemud_driver *qemu_driver = NULL;
130 131


132 133 134 135 136 137
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 已提交
138
    int ret, fd = -1;
139

G
Guido Günther 已提交
140 141
    if ((ret = snprintf(logfile, sizeof(logfile), "%s/%s.log", logDir, name))
        < 0 || ret >= sizeof(logfile)) {
142
        virReportOOMError(conn);
143 144 145 146 147 148 149 150 151
        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) {
152 153 154
        virReportSystemError(conn, errno,
                             _("failed to create logfile %s"),
                             logfile);
155 156
        return -1;
    }
157
    if (virSetCloseExec(fd) < 0) {
158 159
        virReportSystemError(conn, errno, "%s",
                             _("Unable to set VM logfile close-on-exec flag"));
160 161 162 163 164 165 166
        close(fd);
        return -1;
    }
    return fd;
}


167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
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) {
184 185 186
        virReportSystemError(conn, errno,
                             _("failed to create logfile %s"),
                             logfile);
187 188
        return -1;
    }
189
    if (virSetCloseExec(fd) < 0) {
190 191
        virReportSystemError(conn, errno, "%s",
                             _("Unable to set VM logfile close-on-exec flag"));
192 193 194 195
        close(fd);
        return -1;
    }
    if (lseek(fd, pos, SEEK_SET) < 0) {
196 197 198
        virReportSystemError(conn, errno,
                             _("Unable to seek to %lld in %s"),
                             (long long) pos, logfile);
199 200 201 202 203 204
        close(fd);
    }
    return fd;
}


205 206 207
static void
qemudAutostartConfigs(struct qemud_driver *driver) {
    unsigned int i;
208 209 210 211 212 213 214 215 216
    /* 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 */
217 218

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

241 242
    if (conn)
        virConnectClose(conn);
243 244
}

245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261

/**
 * 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) {
262
        virReportOOMError(conn);
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
        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;
}


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 307 308 309 310 311 312
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) {
313 314
            VIR_ERROR(_("Failed to read domain status for %s\n"),
                      vm->def->name);
315 316 317 318 319 320 321 322
            goto next_error;
        }

        status = qemudDomainStatusParseFile(NULL, driver->caps, config, 0);
        if (status) {
            vm->newDef = vm->def;
            vm->def = status->def;
        } else {
323 324
            VIR_ERROR(_("Failed to parse domain status for %s\n"),
                      vm->def->name);
325 326 327 328
            goto next_error;
        }

        if ((rc = qemudOpenMonitor(NULL, driver, vm, status->monitorpath, 1)) != 0) {
329 330
            VIR_ERROR(_("Failed to reconnect monitor for %s: %d\n"),
                      vm->def->name, rc);
331
            goto next_error;
332
        }
333

334
        if ((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0)
335
            goto next_error;
336 337 338 339 340 341 342 343 344 345 346

        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);
347 348 349 350 351 352
        /* Restore orignal def, if we'd loaded a live one */
        if (vm->newDef) {
            virDomainDefFree(vm->def);
            vm->def = vm->newDef;
            vm->newDef = NULL;
        }
353 354
next:
        virDomainObjUnlock(vm);
355 356
        if (status)
            VIR_FREE(status->monitorpath);
357 358 359 360 361 362
        VIR_FREE(status);
        VIR_FREE(config);
    }
    return 0;
}

363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
static int
qemudSecurityInit(struct qemud_driver *qemud_drv)
{
    int ret;
    const char *doi, *model;
    virCapsPtr caps;
    virSecurityDriverPtr security_drv;

    ret = virSecurityDriverStartup(&security_drv,
                                   qemud_drv->securityDriverName);
    if (ret == -1) {
        VIR_ERROR0(_("Failed to start security driver"));
        return -1;
    }
    /* No security driver wanted to be enabled: just return */
    if (ret == -2) {
        VIR_INFO0(_("No security driver available"));
        return 0;
    }

    qemud_drv->securityDriver = security_drv;
    doi = virSecurityDriverGetDOI(security_drv);
    model = virSecurityDriverGetModel(security_drv);

    VIR_DEBUG("Initialized security driver \"%s\" with "
              "DOI \"%s\"", model, doi);

    /*
     * Add security policy host caps now that the security driver is
     * initialized.
     */
    caps = qemud_drv->caps;

    caps->host.secModel.model = strdup(model);
    if (!caps->host.secModel.model) {
        char ebuf[1024];
        VIR_ERROR(_("Failed to copy secModel model: %s"),
                  virStrerror(errno, ebuf, sizeof ebuf));
        return -1;
    }

    caps->host.secModel.doi = strdup(doi);
    if (!caps->host.secModel.doi) {
        char ebuf[1024];
        VIR_ERROR(_("Failed to copy secModel DOI: %s"),
                  virStrerror(errno, ebuf, sizeof ebuf));
        return -1;
    }

    return 0;
}
414

415 416 417 418 419 420 421
/**
 * qemudStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
qemudStartup(void) {
422 423
    uid_t uid = geteuid();
    char *base = NULL;
D
Daniel P. Berrange 已提交
424
    char driverConf[PATH_MAX];
425

426
    if (VIR_ALLOC(qemu_driver) < 0)
427 428
        return -1;

429
    if (virMutexInit(&qemu_driver->lock) < 0) {
430
        VIR_ERROR("%s", _("cannot initialize mutex"));
431 432 433
        VIR_FREE(qemu_driver);
        return -1;
    }
434 435
    qemuDriverLock(qemu_driver);

436 437 438
    /* Don't have a dom0 so start from 1 */
    qemu_driver->nextvmid = 1;

439 440
    /* Init callback list */
    if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
441
        goto out_of_memory;
442 443 444 445 446 447
    if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew()))
        goto out_of_memory;

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

449
    if (!uid) {
450 451
        if (virAsprintf(&qemu_driver->logDir,
                        "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
452
            goto out_of_memory;
453

D
Daniel P. Berrange 已提交
454
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
455
            goto out_of_memory;
456 457 458 459

        if (virAsprintf(&qemu_driver->stateDir,
                      "%s/run/libvirt/qemu/", LOCAL_STATE_DIR) == -1)
            goto out_of_memory;
460
    } else {
461 462
        char *userdir = virGetUserDirectory(NULL, uid);
        if (!userdir)
463
            goto error;
464

465
        if (virAsprintf(&qemu_driver->logDir,
466 467
                        "%s/.libvirt/qemu/log", userdir) == -1) {
            VIR_FREE(userdir);
468
            goto out_of_memory;
469
        }
470

471 472
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
            VIR_FREE(userdir);
473
            goto out_of_memory;
474 475
        }
        VIR_FREE(userdir);
476 477 478 479 480 481

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

    if (virFileMakePath(qemu_driver->stateDir) < 0) {
482
        char ebuf[1024];
483 484
        VIR_ERROR(_("Failed to create state dir '%s': %s\n"),
                  qemu_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
485
        goto error;
486 487 488 489 490
    }

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

495
    if (virAsprintf(&qemu_driver->configDir, "%s/qemu", base) == -1)
496 497
        goto out_of_memory;

498
    if (virAsprintf(&qemu_driver->autostartDir, "%s/qemu/autostart", base) == -1)
499 500
        goto out_of_memory;

501
    VIR_FREE(base);
502 503 504

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

506
    if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
507 508 509
        goto error;
    }

510
    if (qemudSecurityInit(qemu_driver) < 0) {
511
        goto error;
D
Daniel P. Berrange 已提交
512 513
    }

514 515 516 517
    if (virDomainLoadAllConfigs(NULL,
                                qemu_driver->caps,
                                &qemu_driver->domains,
                                qemu_driver->configDir,
518
                                qemu_driver->autostartDir,
519 520
                                NULL, NULL) < 0)
        goto error;
521
    qemudReconnectVMs(qemu_driver);
522 523
    qemudAutostartConfigs(qemu_driver);

524 525
    qemuDriverUnlock(qemu_driver);

526 527
    return 0;

528
out_of_memory:
529
    virReportOOMError(NULL);
530 531 532
error:
    if (qemu_driver)
        qemuDriverUnlock(qemu_driver);
533
    VIR_FREE(base);
534
    qemudShutdown();
535 536 537
    return -1;
}

538 539 540 541
static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
{
    struct qemud_driver *driver = opaque;

542 543 544 545 546 547 548 549
    if (newVM) {
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }
550 551
}

552 553 554 555 556 557 558 559
/**
 * qemudReload:
 *
 * Function to restart the QEmu daemon, it will recheck the configuration
 * files and update its state and the networking
 */
static int
qemudReload(void) {
560 561 562
    if (!qemu_driver)
        return 0;

563
    qemuDriverLock(qemu_driver);
564 565 566 567
    virDomainLoadAllConfigs(NULL,
                            qemu_driver->caps,
                            &qemu_driver->domains,
                            qemu_driver->configDir,
568 569
                            qemu_driver->autostartDir,
                            qemudNotifyLoadDomain, qemu_driver);
570

571
    qemudAutostartConfigs(qemu_driver);
572
    qemuDriverUnlock(qemu_driver);
573 574

    return 0;
575 576
}

577 578 579 580 581 582 583 584 585 586
/**
 * 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) {
587
    unsigned int i;
588
    int active = 0;
589

590 591 592
    if (!qemu_driver)
        return 0;

593 594 595 596 597 598 599 600
    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);
    }
601

602 603
    qemuDriverUnlock(qemu_driver);
    return active;
604 605
}

606 607 608 609 610 611 612
/**
 * qemudShutdown:
 *
 * Shutdown the QEmu daemon, it will stop all active domains and networks
 */
static int
qemudShutdown(void) {
613

614
    if (!qemu_driver)
615
        return -1;
616

617
    qemuDriverLock(qemu_driver);
618 619
    virCapabilitiesFree(qemu_driver->caps);

620
    virDomainObjListFree(&qemu_driver->domains);
621

622
    VIR_FREE(qemu_driver->securityDriverName);
623
    VIR_FREE(qemu_driver->logDir);
624 625
    VIR_FREE(qemu_driver->configDir);
    VIR_FREE(qemu_driver->autostartDir);
626
    VIR_FREE(qemu_driver->stateDir);
627
    VIR_FREE(qemu_driver->vncTLSx509certdir);
J
Jim Meyering 已提交
628
    VIR_FREE(qemu_driver->vncListen);
629
    VIR_FREE(qemu_driver->vncPassword);
630
    VIR_FREE(qemu_driver->vncSASLdir);
D
Daniel P. Berrange 已提交
631

632 633
    /* Free domain callback list */
    virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
634 635 636 637
    virDomainEventQueueFree(qemu_driver->domainEventQueue);

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

639 640 641
    if (qemu_driver->brctl)
        brShutdown(qemu_driver->brctl);

642
    qemuDriverUnlock(qemu_driver);
643
    virMutexDestroy(&qemu_driver->lock);
644
    VIR_FREE(qemu_driver);
645 646

    return 0;
647 648 649
}

/* Return -1 for error, 1 to continue reading and 0 for success */
650
typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
651
                                      virDomainObjPtr vm,
652 653 654
                                      const char *output,
                                      int fd);

655 656 657
/*
 * Returns -1 for error, 0 on end-of-file, 1 for success
 */
658
static int
659
qemudReadMonitorOutput(virConnectPtr conn,
660
                       virDomainObjPtr vm,
661 662
                       int fd,
                       char *buf,
G
Guido Günther 已提交
663
                       size_t buflen,
664
                       qemudHandlerMonitorOutput func,
665 666
                       const char *what,
                       int timeout)
667
{
G
Guido Günther 已提交
668
    size_t got = 0;
669
    buf[0] = '\0';
670
    timeout *= 1000; /* poll wants milli seconds */
671

672
    /* Consume & discard the initial greeting */
673
    while (got < (buflen-1)) {
G
Guido Günther 已提交
674
        ssize_t ret;
675 676

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

678 679 680 681 682 683
        if (ret < 0) {
            struct pollfd pfd = { .fd = fd, .events = POLLIN };
            if (errno == EINTR)
                continue;

            if (errno != EAGAIN) {
684 685 686
                virReportSystemError(conn, errno,
                                     _("Failure while reading %s startup output"),
                                     what);
687 688 689
                return -1;
            }

690
            ret = poll(&pfd, 1, timeout);
691
            if (ret == 0) {
692
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
693
                                 _("Timed out while reading %s startup output"), what);
694 695 696
                return -1;
            } else if (ret == -1) {
                if (errno != EINTR) {
697 698 699
                    virReportSystemError(conn, errno,
                                         _("Failure while reading %s startup output"),
                                         what);
700 701 702 703 704 705 706 707
                    return -1;
                }
            } else {
                /* Make sure we continue loop & read any further data
                   available before dealing with EOF */
                if (pfd.revents & (POLLIN | POLLHUP))
                    continue;

708
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
709
                                 _("Failure while reading %s startup output"), what);
710 711
                return -1;
            }
712 713
        } else if (ret == 0) {
            return 0;
714 715 716
        } else {
            got += ret;
            buf[got] = '\0';
717 718 719 720 721 722
            ret = func(conn, vm, buf, fd);
            if (ret == -1)
                return -1;
            if (ret == 1)
                continue;
            return 1;
723 724 725
        }
    }

726
    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
727
                     _("Out of space while reading %s startup output"), what);
728 729 730 731
    return -1;

}

732 733 734 735 736 737 738 739 740

/*
 * Returns -1 for error, 0 on success
 */
static int
qemudReadLogOutput(virConnectPtr conn,
                   virDomainObjPtr vm,
                   int fd,
                   char *buf,
G
Guido Günther 已提交
741
                   size_t buflen,
742 743 744 745 746 747 748 749
                   qemudHandlerMonitorOutput func,
                   const char *what,
                   int timeout)
{
    int retries = timeout*10;
    buf[0] = '\0';

    while (retries) {
G
Guido Günther 已提交
750 751 752
        ssize_t ret;
        size_t got = 0;

753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
        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;
}

783
static int
784
qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
785
                        virDomainObjPtr vm,
786 787 788 789 790 791 792 793 794 795 796
                        const char *output,
                        int fd)
{
    if (strstr(output, "(qemu) ") == NULL)
        return 1; /* keep reading */

    vm->monitor = fd;

    return 0;
}

797
static int qemudOpenMonitor(virConnectPtr conn,
798
                            struct qemud_driver* driver,
799
                            virDomainObjPtr vm,
800 801
                            const char *monitor,
                            int reconnect) {
802 803 804 805
    int monfd;
    char buf[1024];
    int ret = -1;

D
Daniel Veillard 已提交
806
    if ((monfd = open(monitor, O_RDWR)) < 0) {
807
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
808
                         _("Unable to open monitor path %s"), monitor);
809 810
        return -1;
    }
811
    if (virSetCloseExec(monfd) < 0) {
812
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
813
                         "%s", _("Unable to set monitor close-on-exec flag"));
814 815
        goto error;
    }
816
    if (virSetNonBlock(monfd) < 0) {
817
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
818
                         "%s", _("Unable to put monitor into non-blocking mode"));
819 820 821
        goto error;
    }

822
    if (!reconnect) {
823 824 825 826
        if (qemudReadMonitorOutput(conn,
                                   vm, monfd,
                                   buf, sizeof(buf),
                                   qemudCheckMonitorPrompt,
827
                                   "monitor", 10) <= 0)
828 829 830
            ret = -1;
        else
            ret = 0;
831 832 833 834 835 836 837
    } else {
        vm->monitor = monfd;
        ret = 0;
    }

    if (ret != 0)
         goto error;
838

839
    if (!(vm->monitorpath = strdup(monitor))) {
840
        virReportOOMError(conn);
841 842 843
        goto error;
    }

844 845 846
    if ((vm->monitorWatch = virEventAddHandle(vm->monitor, 0,
                                              qemudDispatchVMEvent,
                                              driver, NULL)) < 0)
847 848 849
        goto error;


850 851 852 853
    /* Keep monitor open upon success */
    if (ret == 0)
        return ret;

854 855 856 857 858
 error:
    close(monfd);
    return ret;
}

859
/* Returns -1 for error, 0 success, 1 continue reading */
860 861
static int qemudExtractMonitorPath(virConnectPtr conn,
                                   const char *haystack,
862
                                   size_t *offset,
863
                                   char **path) {
864
    static const char needle[] = "char device redirected to";
865
    char *tmp, *dev;
866

867
    VIR_FREE(*path);
868
    /* First look for our magic string */
869 870 871 872 873
    if (!(tmp = strstr(haystack + *offset, needle))) {
        return 1;
    }
    tmp += sizeof(needle);
    dev = tmp;
874

875 876 877 878 879
    /*
     * And look for first whitespace character and nul terminate
     * to mark end of the pty path
     */
    while (*tmp) {
880
        if (c_isspace(*tmp)) {
881
            if (VIR_ALLOC_N(*path, (tmp-dev)+1) < 0) {
882
                virReportOOMError(conn);
883 884 885 886
                return -1;
            }
            strncpy(*path, dev, (tmp-dev));
            (*path)[(tmp-dev)] = '\0';
887
            /* ... now further update offset till we get EOL */
888
            *offset = tmp - haystack;
889 890
            return 0;
        }
891
        tmp++;
892 893 894 895 896
    }

    /*
     * We found a path, but didn't find any whitespace,
     * so it must be still incomplete - we should at
897 898
     * least see a \n - indicate that we want to carry
     * on trying again
899
     */
900
    return 1;
901 902 903
}

static int
904
qemudFindCharDevicePTYs(virConnectPtr conn,
905
                        virDomainObjPtr vm,
906 907
                        const char *output,
                        int fd ATTRIBUTE_UNUSED)
908
{
909
    struct qemud_driver* driver = conn->privateData;
910
    char *monitor = NULL;
911
    size_t offset = 0;
912
    int ret, i;
913 914 915 916 917

    /* 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.... */
918

919
    /* So first comes the monitor device */
920 921
    if ((ret = qemudExtractMonitorPath(conn, output, &offset, &monitor)) != 0)
        goto cleanup;
922

923
    /* then the serial devices */
924 925
    for (i = 0 ; i < vm->def->nserials ; i++) {
        virDomainChrDefPtr chr = vm->def->serials[i];
926 927 928 929
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
930 931 932 933
        }
    }

    /* and finally the parallel devices */
934 935
    for (i = 0 ; i < vm->def->nparallels ; i++) {
        virDomainChrDefPtr chr = vm->def->parallels[i];
936 937 938 939
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
940 941 942 943
        }
    }

    /* Got them all, so now open the monitor console */
944
    ret = qemudOpenMonitor(conn, driver, vm, monitor, 0);
945 946 947 948

cleanup:
    VIR_FREE(monitor);
    return ret;
949 950
}

951
static int qemudWaitForMonitor(virConnectPtr conn,
952 953 954
                               struct qemud_driver* driver,
                               virDomainObjPtr vm, off_t pos)
{
955
    char buf[1024]; /* Plenty of space to get startup greeting */
956 957 958 959 960
    int logfd;
    int ret;

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

963 964 965
    ret = qemudReadLogOutput(conn, vm, logfd, buf, sizeof(buf),
                             qemudFindCharDevicePTYs,
                             "console", 3);
966 967
    if (close(logfd) < 0) {
        char ebuf[1024];
968
        VIR_WARN(_("Unable to close logfile: %s\n"),
969 970
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
971

972
    if (ret == 0) /* success */
973 974 975 976 977 978
        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;
979 980
}

981 982
static int
qemudDetectVcpuPIDs(virConnectPtr conn,
983
                    virDomainObjPtr vm) {
984 985 986 987 988 989
    char *qemucpus = NULL;
    char *line;
    int lastVcpu = -1;

    /* Only KVM has seperate threads for CPUs,
       others just use main QEMU process for CPU */
990
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM)
991 992 993 994 995
        vm->nvcpupids = 1;
    else
        vm->nvcpupids = vm->def->vcpus;

    if (VIR_ALLOC_N(vm->vcpupids, vm->nvcpupids) < 0) {
996
        virReportOOMError(conn);
997 998 999
        return -1;
    }

1000
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
1001 1002 1003 1004
        vm->vcpupids[0] = vm->pid;
        return 0;
    }

1005
    if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) {
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
        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;

1064
    VIR_FREE(qemucpus);
1065 1066 1067 1068
    return 0;

error:
    VIR_FREE(vm->vcpupids);
1069 1070
    vm->nvcpupids = 0;
    VIR_FREE(qemucpus);
1071 1072 1073 1074 1075 1076 1077 1078

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

1079 1080
static int
qemudInitCpus(virConnectPtr conn,
D
Daniel Veillard 已提交
1081 1082
              virDomainObjPtr vm,
              const char *migrateFrom) {
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
    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 已提交
1098 1099 1100 1101 1102 1103
    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++)
1104
            CPU_SET(i, &mask);
D
Daniel P. Berrange 已提交
1105
    }
1106 1107 1108 1109

    for (i = 0 ; i < vm->nvcpupids ; i++) {
        if (sched_setaffinity(vm->vcpupids[i],
                              sizeof(mask), &mask) < 0) {
1110 1111
            virReportSystemError(conn, errno, "%s",
                                 _("failed to set CPU affinity"));
1112 1113 1114 1115 1116
            return -1;
        }
    }
#endif /* HAVE_SCHED_GETAFFINITY */

D
Daniel Veillard 已提交
1117 1118
    if (migrateFrom == NULL) {
        /* Allow the CPUS to start executing */
1119
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
D
Daniel Veillard 已提交
1120 1121 1122 1123 1124
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("resume operation failed"));
            return -1;
        }
        VIR_FREE(info);
1125 1126 1127 1128 1129 1130
    }

    return 0;
}


1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
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 &&
1145
        (vm->def->graphics->data.vnc.passwd || driver->vncPassword)) {
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163

        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;
}


1164
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
    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;
}

1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
static int qemuPrepareHostDevices(virConnectPtr conn,
                                  virDomainDefPtr def) {
    int i;

    /* We have to use 2 loops here. *All* devices must
     * be detached before we reset any of them, because
     * in some cases you have to reset the whole PCI,
     * which impacts all devices on it
     */

    for (i = 0 ; i < def->nhostdevs ; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

        if (!hostdev->managed) {
            pciDevice *dev = pciGetDevice(conn,
                                          hostdev->source.subsys.u.pci.domain,
                                          hostdev->source.subsys.u.pci.bus,
                                          hostdev->source.subsys.u.pci.slot,
                                          hostdev->source.subsys.u.pci.function);
            if (!dev)
                goto error;

            if (pciDettachDevice(conn, dev) < 0) {
                pciFreeDevice(conn, dev);
                goto error;
            }

            pciFreeDevice(conn, dev);
        } /* else {
             XXX validate that non-managed device isn't in use, eg
             by checking that device is either un-bound, or bound
             to pci-stub.ko
        } */
    }

    /* Now that all the PCI hostdevs have be dettached, we can safely
     * reset them */
    for (i = 0 ; i < def->nhostdevs ; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];
        pciDevice *dev;

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

        dev = pciGetDevice(conn,
                           hostdev->source.subsys.u.pci.domain,
                           hostdev->source.subsys.u.pci.bus,
                           hostdev->source.subsys.u.pci.slot,
                           hostdev->source.subsys.u.pci.function);
        if (!dev)
            goto error;

        if (pciResetDevice(conn, dev) < 0) {
            pciFreeDevice(conn, dev);
            goto error;
        }

        pciFreeDevice(conn, dev);
    }

    return 0;

error:
    return -1;
}

1273 1274 1275 1276 1277 1278 1279 1280 1281
static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
{
    if (vm->def->seclabel.label != NULL)
        if (driver->securityDriver && driver->securityDriver->domainSetSecurityLabel)
            return driver->securityDriver->domainSetSecurityLabel(conn, driver->securityDriver,
                                                                 vm);
    return 0;
}

1282 1283 1284
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
                                            const char *name);

1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
struct gemudHookData {
        virConnectPtr conn;
        virDomainObjPtr vm;
        struct qemud_driver *driver;
};

static int qemudSecurityHook(void *data) {
        struct gemudHookData *h = (struct gemudHookData *) data;

        if (qemudDomainSetSecurityLabel(h->conn, h->driver, h->vm) < 0) {
                qemudReportError(h->conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 _("Failed to set security label"));
                return -1;
        }
        return 0;
}

1302 1303
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
1304
                              virDomainObjPtr vm,
1305 1306
                              const char *migrateFrom,
                              int stdin_fd) {
1307
    const char **argv = NULL, **tmp;
1308
    const char **progenv = NULL;
1309
    int i, ret;
1310
    struct stat sb;
1311 1312
    int *tapfds = NULL;
    int ntapfds = 0;
1313
    unsigned int qemuCmdFlags;
1314
    fd_set keepfd;
1315
    const char *emulator;
G
Guido Günther 已提交
1316
    pid_t child;
1317
    int pos = -1;
1318
    char ebuf[1024];
1319

1320 1321 1322 1323 1324
    struct gemudHookData hookData;
    hookData.conn = conn;
    hookData.vm = vm;
    hookData.driver = driver;

1325
    FD_ZERO(&keepfd);
1326

1327
    if (virDomainIsActive(vm)) {
1328
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
1329
                         "%s", _("VM is already active"));
1330 1331 1332
        return -1;
    }

1333 1334 1335 1336 1337 1338 1339 1340
    /* If you are using a SecurityDriver with dynamic labelling,
       then generate a security label for isolation */
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
        driver->securityDriver &&
        driver->securityDriver->domainGenSecurityLabel &&
        driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
        return -1;

1341 1342 1343
    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics->data.vnc.autoport) {
1344
        int port = qemudNextFreeVNCPort(driver);
1345
        if (port < 0) {
1346
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
1347
                             "%s", _("Unable to find an unused VNC port"));
1348
            goto cleanup;
1349
        }
1350 1351
        vm->def->graphics->data.vnc.port = port;
    }
1352

1353
    if (virFileMakePath(driver->logDir) < 0) {
1354 1355 1356
        virReportSystemError(conn, errno,
                             _("cannot create log directory %s"),
                             driver->logDir);
1357
        goto cleanup;
1358 1359
    }

1360
    if((vm->logfile = qemudLogFD(conn, driver->logDir, vm->def->name)) < 0)
1361
        goto cleanup;
1362

1363 1364 1365 1366
    emulator = vm->def->emulator;
    if (!emulator)
        emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
    if (!emulator)
1367
        goto cleanup;
1368

1369 1370 1371 1372
    /* 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
     */
1373
    if (stat(emulator, &sb) < 0) {
1374 1375 1376
        virReportSystemError(conn, errno,
                             _("Cannot find QEMU binary %s"),
                             emulator);
1377
        goto cleanup;
1378 1379
    }

1380
    if (qemudExtractVersionInfo(emulator,
1381 1382 1383 1384
                                NULL,
                                &qemuCmdFlags) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Cannot determine QEMU argv syntax %s"),
1385
                         emulator);
1386
        goto cleanup;
1387
    }
1388

1389
    if (qemuPrepareHostDevices(conn, vm->def) < 0)
1390
        goto cleanup;
1391

1392
    vm->def->id = driver->nextvmid++;
1393
    if (qemudBuildCommandLine(conn, driver, vm,
1394
                              qemuCmdFlags, &argv, &progenv,
1395 1396
                              &tapfds, &ntapfds, migrateFrom) < 0)
        goto cleanup;
1397

1398 1399 1400
    tmp = progenv;
    while (*tmp) {
        if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
1401
            VIR_WARN(_("Unable to write envv to logfile: %s\n"),
1402
                     virStrerror(errno, ebuf, sizeof ebuf));
1403
        if (safewrite(vm->logfile, " ", 1) < 0)
1404
            VIR_WARN(_("Unable to write envv to logfile: %s\n"),
1405
                     virStrerror(errno, ebuf, sizeof ebuf));
1406 1407
        tmp++;
    }
1408 1409
    tmp = argv;
    while (*tmp) {
1410
        if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
1411
            VIR_WARN(_("Unable to write argv to logfile: %s\n"),
1412
                     virStrerror(errno, ebuf, sizeof ebuf));
1413
        if (safewrite(vm->logfile, " ", 1) < 0)
1414
            VIR_WARN(_("Unable to write argv to logfile: %s\n"),
1415
                     virStrerror(errno, ebuf, sizeof ebuf));
1416 1417
        tmp++;
    }
1418
    if (safewrite(vm->logfile, "\n", 1) < 0)
1419
        VIR_WARN(_("Unable to write argv to logfile: %s\n"),
1420
                 virStrerror(errno, ebuf, sizeof ebuf));
1421

1422
    if ((pos = lseek(vm->logfile, 0, SEEK_END)) < 0)
1423
        VIR_WARN(_("Unable to seek to end of logfile: %s\n"),
1424
                 virStrerror(errno, ebuf, sizeof ebuf));
1425

1426 1427 1428
    for (i = 0 ; i < ntapfds ; i++)
        FD_SET(tapfds[i], &keepfd);

1429 1430 1431 1432
    ret = virExecWithHook(conn, argv, progenv, &keepfd, &child,
                          stdin_fd, &vm->logfile, &vm->logfile,
                          VIR_EXEC_NONBLOCK | VIR_EXEC_DAEMON,
                          qemudSecurityHook, &hookData);
G
Guido Günther 已提交
1433 1434 1435 1436

    /* wait for qemu process to to show up */
    if (ret == 0) {
        int retries = 100;
1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
        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--;
            }
1449 1450 1451 1452 1453
            if (ret) {
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                                 _("Domain %s didn't show up\n"), vm->def->name);
                ret = -1;
            }
1454 1455
        } else {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1456
                             "%s", _("Unable to daemonize QEMU process"));
1457
            ret = -1;
G
Guido Günther 已提交
1458
        }
1459
        vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
1460
    }
1461

1462
    for (i = 0 ; argv[i] ; i++)
1463 1464
        VIR_FREE(argv[i]);
    VIR_FREE(argv);
1465

1466 1467 1468 1469
    for (i = 0 ; progenv[i] ; i++)
        VIR_FREE(progenv[i]);
    VIR_FREE(progenv);

1470 1471 1472
    if (tapfds) {
        for (i = 0 ; i < ntapfds ; i++) {
            close(tapfds[i]);
1473
        }
1474
        VIR_FREE(tapfds);
1475 1476
    }

1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
    if (ret == -1)
        goto cleanup;

    if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
        (qemudDetectVcpuPIDs(conn, vm) < 0) ||
        (qemudInitCpus(conn, vm, migrateFrom) < 0) ||
        (qemudInitPasswords(conn, driver, vm) < 0) ||
        (qemudDomainSetMemoryBalloon(conn, vm, vm->def->memory) < 0) ||
        (qemudSaveDomainStatus(conn, qemu_driver, vm) < 0)) {
        qemudShutdownVMDaemon(conn, driver, vm);
        ret = -1;
        /* No need for 'goto cleanup' now since qemudShutdownVMDaemon does enough */
1489 1490
    }

1491
    return ret;
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508

cleanup:
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
        VIR_FREE(vm->def->seclabel.model);
        VIR_FREE(vm->def->seclabel.label);
        VIR_FREE(vm->def->seclabel.imagelabel);
    }
    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics->data.vnc.autoport)
        vm->def->graphics->data.vnc.port = -1;
    if (vm->logfile != -1) {
        close(vm->logfile);
        vm->logfile = -1;
    }
    vm->def->id = -1;
    return -1;
1509 1510 1511
}


1512
static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
1513 1514
                                  struct qemud_driver *driver,
                                  virDomainObjPtr vm) {
1515
    if (!virDomainIsActive(vm))
1516
        return;
1517

1518
    VIR_DEBUG(_("Shutting down VM '%s'\n"), vm->def->name);
1519

G
Guido Günther 已提交
1520 1521
    if (virKillProcess(vm->pid, 0) == 0 &&
        virKillProcess(vm->pid, SIGTERM) < 0)
1522 1523 1524
        virReportSystemError(conn, errno,
                             _("Failed to send SIGTERM to %s (%d)"),
                             vm->def->name, vm->pid);
1525

1526 1527 1528
    if (vm->monitorWatch != -1) {
        virEventRemoveHandle(vm->monitorWatch);
        vm->monitorWatch = -1;
1529
    }
1530

1531 1532
    if (close(vm->logfile) < 0) {
        char ebuf[1024];
1533
        VIR_WARN(_("Unable to close logfile: %s\n"),
1534 1535
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1536 1537 1538 1539 1540
    if (vm->monitor != -1)
        close(vm->monitor);
    vm->logfile = -1;
    vm->monitor = -1;

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

1544 1545 1546 1547
    /* Reset Security Labels */
    if (driver->securityDriver)
        driver->securityDriver->domainRestoreSecurityLabel(conn, vm);

1548 1549 1550 1551 1552 1553 1554
    /* Clear out dynamically assigned labels */
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
        VIR_FREE(vm->def->seclabel.model);
        VIR_FREE(vm->def->seclabel.label);
        VIR_FREE(vm->def->seclabel.imagelabel);
    }

1555
    if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
1556
        VIR_WARN(_("Failed to remove domain status for %s"),
1557 1558
                 vm->def->name);
    }
1559
    vm->pid = -1;
1560
    vm->def->id = -1;
1561
    vm->state = VIR_DOMAIN_SHUTOFF;
1562
    VIR_FREE(vm->vcpupids);
1563
    vm->nvcpupids = 0;
1564 1565

    if (vm->newDef) {
1566
        virDomainDefFree(vm->def);
1567
        vm->def = vm->newDef;
1568
        vm->def->id = -1;
1569 1570 1571 1572 1573
        vm->newDef = NULL;
    }
}


1574
static void
1575
qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
1576
    struct qemud_driver *driver = opaque;
1577
    virDomainObjPtr vm = NULL;
1578
    virDomainEventPtr event = NULL;
1579
    unsigned int i;
1580
    int quit = 0, failed = 0;
1581

1582
    qemuDriverLock(driver);
1583
    for (i = 0 ; i < driver->domains.count ; i++) {
1584 1585 1586
        virDomainObjPtr tmpvm = driver->domains.objs[i];
        virDomainObjLock(tmpvm);
        if (virDomainIsActive(tmpvm) &&
1587
            tmpvm->monitorWatch == watch) {
1588
            vm = tmpvm;
1589
            break;
1590
        }
1591
        virDomainObjUnlock(tmpvm);
1592 1593 1594
    }

    if (!vm)
1595
        goto cleanup;
1596

1597
    if (vm->monitor != fd) {
1598 1599
        failed = 1;
    } else {
1600
        if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
1601
            quit = 1;
1602
        else {
1603 1604
            VIR_ERROR(_("unhandled fd event %d for %s"),
                      events, vm->def->name);
1605
            failed = 1;
1606
        }
1607 1608
    }

1609
    if (failed || quit) {
1610 1611 1612 1613 1614
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         quit ?
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
        qemudShutdownVMDaemon(NULL, driver, vm);
        if (!vm->persistent) {
            virDomainRemoveInactive(&driver->domains,
                                    vm);
            vm = NULL;
        }
    }

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
1626 1627
    if (event)
        qemuDomainEventQueue(driver, event);
1628
    qemuDriverUnlock(driver);
1629 1630
}

1631
static int
1632 1633 1634 1635 1636
qemudMonitorCommandExtra(const virDomainObjPtr vm,
                         const char *cmd,
                         const char *extra,
                         const char *extraPrompt,
                         char **reply) {
D
Daniel P. Berrange 已提交
1637 1638
    int size = 0;
    char *buf = NULL;
1639
    size_t cmdlen = strlen(cmd);
1640
    size_t extralen = extra ? strlen(extra) : 0;
D
Daniel P. Berrange 已提交
1641

1642 1643 1644
    if (safewrite(vm->monitor, cmd, cmdlen) != cmdlen)
        return -1;
    if (safewrite(vm->monitor, "\r", 1) != 1)
D
Daniel P. Berrange 已提交
1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
        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 已提交
1657

1658 1659
            if (got == 0)
                goto error;
D
Daniel P. Berrange 已提交
1660 1661 1662 1663 1664
            if (got < 0) {
                if (errno == EINTR)
                    continue;
                if (errno == EAGAIN)
                    break;
1665
                goto error;
1666
            }
1667
            if (VIR_REALLOC_N(buf, size+got+1) < 0)
1668 1669
                goto error;

D
Daniel P. Berrange 已提交
1670 1671 1672 1673
            memmove(buf+size, data, got);
            buf[size+got] = '\0';
            size += got;
        }
1674

D
Daniel P. Berrange 已提交
1675
        /* Look for QEMU prompt to indicate completion */
1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700
        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 已提交
1701

1702 1703
                break;
            }
D
Daniel P. Berrange 已提交
1704 1705 1706 1707 1708 1709
        }
    pollagain:
        /* Need to wait for more data */
        if (poll(&fd, 1, -1) < 0) {
            if (errno == EINTR)
                goto pollagain;
1710
            goto error;
D
Daniel P. Berrange 已提交
1711 1712 1713
        }
    }

1714
    /* Log, but ignore failures to write logfile for VM */
1715 1716
    if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
        char ebuf[1024];
1717
        VIR_WARN(_("Unable to log VM console data: %s\n"),
1718 1719
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1720

D
Daniel P. Berrange 已提交
1721 1722
    *reply = buf;
    return 0;
1723 1724 1725 1726

 error:
    if (buf) {
        /* Log, but ignore failures to write logfile for VM */
1727 1728
        if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
            char ebuf[1024];
1729
            VIR_WARN(_("Unable to log VM console data: %s\n"),
1730 1731
                     virStrerror(errno, ebuf, sizeof ebuf));
        }
1732
        VIR_FREE(buf);
1733 1734
    }
    return -1;
D
Daniel P. Berrange 已提交
1735 1736
}

1737 1738 1739 1740 1741 1742 1743 1744
static int
qemudMonitorCommand(const virDomainObjPtr vm,
                    const char *cmd,
                    char **reply) {
    return qemudMonitorCommandExtra(vm, cmd, NULL, NULL, reply);
}


1745 1746 1747 1748 1749 1750
/**
 * qemudProbe:
 *
 * Probe for the availability of the qemu driver, assume the
 * presence of QEmu emulation if the binaries are installed
 */
1751
static int qemudProbe(void)
1752 1753 1754
{
    if ((virFileExists("/usr/bin/qemu")) ||
        (virFileExists("/usr/bin/qemu-kvm")) ||
G
Guido Günther 已提交
1755
        (virFileExists("/usr/bin/kvm")) ||
1756 1757 1758 1759
        (virFileExists("/usr/bin/xenner")))
        return 1;

    return 0;
1760
}
1761

1762
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
1763
                                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1764
                                  int flags ATTRIBUTE_UNUSED) {
1765 1766 1767
    uid_t uid = getuid();

    if (qemu_driver == NULL)
1768
        goto decline;
1769

1770 1771 1772 1773 1774 1775
    if (!qemudProbe())
        goto decline;

    if (conn->uri == NULL) {
        conn->uri = xmlParseURI(uid ? "qemu:///session" : "qemu:///system");
        if (!conn->uri) {
1776
            virReportOOMError(conn);
1777 1778 1779 1780
            return VIR_DRV_OPEN_ERROR;
        }
    } else if (conn->uri->scheme == NULL ||
               conn->uri->path == NULL)
1781 1782
        goto decline;

1783
    if (STRNEQ (conn->uri->scheme, "qemu"))
1784 1785
        goto decline;

1786
    if (uid != 0) {
1787
        if (STRNEQ (conn->uri->path, "/session"))
1788
            goto decline;
1789
    } else { /* root */
1790 1791
        if (STRNEQ (conn->uri->path, "/system") &&
            STRNEQ (conn->uri->path, "/session"))
1792
            goto decline;
1793 1794 1795 1796 1797
    }

    conn->privateData = qemu_driver;

    return VIR_DRV_OPEN_SUCCESS;
1798 1799

 decline:
1800
    return VIR_DRV_OPEN_DECLINED;
1801 1802 1803
}

static int qemudClose(virConnectPtr conn) {
1804
    struct qemud_driver *driver = conn->privateData;
1805 1806 1807

    /* Get rid of callbacks registered for this conn */
    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
1808 1809 1810 1811 1812 1813

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
1814 1815 1816 1817 1818 1819 1820 1821 1822 1823
/* 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;
    }
}

1824
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1825
    return "QEMU";
1826 1827
}

1828 1829 1830 1831 1832

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

    int r, fd;
1833

1834 1835
    fd = open(KVM_DEVICE, O_RDONLY);
    if (fd < 0) {
1836 1837
        virReportSystemError(NULL, errno, _("Unable to open %s"), KVM_DEVICE);
        return -1;
1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848
    }

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

    close(fd);
    return maxvcpus;
}


1849
static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) {
1850 1851 1852
    if (!type)
        return 16;

1853
    if (STRCASEEQ(type, "qemu"))
1854 1855
        return 16;

1856
    if (STRCASEEQ(type, "kvm"))
1857
        return kvmGetMaxVCPUs();
1858

1859
    if (STRCASEEQ(type, "kqemu"))
1860
        return 1;
1861 1862 1863

    qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
                     _("unknown type '%s'"), type);
1864 1865 1866
    return -1;
}

1867 1868 1869
static int qemudGetNodeInfo(virConnectPtr conn,
                            virNodeInfoPtr nodeinfo) {
    return virNodeInfoPopulate(conn, nodeinfo);
1870 1871 1872
}


1873
static char *qemudGetCapabilities(virConnectPtr conn) {
1874
    struct qemud_driver *driver = conn->privateData;
1875
    char *xml;
1876

1877
    qemuDriverLock(driver);
1878
    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
1879
        virReportOOMError(conn);
1880
    qemuDriverUnlock(driver);
1881

1882
    return xml;
1883 1884 1885
}


1886 1887 1888 1889 1890 1891 1892 1893
#if HAVE_NUMACTL
static int
qemudNodeGetCellsFreeMemory(virConnectPtr conn,
                            unsigned long long *freeMems,
                            int startCell,
                            int maxCells)
{
    int n, lastCell, numCells;
1894
    int ret = -1;
D
Daniel P. Berrange 已提交
1895
    int maxCell;
1896 1897 1898 1899

    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1900
        goto cleanup;
1901
    }
D
Daniel P. Berrange 已提交
1902 1903 1904 1905 1906 1907 1908
    maxCell = numa_max_node();
    if (startCell > maxCell) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("start cell %d out of range (0-%d)"),
                         startCell, maxCell);
        goto cleanup;
    }
1909
    lastCell = startCell + maxCells - 1;
D
Daniel P. Berrange 已提交
1910 1911
    if (lastCell > maxCell)
        lastCell = maxCell;
1912 1913 1914 1915 1916 1917

    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"));
1918
            goto cleanup;
1919 1920 1921
        }
        freeMems[numCells++] = mem;
    }
1922 1923 1924 1925
    ret = numCells;

cleanup:
    return ret;
1926 1927 1928 1929 1930
}

static unsigned long long
qemudNodeGetFreeMemory (virConnectPtr conn)
{
D
Daniel P. Berrange 已提交
1931
    unsigned long long freeMem = 0;
1932
    int n;
1933

1934 1935 1936
    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1937
        goto cleanup;
1938 1939 1940 1941 1942 1943 1944
    }

    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"));
1945
            goto cleanup;
1946 1947 1948 1949
        }
        freeMem += mem;
    }

1950
cleanup:
1951 1952 1953 1954
    return freeMem;
}

#endif
1955

D
Daniel P. Berrange 已提交
1956 1957 1958
static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) {
    char proc[PATH_MAX];
    FILE *pidinfo;
1959
    unsigned long long usertime, systime;
D
Daniel P. Berrange 已提交
1960 1961 1962 1963 1964 1965

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

    if (!(pidinfo = fopen(proc, "r"))) {
1966
        /*printf("cannot read pid info");*/
D
Daniel P. Berrange 已提交
1967 1968 1969 1970 1971
        /* VM probably shut down, so fake 0 */
        *cpuTime = 0;
        return 0;
    }

1972
    if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
1973
        qemudDebug("not enough arg");
D
Daniel P. Berrange 已提交
1974 1975 1976 1977 1978 1979 1980 1981
        return -1;
    }

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

1984
    qemudDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
D
Daniel P. Berrange 已提交
1985 1986 1987 1988 1989 1990 1991

    fclose(pidinfo);

    return 0;
}


1992
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
1993
                                          int id) {
1994 1995 1996 1997
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

1998
    qemuDriverLock(driver);
1999
    vm  = virDomainFindByID(&driver->domains, id);
2000
    qemuDriverUnlock(driver);
2001 2002

    if (!vm) {
2003
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
2004
        goto cleanup;
2005 2006
    }

2007
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2008
    if (dom) dom->id = vm->def->id;
2009 2010

cleanup:
2011 2012
    if (vm)
        virDomainObjUnlock(vm);
2013 2014
    return dom;
}
2015

2016
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
2017
                                            const unsigned char *uuid) {
2018 2019 2020
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
2021

2022
    qemuDriverLock(driver);
2023
    vm = virDomainFindByUUID(&driver->domains, uuid);
2024 2025
    qemuDriverUnlock(driver);

2026
    if (!vm) {
2027
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
2028
        goto cleanup;
2029 2030
    }

2031
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2032
    if (dom) dom->id = vm->def->id;
2033 2034

cleanup:
2035 2036
    if (vm)
        virDomainObjUnlock(vm);
2037 2038
    return dom;
}
2039

2040
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
2041
                                            const char *name) {
2042 2043 2044
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
2045

2046
    qemuDriverLock(driver);
2047
    vm = virDomainFindByName(&driver->domains, name);
2048 2049
    qemuDriverUnlock(driver);

2050
    if (!vm) {
2051
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
2052
        goto cleanup;
2053 2054
    }

2055
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2056
    if (dom) dom->id = vm->def->id;
2057 2058

cleanup:
2059 2060
    if (vm)
        virDomainObjUnlock(vm);
2061 2062 2063
    return dom;
}

2064
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
2065 2066 2067
    struct qemud_driver *driver = conn->privateData;
    int ret = -1;

2068
    qemuDriverLock(driver);
2069
    if (qemudExtractVersion(conn, driver) < 0)
2070
        goto cleanup;
2071

2072
    *version = qemu_driver->qemuVersion;
2073 2074 2075
    ret = 0;

cleanup:
2076
    qemuDriverUnlock(driver);
2077
    return ret;
D
Daniel P. Berrange 已提交
2078 2079
}

2080 2081 2082
static char *
qemudGetHostname (virConnectPtr conn)
{
2083
    char *result;
2084

2085 2086
    result = virGetHostname();
    if (result == NULL) {
2087 2088
        virReportSystemError (conn, errno,
                              "%s", _("failed to determine host name"));
2089 2090 2091
        return NULL;
    }
    /* Caller frees this string. */
2092
    return result;
2093 2094
}

2095
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
2096
    struct qemud_driver *driver = conn->privateData;
2097 2098
    int got = 0, i;

2099 2100 2101
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count && got < nids ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
2102 2103
        if (virDomainIsActive(driver->domains.objs[i]))
            ids[got++] = driver->domains.objs[i]->def->id;
2104 2105 2106
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
2107

D
Daniel P. Berrange 已提交
2108 2109
    return got;
}
2110

2111
static int qemudNumDomains(virConnectPtr conn) {
2112
    struct qemud_driver *driver = conn->privateData;
2113 2114
    int n = 0, i;

2115 2116 2117
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
2118
        if (virDomainIsActive(driver->domains.objs[i]))
2119
            n++;
2120 2121 2122
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
2123

2124
    return n;
D
Daniel P. Berrange 已提交
2125
}
2126

2127
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
2128
                                      unsigned int flags ATTRIBUTE_UNUSED) {
2129
    struct qemud_driver *driver = conn->privateData;
2130
    virDomainDefPtr def;
2131
    virDomainObjPtr vm = NULL;
2132
    virDomainPtr dom = NULL;
2133
    virDomainEventPtr event = NULL;
D
Daniel P. Berrange 已提交
2134

2135
    qemuDriverLock(driver);
2136 2137
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
2138
        goto cleanup;
2139

2140 2141 2142
    if (virSecurityDriverVerify(conn, def) < 0)
        goto cleanup;

2143
    vm = virDomainFindByName(&driver->domains, def->name);
2144
    if (vm) {
2145
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2146
                         _("domain '%s' is already defined"),
2147
                         def->name);
2148
        goto cleanup;
2149
    }
2150
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
2151 2152 2153 2154 2155
    if (vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(def->uuid, uuidstr);
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2156
                         _("domain with uuid '%s' is already defined"),
2157
                         uuidstr);
2158
        goto cleanup;
2159
    }
2160

2161 2162
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
2163 2164 2165 2166
                                  def)))
        goto cleanup;

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

2168
    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
2169 2170
        virDomainRemoveInactive(&driver->domains,
                                vm);
2171
        vm = NULL;
2172
        goto cleanup;
D
Daniel P. Berrange 已提交
2173
    }
2174 2175 2176 2177

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

2179
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2180
    if (dom) dom->id = vm->def->id;
2181 2182 2183

cleanup:
    virDomainDefFree(def);
2184 2185
    if (vm)
        virDomainObjUnlock(vm);
2186 2187
    if (event)
        qemuDomainEventQueue(driver, event);
2188
    qemuDriverUnlock(driver);
2189
    return dom;
D
Daniel P. Berrange 已提交
2190 2191 2192
}


2193
static int qemudDomainSuspend(virDomainPtr dom) {
2194
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
2195
    char *info;
2196 2197
    virDomainObjPtr vm;
    int ret = -1;
2198
    virDomainEventPtr event = NULL;
2199

2200
    qemuDriverLock(driver);
2201
    vm = virDomainFindByID(&driver->domains, dom->id);
2202 2203
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
2204
    if (!vm) {
2205
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
2206
        goto cleanup;
D
Daniel P. Berrange 已提交
2207
    }
2208
    if (!virDomainIsActive(vm)) {
2209 2210
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
2211
        goto cleanup;
D
Daniel P. Berrange 已提交
2212
    }
2213
    if (vm->state != VIR_DOMAIN_PAUSED) {
2214
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
2215 2216 2217 2218 2219 2220
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("suspend operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
2221 2222 2223
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
2224
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
2225
    }
2226 2227
    if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        goto cleanup;
2228 2229 2230
    ret = 0;

cleanup:
2231 2232
    if (vm)
        virDomainObjUnlock(vm);
2233 2234 2235 2236 2237 2238

    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2239
    return ret;
D
Daniel P. Berrange 已提交
2240 2241 2242
}


2243
static int qemudDomainResume(virDomainPtr dom) {
2244
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
2245
    char *info;
2246 2247
    virDomainObjPtr vm;
    int ret = -1;
2248
    virDomainEventPtr event = NULL;
2249

2250
    qemuDriverLock(driver);
2251
    vm = virDomainFindByID(&driver->domains, dom->id);
2252 2253
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
2254
    if (!vm) {
2255 2256
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         _("no domain with matching id %d"), dom->id);
2257
        goto cleanup;
D
Daniel P. Berrange 已提交
2258
    }
2259
    if (!virDomainIsActive(vm)) {
2260 2261
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
2262
        goto cleanup;
D
Daniel P. Berrange 已提交
2263
    }
2264
    if (vm->state == VIR_DOMAIN_PAUSED) {
2265
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
2266 2267 2268 2269 2270 2271
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("resume operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_RUNNING;
        qemudDebug("Reply %s", info);
2272 2273 2274
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
2275
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
2276
    }
2277 2278
    if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        goto cleanup;
2279 2280 2281
    ret = 0;

cleanup:
2282 2283
    if (vm)
        virDomainObjUnlock(vm);
2284 2285 2286 2287 2288
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2289
    return ret;
D
Daniel P. Berrange 已提交
2290 2291 2292
}


2293
static int qemudDomainShutdown(virDomainPtr dom) {
2294 2295
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2296
    char* info;
2297
    int ret = -1;
2298

2299
    qemuDriverLock(driver);
2300
    vm = virDomainFindByID(&driver->domains, dom->id);
2301 2302
    qemuDriverUnlock(driver);

2303 2304
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2305
                         _("no domain with matching id %d"), dom->id);
2306
        goto cleanup;
2307 2308
    }

2309
    if (qemudMonitorCommand(vm, "system_powerdown", &info) < 0) {
2310
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2311
                         "%s", _("shutdown operation failed"));
2312
        goto cleanup;
2313
    }
D
Daniel Veillard 已提交
2314
    VIR_FREE(info);
2315 2316 2317
    ret = 0;

cleanup:
2318 2319
    if (vm)
        virDomainObjUnlock(vm);
2320
    return ret;
2321 2322 2323
}


2324
static int qemudDomainDestroy(virDomainPtr dom) {
2325 2326 2327
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2328
    virDomainEventPtr event = NULL;
2329

2330
    qemuDriverLock(driver);
2331
    vm  = virDomainFindByID(&driver->domains, dom->id);
D
Daniel P. Berrange 已提交
2332
    if (!vm) {
2333
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2334
                         _("no domain with matching id %d"), dom->id);
2335
        goto cleanup;
D
Daniel P. Berrange 已提交
2336
    }
2337

2338
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2339 2340 2341
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2342
    if (!vm->persistent) {
2343 2344
        virDomainRemoveInactive(&driver->domains,
                                vm);
2345 2346
        vm = NULL;
    }
2347 2348 2349
    ret = 0;

cleanup:
2350 2351
    if (vm)
        virDomainObjUnlock(vm);
2352 2353
    if (event)
        qemuDomainEventQueue(driver, event);
2354
    qemuDriverUnlock(driver);
2355
    return ret;
D
Daniel P. Berrange 已提交
2356 2357 2358
}


2359
static char *qemudDomainGetOSType(virDomainPtr dom) {
2360 2361 2362
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *type = NULL;
2363

2364
    qemuDriverLock(driver);
2365
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2366
    qemuDriverUnlock(driver);
2367 2368
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2369
                         "%s", _("no domain with matching uuid"));
2370
        goto cleanup;
2371 2372
    }

2373
    if (!(type = strdup(vm->def->os.type)))
2374
        virReportOOMError(dom->conn);
2375 2376

cleanup:
2377 2378
    if (vm)
        virDomainObjUnlock(vm);
2379 2380 2381
    return type;
}

2382 2383
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
2384 2385 2386
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    unsigned long ret = 0;
2387

2388
    qemuDriverLock(driver);
2389
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2390 2391
    qemuDriverUnlock(driver);

2392
    if (!vm) {
2393 2394 2395
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2396
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2397
                         _("no domain with matching uuid '%s'"), uuidstr);
2398
        goto cleanup;
2399 2400
    }

2401 2402 2403
    ret = vm->def->maxmem;

cleanup:
2404 2405
    if (vm)
        virDomainObjUnlock(vm);
2406
    return ret;
2407 2408 2409
}

static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
2410 2411 2412
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2413

2414
    qemuDriverLock(driver);
2415
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2416 2417
    qemuDriverUnlock(driver);

2418
    if (!vm) {
2419 2420 2421
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2422
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2423
                         _("no domain with matching uuid '%s'"), uuidstr);
2424
        goto cleanup;
2425 2426 2427 2428
    }

    if (newmax < vm->def->memory) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2429
                         "%s", _("cannot set max memory lower than current memory"));
2430
        goto cleanup;;
2431 2432 2433
    }

    vm->def->maxmem = newmax;
2434 2435 2436
    ret = 0;

cleanup:
2437 2438
    if (vm)
        virDomainObjUnlock(vm);
2439
    return ret;
2440 2441
}

2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456

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

/*
 * Returns: 0 if balloon not supported, +1 if balloon query worked
 * or -1 on failure
 */
static int qemudDomainGetMemoryBalloon(virConnectPtr conn,
                                       virDomainObjPtr vm,
                                       unsigned long *currmem) {
    char *reply = NULL;
    int ret = -1;
    char *offset;

2457 2458 2459
    if (!virDomainIsActive(vm))
        return 0;

2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533
    if (qemudMonitorCommand(vm, "info balloon", &reply) < 0) {
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("could not query memory balloon allocation"));
        goto cleanup;
    }

    DEBUG ("balloon reply: '%s'", reply);
    if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) {
        unsigned int memMB;
        char *end;
        offset += strlen(BALLOON_PREFIX);
        if (virStrToLong_ui(offset, &end, 10, &memMB) < 0) {
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("could not parse memory balloon allocation"));
            goto cleanup;
        }
        *currmem = memMB * 1024;
        ret = 1;
    } else {
        /* We don't raise an error here, since its to be expected that
         * many QEMU's don't support ballooning
         */
        ret = 0;
    }

cleanup:
    VIR_FREE(reply);
    return ret;
}

/*
 * Returns: 0 if balloon not supported, +1 if balloon query worked
 * or -1 on failure
 */
static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
                                       virDomainObjPtr vm,
                                       unsigned long newmem) {
    char *cmd;
    char *reply = NULL;
    int ret = -1;

    /*
     * 'newmem' is in KB, QEMU monitor works in MB, and we all wish
     * we just worked in bytes with unsigned long long everywhere.
     */
    if (virAsprintf(&cmd, "balloon %lu", (newmem / 1024)) < 0) {
        virReportOOMError(conn);
        goto cleanup;
    }

    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("could not balloon memory allocation"));
        VIR_FREE(cmd);
        goto cleanup;
    }
    VIR_FREE(cmd);

    /* If the command failed qemu prints: 'unknown command'
     * No message is printed on success it seems */
    DEBUG ("balloon reply: %s", reply);
    if (strstr(reply, "\nunknown command:")) {
        /* Don't set error - it is expected memory balloon fails on many qemu */
        ret = 0;
    } else {
        ret = 1;
    }

cleanup:
    VIR_FREE(reply);
    return ret;
}


2534
static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
2535 2536 2537
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2538

2539
    qemuDriverLock(driver);
2540
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2541
    qemuDriverUnlock(driver);
2542
    if (!vm) {
2543 2544 2545
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

    if (newmem > vm->def->maxmem) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2553
                         "%s", _("cannot set memory higher than max memory"));
2554
        goto cleanup;
2555 2556
    }

2557 2558 2559 2560 2561 2562 2563 2564 2565
    if (virDomainIsActive(vm)) {
        ret = qemudDomainSetMemoryBalloon(dom->conn, vm, newmem);
        if (ret == 0)
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                             "%s", _("cannot set memory of an active domain"));
    } else {
        vm->def->memory = newmem;
        ret = 0;
    }
2566 2567

cleanup:
2568 2569
    if (vm)
        virDomainObjUnlock(vm);
2570
    return ret;
2571 2572
}

2573
static int qemudDomainGetInfo(virDomainPtr dom,
2574
                              virDomainInfoPtr info) {
2575 2576 2577
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2578 2579
    int err;
    unsigned long balloon;
2580

2581
    qemuDriverLock(driver);
2582
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2583
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
2584
    if (!vm) {
2585 2586
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
2587
        goto cleanup;
D
Daniel P. Berrange 已提交
2588 2589
    }

2590
    info->state = vm->state;
D
Daniel P. Berrange 已提交
2591

2592
    if (!virDomainIsActive(vm)) {
2593
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
2594
    } else {
2595
        if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
2596
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
2597
            goto cleanup;
D
Daniel P. Berrange 已提交
2598 2599 2600
        }
    }

2601 2602 2603 2604
    err = qemudDomainGetMemoryBalloon(dom->conn, vm, &balloon);
    if (err < 0)
        goto cleanup;

2605
    info->maxMem = vm->def->maxmem;
2606 2607 2608 2609 2610
    if (err == 0)
        /* Balloon not supported, so maxmem is always the allocation */
        info->memory = vm->def->maxmem;
    else
        info->memory = balloon;
2611
    info->nrVirtCpu = vm->def->vcpus;
2612 2613 2614
    ret = 0;

cleanup:
2615 2616
    if (vm)
        virDomainObjUnlock(vm);
2617
    return ret;
D
Daniel P. Berrange 已提交
2618 2619 2620
}


D
Daniel P. Berrange 已提交
2621
static char *qemudEscape(const char *in, int shell)
2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642
{
    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 已提交
2643 2644 2645 2646
            if (shell)
                len += 5;
            else
                len += 1;
2647 2648 2649 2650 2651 2652 2653
            break;
        default:
            len += 1;
            break;
        }
    }

2654
    if (VIR_ALLOC_N(out, len + 1) < 0)
2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672
        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 已提交
2673 2674 2675 2676 2677 2678 2679 2680 2681
            if (shell) {
                out[j++] = '\'';
                out[j++] = '\\';
                out[j++] = '\\';
                out[j++] = '\'';
                out[j++] = '\'';
            } else {
                out[j++] = in[i];
            }
2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
            break;
        default:
            out[j++] = in[i];
            break;
        }
    }
    out[j] = '\0';

    return out;
}

2693 2694 2695 2696 2697
static char *qemudEscapeMonitorArg(const char *in)
{
    return qemudEscape(in, 0);
}

D
Daniel P. Berrange 已提交
2698 2699 2700 2701
static char *qemudEscapeShellArg(const char *in)
{
    return qemudEscape(in, 1);
}
2702

2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713
#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];
};

2714
static int qemudDomainSave(virDomainPtr dom,
2715
                           const char *path) {
2716 2717 2718 2719 2720 2721 2722
    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;
2723
    struct qemud_save_header header;
2724
    int ret = -1;
2725
    virDomainEventPtr event = NULL;
2726 2727 2728 2729 2730

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

2731
    qemuDriverLock(driver);
2732 2733
    vm = virDomainFindByID(&driver->domains, dom->id);

D
Daniel P. Berrange 已提交
2734
    if (!vm) {
2735
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2736
                         _("no domain with matching id %d"), dom->id);
2737
        goto cleanup;
D
Daniel P. Berrange 已提交
2738
    }
2739

2740
    if (!virDomainIsActive(vm)) {
2741
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2742
                         "%s", _("domain is not running"));
2743
        goto cleanup;
D
Daniel P. Berrange 已提交
2744
    }
2745 2746 2747 2748

    /* Pause */
    if (vm->state == VIR_DOMAIN_RUNNING) {
        header.was_running = 1;
2749
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
2750
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2751
                             "%s", _("suspend operation failed"));
2752
            goto cleanup;
2753
        }
2754 2755 2756
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
        VIR_FREE(info);
2757 2758 2759
    }

    /* Get XML for the domain */
2760
    xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE);
2761 2762
    if (!xml) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2763
                         "%s", _("failed to get domain xml"));
2764
        goto cleanup;
2765 2766 2767 2768 2769 2770
    }
    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,
2771
                         _("failed to create '%s'"), path);
2772
        goto cleanup;
2773 2774 2775 2776
    }

    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2777
                         "%s", _("failed to write save header"));
2778
        goto cleanup;
2779 2780 2781 2782
    }

    if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2783
                         "%s", _("failed to write xml"));
2784
        goto cleanup;
2785 2786
    }

2787
    if (close(fd) < 0) {
2788 2789 2790
        virReportSystemError(dom->conn, errno,
                             _("unable to save file %s"),
                             path);
2791 2792 2793
        goto cleanup;
    }
    fd = -1;
2794 2795 2796 2797

    /* Migrate to file */
    safe_path = qemudEscapeShellArg(path);
    if (!safe_path) {
2798
        virReportOOMError(dom->conn);
2799
        goto cleanup;
2800
    }
2801
    if (virAsprintf(&command, "migrate \"exec:"
2802
                  "dd of='%s' oflag=append conv=notrunc 2>/dev/null"
2803
                  "\"", safe_path) == -1) {
2804
        virReportOOMError(dom->conn);
2805 2806
        command = NULL;
        goto cleanup;
2807 2808
    }

2809
    if (qemudMonitorCommand(vm, command, &info) < 0) {
2810
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2811
                         "%s", _("migrate operation failed"));
2812
        goto cleanup;
2813 2814
    }

2815 2816 2817 2818 2819 2820 2821 2822
    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"));
2823
        goto cleanup;
2824 2825
    }

2826 2827
    /* Shut it down */
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2828 2829 2830
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2831
    if (!vm->persistent) {
2832 2833
        virDomainRemoveInactive(&driver->domains,
                                vm);
2834 2835
        vm = NULL;
    }
2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
    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);
2847 2848
    if (vm)
        virDomainObjUnlock(vm);
2849 2850
    if (event)
        qemuDomainEventQueue(driver, event);
2851
    qemuDriverUnlock(driver);
2852
    return ret;
D
Daniel P. Berrange 已提交
2853 2854 2855
}


2856
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
2857 2858
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2859
    int max;
2860
    int ret = -1;
2861
    const char *type;
2862

2863
    qemuDriverLock(driver);
2864
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2865 2866
    qemuDriverUnlock(driver);

2867
    if (!vm) {
2868 2869 2870
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2871
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2872
                         _("no domain with matching uuid '%s'"), uuidstr);
2873
        goto cleanup;
2874 2875
    }

2876
    if (virDomainIsActive(vm)) {
2877
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
2878
                         _("cannot change vcpu count of an active domain"));
2879
        goto cleanup;
2880 2881
    }

2882 2883 2884 2885 2886 2887 2888 2889
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("unknown virt type in domain definition '%d'"),
                         vm->def->virtType);
        goto cleanup;
    }

    if ((max = qemudGetMaxVCPUs(dom->conn, type)) < 0) {
2890 2891
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                         _("could not determine max vcpus for the domain"));
2892
        goto cleanup;
2893 2894 2895 2896 2897 2898
    }

    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);
2899
        goto cleanup;
2900 2901 2902
    }

    vm->def->vcpus = nvcpus;
2903 2904 2905
    ret = 0;

cleanup:
2906 2907
    if (vm)
        virDomainObjUnlock(vm);
2908
    return ret;
2909 2910
}

2911 2912 2913 2914 2915 2916 2917

#if HAVE_SCHED_GETAFFINITY
static int
qemudDomainPinVcpu(virDomainPtr dom,
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
2918 2919
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2920 2921 2922
    cpu_set_t mask;
    int i, maxcpu;
    virNodeInfo nodeinfo;
2923
    int ret = -1;
2924

2925
    qemuDriverLock(driver);
2926
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2927 2928
    qemuDriverUnlock(driver);

2929
    if (!virDomainIsActive(vm)) {
2930 2931
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         "%s",_("cannot pin vcpus on an inactive domain"));
2932
        goto cleanup;
2933 2934 2935 2936 2937 2938
    }

    if (vcpu > (vm->nvcpupids-1)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         _("vcpu number out of range %d > %d"),
                         vcpu, vm->nvcpupids);
2939
        goto cleanup;
2940 2941 2942
    }

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2943
        goto cleanup;
2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956

    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) {
2957 2958
            virReportSystemError(dom->conn, errno, "%s",
                                 _("cannot set affinity"));
2959
            goto cleanup;
2960 2961 2962 2963
        }
    } else {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("cpu affinity is not supported"));
2964
        goto cleanup;
2965
    }
2966
    ret = 0;
2967

2968
cleanup:
2969 2970
    if (vm)
        virDomainObjUnlock(vm);
2971
    return ret;
2972 2973 2974 2975 2976 2977 2978 2979
}

static int
qemudDomainGetVcpus(virDomainPtr dom,
                    virVcpuInfoPtr info,
                    int maxinfo,
                    unsigned char *cpumaps,
                    int maplen) {
2980 2981
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2982 2983
    virNodeInfo nodeinfo;
    int i, v, maxcpu;
2984
    int ret = -1;
2985

2986
    qemuDriverLock(driver);
2987
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2988 2989
    qemuDriverUnlock(driver);

2990
    if (!virDomainIsActive(vm)) {
2991 2992
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         "%s",_("cannot pin vcpus on an inactive domain"));
2993
        goto cleanup;
2994 2995 2996
    }

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2997
        goto cleanup;
2998 2999 3000 3001 3002 3003 3004 3005 3006

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

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

3007 3008 3009 3010 3011 3012 3013 3014
    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 */
            }
3015 3016
        }

3017 3018 3019 3020 3021 3022 3023 3024 3025
        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) {
3026 3027
                        virReportSystemError(dom->conn, errno, "%s",
                                             _("cannot get affinity"));
3028 3029 3030 3031 3032 3033
                        goto cleanup;
                    }

                    for (i = 0 ; i < maxcpu ; i++)
                        if (CPU_ISSET(i, &mask))
                            VIR_USE_CPU(cpumap, i);
3034
                }
3035 3036 3037 3038
            } else {
                qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                                 "%s", _("cpu affinity is not available"));
                goto cleanup;
3039 3040 3041
            }
        }
    }
3042
    ret = maxinfo;
3043

3044
cleanup:
3045 3046
    if (vm)
        virDomainObjUnlock(vm);
3047
    return ret;
3048 3049 3050 3051
}
#endif /* HAVE_SCHED_GETAFFINITY */


3052
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
3053 3054
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3055
    const char *type;
3056
    int ret = -1;
3057

3058
    qemuDriverLock(driver);
3059
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3060 3061
    qemuDriverUnlock(driver);

3062
    if (!vm) {
3063 3064 3065
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
3066
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
3067
                         _("no domain with matching uuid '%s'"), uuidstr);
3068
        goto cleanup;
3069 3070
    }

3071
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
3072 3073 3074
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("unknown virt type in domain definition '%d'"),
                         vm->def->virtType);
3075
        goto cleanup;
3076 3077
    }

3078
    ret = qemudGetMaxVCPUs(dom->conn, type);
3079

3080
cleanup:
3081 3082
    if (vm)
        virDomainObjUnlock(vm);
3083 3084 3085
    return ret;
}

3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151
static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
{
    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
    virDomainObjPtr vm;
    const char *type;
    int ret = -1;

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

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

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

    /*
     * Theoretically, the pid can be replaced during this operation and
     * return the label of a different process.  If atomicity is needed,
     * further validation will be required.
     *
     * Comment from Dan Berrange:
     *
     *   Well the PID as stored in the virDomainObjPtr can't be changed
     *   because you've got a locked object.  The OS level PID could have
     *   exited, though and in extreme circumstances have cycled through all
     *   PIDs back to ours. We could sanity check that our PID still exists
     *   after reading the label, by checking that our FD connecting to the
     *   QEMU monitor hasn't seen SIGHUP/ERR on poll().
     */
    if (virDomainIsActive(vm)) {
        if (driver->securityDriver && driver->securityDriver->domainGetSecurityLabel) {
            if (driver->securityDriver->domainGetSecurityLabel(dom->conn, vm, seclabel) == -1) {
                qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                                 _("Failed to get security label"));
                goto cleanup;
            }
        }
    }

    ret = 0;

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
    return ret;
}

static int qemudNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel)
{
    struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
    char *p;

    if (!driver->securityDriver)
        return -2;
3152

3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173
    p = driver->caps->host.secModel.model;
    if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("security model string exceeds max %d bytes"),
                         VIR_SECURITY_MODEL_BUFLEN-1);
        return -1;
    }
    strcpy(secmodel->model, p);

    p = driver->caps->host.secModel.doi;
    if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("security DOI string exceeds max %d bytes"),
                         VIR_SECURITY_DOI_BUFLEN-1);
        return -1;
    }
    strcpy(secmodel->doi, p);
    return 0;
}

/* TODO: check seclabel restore */
3174
static int qemudDomainRestore(virConnectPtr conn,
3175 3176 3177
                              const char *path) {
    struct qemud_driver *driver = conn->privateData;
    virDomainDefPtr def = NULL;
3178
    virDomainObjPtr vm = NULL;
3179 3180 3181
    int fd = -1;
    int ret = -1;
    char *xml = NULL;
3182
    struct qemud_save_header header;
3183
    virDomainEventPtr event = NULL;
3184

3185
    qemuDriverLock(driver);
3186 3187 3188
    /* Verify the header and read the XML */
    if ((fd = open(path, O_RDONLY)) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3189
                         "%s", _("cannot read domain image"));
3190
        goto cleanup;
3191 3192 3193 3194
    }

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3195
                         "%s", _("failed to read qemu header"));
3196
        goto cleanup;
3197 3198 3199 3200
    }

    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3201
                         "%s", _("image magic is incorrect"));
3202
        goto cleanup;
3203 3204 3205 3206
    }

    if (header.version > QEMUD_SAVE_VERSION) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3207
                         _("image version is not supported (%d > %d)"),
3208
                         header.version, QEMUD_SAVE_VERSION);
3209
        goto cleanup;
3210 3211
    }

3212
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
3213
        virReportOOMError(conn);
3214
        goto cleanup;
3215 3216 3217 3218
    }

    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3219
                         "%s", _("failed to read XML"));
3220
        goto cleanup;
3221 3222 3223
    }

    /* Create a domain from this XML */
3224 3225
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
3226
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3227
                         "%s", _("failed to parse XML"));
3228
        goto cleanup;
3229 3230 3231
    }

    /* Ensure the name and UUID don't already exist in an active VM */
3232
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
3233
    if (!vm)
3234
        vm = virDomainFindByName(&driver->domains, def->name);
3235 3236 3237 3238 3239 3240 3241 3242
    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);
        }
3243 3244
    }

3245 3246 3247
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
3248
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3249
                         "%s", _("failed to assign new VM"));
3250
        goto cleanup;
3251
    }
3252
    def = NULL;
3253 3254

    /* Set the migration source and start it up. */
3255
    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
3256
    close(fd);
3257
    fd = -1;
3258
    if (ret < 0) {
3259
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3260
                         "%s", _("failed to start VM"));
3261
        if (!vm->persistent) {
3262 3263
            virDomainRemoveInactive(&driver->domains,
                                    vm);
3264 3265
            vm = NULL;
        }
3266
        goto cleanup;
3267 3268
    }

3269 3270 3271
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
3272

3273 3274 3275
    /* If it was running before, resume it now. */
    if (header.was_running) {
        char *info;
3276
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
3277
            qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3278
                             "%s", _("failed to resume domain"));
3279
            goto cleanup;
3280
        }
3281
        VIR_FREE(info);
3282 3283
        vm->state = VIR_DOMAIN_RUNNING;
    }
3284
    ret = 0;
3285

3286 3287 3288 3289 3290
cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
3291 3292
    if (vm)
        virDomainObjUnlock(vm);
3293 3294
    if (event)
        qemuDomainEventQueue(driver, event);
3295
    qemuDriverUnlock(driver);
3296
    return ret;
D
Daniel P. Berrange 已提交
3297 3298 3299
}


3300
static char *qemudDomainDumpXML(virDomainPtr dom,
3301
                                int flags) {
3302 3303 3304
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;
3305 3306
    unsigned long balloon;
    int err;
3307

3308
    qemuDriverLock(driver);
3309
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3310 3311
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
3312
    if (!vm) {
3313 3314
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3315
        goto cleanup;
D
Daniel P. Berrange 已提交
3316 3317
    }

3318 3319 3320 3321 3322 3323 3324
    /* Refresh current memory based on balloon info */
    err = qemudDomainGetMemoryBalloon(dom->conn, vm, &balloon);
    if (err < 0)
        goto cleanup;
    if (err > 0)
        vm->def->memory = balloon;

3325 3326 3327 3328 3329 3330
    ret = virDomainDefFormat(dom->conn,
                             (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
                             vm->newDef : vm->def,
                             flags);

cleanup:
3331 3332
    if (vm)
        virDomainObjUnlock(vm);
3333
    return ret;
D
Daniel P. Berrange 已提交
3334 3335 3336
}


3337
static int qemudListDefinedDomains(virConnectPtr conn,
3338
                            char **const names, int nnames) {
3339
    struct qemud_driver *driver = conn->privateData;
3340
    int got = 0, i;
3341

3342
    qemuDriverLock(driver);
3343
    for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
3344
        virDomainObjLock(driver->domains.objs[i]);
3345 3346
        if (!virDomainIsActive(driver->domains.objs[i])) {
            if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) {
3347
                virReportOOMError(conn);
3348
                virDomainObjUnlock(driver->domains.objs[i]);
3349 3350
                goto cleanup;
            }
3351
        }
3352
        virDomainObjUnlock(driver->domains.objs[i]);
D
Daniel P. Berrange 已提交
3353
    }
3354

3355
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
3356
    return got;
3357 3358 3359

 cleanup:
    for (i = 0 ; i < got ; i++)
3360
        VIR_FREE(names[i]);
3361
    qemuDriverUnlock(driver);
3362
    return -1;
D
Daniel P. Berrange 已提交
3363 3364
}

3365
static int qemudNumDefinedDomains(virConnectPtr conn) {
3366
    struct qemud_driver *driver = conn->privateData;
3367 3368
    int n = 0, i;

3369
    qemuDriverLock(driver);
3370 3371
    for (i = 0 ; i < driver->domains.count ; i++)
        if (!virDomainIsActive(driver->domains.objs[i]))
3372
            n++;
3373
    qemuDriverUnlock(driver);
3374

3375
    return n;
D
Daniel P. Berrange 已提交
3376 3377 3378
}


3379
static int qemudDomainStart(virDomainPtr dom) {
3380 3381 3382
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3383
    virDomainEventPtr event = NULL;
3384

3385
    qemuDriverLock(driver);
3386
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3387 3388
    qemuDriverUnlock(driver);

3389
    if (!vm) {
3390
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
3391
                         "%s", _("no domain with matching uuid"));
3392
        goto cleanup;
3393 3394
    }

3395
    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
3396
    if (ret != -1)
3397 3398 3399
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
3400 3401

cleanup:
3402 3403
    if (vm)
        virDomainObjUnlock(vm);
3404 3405 3406 3407 3408
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
3409
    return ret;
D
Daniel P. Berrange 已提交
3410 3411 3412
}


3413
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
3414
    struct qemud_driver *driver = conn->privateData;
3415
    virDomainDefPtr def;
3416
    virDomainObjPtr vm = NULL;
3417
    virDomainPtr dom = NULL;
3418
    virDomainEventPtr event = NULL;
3419
    int newVM = 1;
3420

3421
    qemuDriverLock(driver);
3422 3423
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
3424
        goto cleanup;
3425

3426 3427 3428
    if (virSecurityDriverVerify(conn, def) < 0)
        goto cleanup;

3429
    vm = virDomainFindByName(&driver->domains, def->name);
3430 3431
    if (vm) {
        virDomainObjUnlock(vm);
3432
        newVM = 0;
3433
    }
3434

3435 3436 3437 3438
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
        virDomainDefFree(def);
3439
        goto cleanup;
3440
    }
3441
    vm->persistent = 1;
3442

3443 3444
    if (virDomainSaveConfig(conn,
                            driver->configDir,
3445
                            vm->newDef ? vm->newDef : vm->def) < 0) {
3446 3447
        virDomainRemoveInactive(&driver->domains,
                                vm);
3448
        vm = NULL;
3449
        goto cleanup;
3450 3451
    }

3452 3453 3454 3455 3456
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     newVM ?
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
3457

3458
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3459
    if (dom) dom->id = vm->def->id;
3460 3461

cleanup:
3462 3463
    if (vm)
        virDomainObjUnlock(vm);
3464 3465
    if (event)
        qemuDomainEventQueue(driver, event);
3466
    qemuDriverUnlock(driver);
3467
    return dom;
D
Daniel P. Berrange 已提交
3468 3469
}

3470
static int qemudDomainUndefine(virDomainPtr dom) {
3471 3472
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3473
    virDomainEventPtr event = NULL;
3474
    int ret = -1;
D
Daniel P. Berrange 已提交
3475

3476
    qemuDriverLock(driver);
3477
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3478

D
Daniel P. Berrange 已提交
3479
    if (!vm) {
3480 3481
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3482
        goto cleanup;
D
Daniel P. Berrange 已提交
3483 3484
    }

3485
    if (virDomainIsActive(vm)) {
3486 3487
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot delete active domain"));
3488
        goto cleanup;
D
Daniel P. Berrange 已提交
3489 3490
    }

3491 3492 3493
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot undefine transient domain"));
3494
        goto cleanup;
3495 3496 3497
    }

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

3500 3501 3502
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
3503

3504 3505
    virDomainRemoveInactive(&driver->domains,
                            vm);
3506
    vm = NULL;
3507
    ret = 0;
D
Daniel P. Berrange 已提交
3508

3509
cleanup:
3510 3511
    if (vm)
        virDomainObjUnlock(vm);
3512 3513
    if (event)
        qemuDomainEventQueue(driver, event);
3514
    qemuDriverUnlock(driver);
3515
    return ret;
D
Daniel P. Berrange 已提交
3516 3517
}

3518
/* Return the disks name for use in monitor commands */
3519
static char *qemudDiskDeviceName(const virConnectPtr conn,
3520
                                 const virDomainDiskDefPtr disk) {
3521 3522 3523 3524 3525 3526

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

    if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) {
3527
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
3528 3529 3530 3531 3532 3533 3534
                         _("cannot convert disk '%s' to bus/device index"),
                         disk->dst);
        return NULL;
    }

    switch (disk->bus) {
        case VIR_DOMAIN_DISK_BUS_IDE:
3535
            if (disk->device== VIR_DOMAIN_DISK_DEVICE_DISK)
3536
                ret = virAsprintf(&devname, "ide%d-hd%d", busid, devid);
3537
            else
3538
                ret = virAsprintf(&devname, "ide%d-cd%d", busid, devid);
3539 3540
            break;
        case VIR_DOMAIN_DISK_BUS_SCSI:
3541
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
3542
                ret = virAsprintf(&devname, "scsi%d-hd%d", busid, devid);
3543
            else
3544
                ret = virAsprintf(&devname, "scsi%d-cd%d", busid, devid);
3545 3546
            break;
        case VIR_DOMAIN_DISK_BUS_FDC:
3547
            ret = virAsprintf(&devname, "floppy%d", devid);
3548 3549
            break;
        case VIR_DOMAIN_DISK_BUS_VIRTIO:
3550
            ret = virAsprintf(&devname, "virtio%d", devid);
3551 3552
            break;
        default:
3553
            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
3554 3555 3556 3557 3558 3559
                             _("Unsupported disk name mapping for bus '%s'"),
                             virDomainDiskBusTypeToString(disk->bus));
            return NULL;
    }

    if (ret == -1) {
3560
        virReportOOMError(conn);
3561 3562 3563 3564 3565 3566
        return NULL;
    }

    return devname;
}

3567 3568
static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
                                           virDomainObjPtr vm,
3569 3570
                                           virDomainDeviceDefPtr dev)
{
3571
    virDomainDiskDefPtr origdisk = NULL, newdisk;
3572
    char *cmd, *reply, *safe_path;
3573
    char *devname = NULL;
3574
    unsigned int qemuCmdFlags;
3575
    int i;
3576

3577
    origdisk = NULL;
3578
    newdisk = dev->data.disk;
3579 3580 3581 3582
    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];
3583
            break;
3584
        }
3585 3586 3587
    }

    if (!origdisk) {
3588
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3589 3590 3591 3592 3593 3594 3595 3596 3597
                         _("No device with bus '%s' and target '%s'"),
                         virDomainDiskBusTypeToString(newdisk->bus),
                         newdisk->dst);
        return -1;
    }

    if (qemudExtractVersionInfo(vm->def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0) {
3598
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3599 3600 3601 3602 3603 3604
                         _("Cannot determine QEMU argv syntax %s"),
                         vm->def->emulator);
        return -1;
    }

    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
3605
        if (!(devname = qemudDiskDeviceName(conn, newdisk)))
3606 3607 3608 3609 3610 3611 3612 3613 3614
            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 {
3615
            qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3616 3617 3618 3619 3620 3621 3622 3623
                             _("Emulator version does not support removable "
                               "media for device '%s' and target '%s'"),
                               virDomainDiskDeviceTypeToString(newdisk->device),
                               newdisk->dst);
            return -1;
        }

        if (!devname) {
3624
            virReportOOMError(conn);
3625 3626 3627
            return -1;
        }
    }
3628

3629
    if (newdisk->src) {
3630 3631
        safe_path = qemudEscapeMonitorArg(newdisk->src);
        if (!safe_path) {
3632
            virReportOOMError(conn);
3633
            VIR_FREE(devname);
3634 3635
            return -1;
        }
3636
        if (virAsprintf(&cmd, "change %s \"%s\"", devname, safe_path) == -1) {
3637
            virReportOOMError(conn);
3638
            VIR_FREE(safe_path);
3639
            VIR_FREE(devname);
3640 3641
            return -1;
        }
3642
        VIR_FREE(safe_path);
3643

3644
    } else if (virAsprintf(&cmd, "eject %s", devname) == -1) {
3645
        virReportOOMError(conn);
3646
        VIR_FREE(devname);
3647 3648
        return -1;
    }
3649
    VIR_FREE(devname);
3650

3651
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3652
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3653
                         "%s", _("could not change cdrom media"));
3654
        VIR_FREE(cmd);
3655 3656
        return -1;
    }
3657 3658 3659 3660

    /* If the command failed qemu prints:
     * device not found, device is locked ...
     * No message is printed on success it seems */
3661
    DEBUG ("ejectable media change reply: %s", reply);
3662
    if (strstr(reply, "\ndevice ")) {
3663
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3664
                          _("changing cdrom media failed: %s"), reply);
3665 3666 3667 3668
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3669 3670
    VIR_FREE(reply);
    VIR_FREE(cmd);
3671

3672 3673
    VIR_FREE(origdisk->src);
    origdisk->src = newdisk->src;
3674
    newdisk->src = NULL;
3675
    origdisk->type = newdisk->type;
3676 3677 3678
    return 0;
}

3679 3680 3681
static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm,
                                          virDomainDeviceDefPtr dev)
3682 3683
{
    int ret, i;
3684
    char *cmd, *reply, *s;
3685 3686 3687 3688 3689
    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)) {
3690
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3691 3692 3693 3694 3695 3696
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3697
        virReportOOMError(conn);
3698 3699 3700 3701 3702
        return -1;
    }

    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3703
        virReportOOMError(conn);
3704 3705 3706
        return -1;
    }

3707 3708
    ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
                      safe_path, type);
3709 3710
    VIR_FREE(safe_path);
    if (ret == -1) {
3711
        virReportOOMError(conn);
3712 3713 3714
        return ret;
    }

3715
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3716
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3717 3718 3719 3720 3721 3722 3723 3724
                         _("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... */
3725 3726 3727 3728 3729 3730
#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)
3731
            VIR_WARN("%s", _("Unable to parse slot number\n"));
3732
    } else {
3733
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747
                          _("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;
}
3748

3749 3750 3751
static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
                                                 virDomainObjPtr vm,
                                                 virDomainDeviceDefPtr dev)
3752
{
3753 3754
    int ret, i;
    char *safe_path;
3755 3756
    char *cmd, *reply;

3757 3758
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
3759
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3760 3761 3762 3763 3764
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

3765
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3766
        virReportOOMError(conn);
3767
        return -1;
3768 3769
    }

3770 3771
    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3772
        virReportOOMError(conn);
3773 3774 3775
        return -1;
    }

3776
    ret = virAsprintf(&cmd, "usb_add disk:%s", safe_path);
3777
    VIR_FREE(safe_path);
3778
    if (ret == -1) {
3779
        virReportOOMError(conn);
3780 3781 3782
        return ret;
    }

3783
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3784
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3785
                         "%s", _("cannot attach usb disk"));
3786 3787 3788 3789 3790 3791 3792 3793
        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 ")) {
3794
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3795
                          "%s",
3796
                          _("adding usb disk failed"));
3797 3798 3799 3800
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3801

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

3806 3807 3808 3809 3810
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return 0;
}

3811 3812 3813
static int qemudDomainAttachHostDevice(virConnectPtr conn,
                                       virDomainObjPtr vm,
                                       virDomainDeviceDefPtr dev)
3814 3815 3816 3817
{
    int ret;
    char *cmd, *reply;

3818
    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
3819
        virReportOOMError(conn);
3820 3821
        return -1;
    }
3822

3823
    if (dev->data.hostdev->source.subsys.u.usb.vendor) {
3824 3825 3826
        ret = virAsprintf(&cmd, "usb_add host:%.4x:%.4x",
                          dev->data.hostdev->source.subsys.u.usb.vendor,
                          dev->data.hostdev->source.subsys.u.usb.product);
3827
    } else {
3828 3829 3830
        ret = virAsprintf(&cmd, "usb_add host:%.3d.%.3d",
                          dev->data.hostdev->source.subsys.u.usb.bus,
                          dev->data.hostdev->source.subsys.u.usb.device);
3831 3832
    }
    if (ret == -1) {
3833
        virReportOOMError(conn);
3834 3835 3836
        return -1;
    }

3837
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3838
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3839 3840 3841 3842 3843 3844 3845 3846 3847
                         "%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 ")) {
3848
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3849 3850 3851 3852 3853 3854
                          "%s",
                          _("adding usb device failed"));
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3855

3856
    vm->def->hostdevs[vm->def->nhostdevs++] = dev->data.hostdev;
3857

3858 3859
    VIR_FREE(reply);
    VIR_FREE(cmd);
3860 3861 3862
    return 0;
}

3863 3864
static int qemudDomainAttachDevice(virDomainPtr dom,
                                   const char *xml) {
3865 3866 3867 3868
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
3869

3870
    qemuDriverLock(driver);
3871
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3872
    if (!vm) {
3873
        qemuDriverUnlock(driver);
3874 3875
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3876
        goto cleanup;
3877 3878 3879
    }

    if (!virDomainIsActive(vm)) {
3880
        qemuDriverUnlock(driver);
3881 3882
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot attach device on inactive domain"));
3883
        goto cleanup;
3884 3885
    }

3886 3887
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
3888
    qemuDriverUnlock(driver);
3889 3890 3891
    if (dev == NULL)
        goto cleanup;

3892

3893 3894
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        switch (dev->data.disk->device) {
3895 3896
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
        case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
3897
            ret = qemudDomainChangeEjectableMedia(dom->conn, vm, dev);
3898
            break;
3899

3900 3901
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
3902
                ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, vm, dev);
3903 3904
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
                       dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
3905
                ret = qemudDomainAttachPciDiskDevice(dom->conn, vm, dev);
3906 3907 3908 3909 3910
            } else {
                qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                                 _("disk bus '%s' cannot be hotplugged."),
                                 virDomainDiskBusTypeToString(dev->data.disk->bus));
                goto cleanup;
3911
            }
3912
            if (driver->securityDriver)
3913
                driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
3914
            break;
3915

3916 3917
        default:
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
3918 3919
                             _("disk device type '%s' cannot be hotplugged"),
                             virDomainDiskDeviceTypeToString(dev->data.disk->device));
3920
            goto cleanup;
3921
        }
3922
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
3923 3924
               dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
               dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
3925
        ret = qemudDomainAttachHostDevice(dom->conn, vm, dev);
3926
    } else {
3927
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
3928 3929
                         _("device type '%s' cannot be attached"),
                         virDomainDeviceTypeToString(dev->type));
3930
        goto cleanup;
3931 3932
    }

3933 3934 3935
    if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        ret = -1;

3936
cleanup:
G
Guido Günther 已提交
3937 3938
    if (ret < 0)
        virDomainDeviceDefFree(dev);
3939 3940
    if (vm)
        virDomainObjUnlock(vm);
3941 3942 3943
    return ret;
}

3944 3945
static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3946 3947
{
    int i, ret = -1;
3948 3949
    char *cmd = NULL;
    char *reply = NULL;
3950 3951 3952 3953 3954 3955 3956 3957 3958 3959
    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) {
3960
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3961
                         _("disk %s not found"), dev->data.disk->dst);
3962
        goto cleanup;
3963 3964 3965
    }

    if (detach->slotnum < 1) {
3966
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3967
                         _("disk %s cannot be detached - invalid slot number %d"),
3968
                           detach->dst, detach->slotnum);
3969
        goto cleanup;
3970 3971
    }

3972
    if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
3973
        virReportOOMError(conn);
3974
        goto cleanup;
3975 3976
    }

3977
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3978
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3979
                          _("failed to execute detach disk %s command"), detach->dst);
3980
        goto cleanup;
3981 3982 3983 3984 3985 3986
    }

    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")) {
3987
        qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3988
                          _("failed to detach disk %s: invalid slot %d"),
3989 3990
                          detach->dst, detach->slotnum);
        goto cleanup;
3991 3992 3993 3994 3995
    }

    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) {
3996
            virReportOOMError(conn);
3997
            goto cleanup;
3998 3999 4000 4001 4002 4003 4004 4005
        }
        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;
4006 4007

cleanup:
4008 4009 4010 4011 4012 4013 4014
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}

static int qemudDomainDetachDevice(virDomainPtr dom,
                                   const char *xml) {
4015 4016 4017 4018
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
4019

4020
    qemuDriverLock(driver);
4021
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4022
    if (!vm) {
4023
        qemuDriverUnlock(driver);
4024 4025
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
4026
        goto cleanup;
4027 4028 4029
    }

    if (!virDomainIsActive(vm)) {
4030
        qemuDriverUnlock(driver);
4031
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
G
Guido Günther 已提交
4032
                         "%s", _("cannot detach device on inactive domain"));
4033
        goto cleanup;
4034 4035
    }

4036 4037
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
4038
    qemuDriverUnlock(driver);
4039 4040 4041
    if (dev == NULL)
        goto cleanup;

4042 4043 4044 4045

    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 ||
4046
         dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)) {
4047
        ret = qemudDomainDetachPciDiskDevice(dom->conn, vm, dev);
4048
        if (driver->securityDriver)
4049
            driver->securityDriver->domainRestoreSecurityImageLabel(dom->conn, dev->data.disk);
4050
    }
4051
    else
4052 4053 4054
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("only SCSI or virtio disk device can be detached dynamically"));

4055 4056 4057
    if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        ret = -1;

4058 4059
cleanup:
    virDomainDeviceDefFree(dev);
4060 4061
    if (vm)
        virDomainObjUnlock(vm);
4062 4063 4064
    return ret;
}

4065
static int qemudDomainGetAutostart(virDomainPtr dom,
4066
                                   int *autostart) {
4067 4068 4069
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
4070

4071
    qemuDriverLock(driver);
4072
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4073 4074
    qemuDriverUnlock(driver);

4075
    if (!vm) {
4076 4077
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
4078
        goto cleanup;
4079 4080 4081
    }

    *autostart = vm->autostart;
4082
    ret = 0;
4083

4084
cleanup:
4085 4086
    if (vm)
        virDomainObjUnlock(vm);
4087
    return ret;
4088 4089
}

4090
static int qemudDomainSetAutostart(virDomainPtr dom,
4091
                                   int autostart) {
4092 4093
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4094 4095
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
4096

4097
    qemuDriverLock(driver);
4098
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4099 4100
    qemuDriverUnlock(driver);

4101
    if (!vm) {
4102 4103
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
4104
        goto cleanup;
4105 4106
    }

4107 4108 4109
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot set autostart for transient domain"));
4110
        goto cleanup;
4111 4112
    }

4113 4114
    autostart = (autostart != 0);

4115 4116 4117 4118 4119
    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;
4120

4121 4122
        if (autostart) {
            int err;
4123

4124
            if ((err = virFileMakePath(driver->autostartDir))) {
4125 4126 4127
                virReportSystemError(dom->conn, err,
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
4128 4129
                goto cleanup;
            }
4130

4131
            if (symlink(configFile, autostartLink) < 0) {
4132 4133 4134
                virReportSystemError(dom->conn, errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
4135 4136 4137 4138
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
4139 4140 4141
                virReportSystemError(dom->conn, errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
4142 4143
                goto cleanup;
            }
4144 4145
        }

4146
        vm->autostart = autostart;
4147
    }
4148
    ret = 0;
4149

4150 4151 4152
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
4153 4154
    if (vm)
        virDomainObjUnlock(vm);
4155
    return ret;
4156 4157
}

4158 4159 4160 4161 4162 4163 4164 4165 4166
/* 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)
{
4167
    struct qemud_driver *driver = dom->conn->privateData;
4168
    char *dummy, *info = NULL;
4169
    const char *p, *eol;
4170
    const char *qemu_dev_name = NULL;
4171
    size_t len;
4172
    int i, ret = -1;
4173
    virDomainObjPtr vm;
4174
    virDomainDiskDefPtr disk = NULL;
4175

4176
    qemuDriverLock(driver);
4177
    vm = virDomainFindByID(&driver->domains, dom->id);
4178
    qemuDriverUnlock(driver);
4179 4180 4181
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4182
        goto cleanup;
4183
    }
4184
    if (!virDomainIsActive (vm)) {
4185 4186
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
4187
        goto cleanup;
4188 4189
    }

4190 4191 4192 4193 4194 4195 4196 4197
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(path, vm->def->disks[i]->dst)) {
            disk = vm->def->disks[i];
            break;
        }
    }

    if (!disk) {
4198 4199
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          _("invalid path: %s"), path);
4200
        goto cleanup;
4201 4202
    }

4203
    qemu_dev_name = qemudDiskDeviceName(dom->conn, disk);
4204
    if (!qemu_dev_name)
4205
        goto cleanup;
4206 4207
    len = strlen (qemu_dev_name);

4208
    if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) {
4209 4210
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("'info blockstats' command failed"));
4211
        goto cleanup;
4212 4213 4214 4215 4216 4217 4218 4219
    }
    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 已提交
4220
    if (strstr(info, "\ninfo ")) {
4221 4222 4223
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s",
                          _("'info blockstats' not supported by this qemu"));
4224
        goto cleanup;
4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250
    }

    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) {
4251
                if (STRPREFIX (p, "rd_bytes=")) {
4252 4253 4254
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1)
                        DEBUG ("error reading rd_bytes: %s", p);
4255
                } else if (STRPREFIX (p, "wr_bytes=")) {
4256 4257 4258
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1)
                        DEBUG ("error reading wr_bytes: %s", p);
4259
                } else if (STRPREFIX (p, "rd_operations=")) {
4260 4261 4262
                    p += 14;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1)
                        DEBUG ("error reading rd_req: %s", p);
4263
                } else if (STRPREFIX (p, "wr_operations=")) {
4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274
                    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++;
            }
4275
            ret = 0;
4276
            goto cleanup;
4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287
        }

        /* 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);
4288
 cleanup:
4289 4290
    VIR_FREE(qemu_dev_name);
    VIR_FREE(info);
4291 4292
    if (vm)
        virDomainObjUnlock(vm);
4293
    return ret;
4294 4295
}

4296
#ifdef __linux__
4297 4298 4299 4300 4301
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path,
                           struct _virDomainInterfaceStats *stats)
{
4302 4303
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4304
    int i;
4305
    int ret = -1;
4306

4307
    qemuDriverLock(driver);
4308
    vm = virDomainFindByID(&driver->domains, dom->id);
4309 4310
    qemuDriverUnlock(driver);

4311 4312
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
4313
                          _("no domain with matching id %d"), dom->id);
4314
        goto cleanup;
4315 4316
    }

4317
    if (!virDomainIsActive(vm)) {
4318
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
4319
                         "%s", _("domain is not running"));
4320
        goto cleanup;
4321 4322 4323 4324
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
4325
                         "%s", _("NULL or empty path"));
4326
        goto cleanup;
4327 4328 4329
    }

    /* Check the path is one of the domain's network interfaces. */
4330 4331
    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (vm->def->nets[i]->ifname &&
4332 4333 4334 4335
            STREQ (vm->def->nets[i]->ifname, path)) {
            ret = 0;
            break;
        }
4336 4337
    }

4338 4339 4340 4341 4342
    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);
4343

4344
cleanup:
4345 4346
    if (vm)
        virDomainObjUnlock(vm);
4347 4348
    return ret;
}
4349
#else
4350 4351 4352 4353
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path ATTRIBUTE_UNUSED,
                           struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
4354 4355 4356 4357
    qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                      "%s", __FUNCTION__);
    return -1;
}
4358
#endif
4359

4360 4361 4362 4363 4364 4365 4366
static int
qemudDomainBlockPeek (virDomainPtr dom,
                      const char *path,
                      unsigned long long offset, size_t size,
                      void *buffer,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
4367 4368 4369
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int fd = -1, ret = -1, i;
4370

4371
    qemuDriverLock(driver);
4372
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4373 4374
    qemuDriverUnlock(driver);

4375 4376
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
4377
                          "%s", _("no domain with matching uuid"));
4378
        goto cleanup;
4379 4380 4381 4382
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
4383
                         "%s", _("NULL or empty path"));
4384
        goto cleanup;
4385 4386 4387
    }

    /* Check the path belongs to this domain. */
4388 4389
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (vm->def->disks[i]->src != NULL &&
4390 4391 4392 4393
            STREQ (vm->def->disks[i]->src, path)) {
            ret = 0;
            break;
        }
4394 4395
    }

4396 4397 4398 4399 4400
    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) {
4401 4402
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to open"), path);
4403 4404
            goto cleanup;
        }
4405

4406 4407 4408 4409 4410 4411
        /* 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) {
4412 4413
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to seek or read"), path);
4414 4415 4416 4417 4418 4419 4420
            goto cleanup;
        }

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

4423 4424 4425
cleanup:
    if (fd >= 0)
        close (fd);
4426 4427
    if (vm)
        virDomainObjUnlock(vm);
4428 4429 4430
    return ret;
}

R
Richard W.M. Jones 已提交
4431 4432 4433 4434 4435 4436
static int
qemudDomainMemoryPeek (virDomainPtr dom,
                       unsigned long long offset, size_t size,
                       void *buffer,
                       unsigned int flags)
{
4437 4438 4439
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char cmd[256], *info = NULL;
R
Richard W.M. Jones 已提交
4440 4441 4442
    char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
    int fd = -1, ret = -1;

4443
    qemuDriverLock(driver);
4444
    vm = virDomainFindByID(&driver->domains, dom->id);
4445
    qemuDriverUnlock(driver);
R
Richard W.M. Jones 已提交
4446 4447 4448 4449

    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4450 4451 4452 4453 4454 4455 4456
        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 已提交
4457 4458
    }

4459
    if (!virDomainIsActive(vm)) {
R
Richard W.M. Jones 已提交
4460 4461
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
4462
        goto cleanup;
R
Richard W.M. Jones 已提交
4463 4464 4465 4466
    }

    /* Create a temporary filename. */
    if ((fd = mkstemp (tmp)) == -1) {
4467 4468
        virReportSystemError (dom->conn, errno,
                              _("mkstemp(\"%s\") failed"), tmp);
4469
        goto cleanup;
R
Richard W.M. Jones 已提交
4470 4471 4472 4473
    }

    /* Issue the memsave command. */
    snprintf (cmd, sizeof cmd, "memsave %llu %zi \"%s\"", offset, size, tmp);
4474
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
R
Richard W.M. Jones 已提交
4475
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
4476
                          "%s", _("'memsave' command failed"));
4477
        goto cleanup;
R
Richard W.M. Jones 已提交
4478 4479 4480 4481 4482 4483
    }

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

    /* Read the memory file into buffer. */
    if (saferead (fd, buffer, size) == (ssize_t) -1) {
4484 4485 4486
        virReportSystemError (dom->conn, errno,
                              _("failed to read temporary file "
                                "created with template %s"), tmp);
4487
        goto cleanup;
R
Richard W.M. Jones 已提交
4488 4489 4490
    }

    ret = 0;
4491 4492 4493

cleanup:
    VIR_FREE(info);
R
Richard W.M. Jones 已提交
4494 4495
    if (fd >= 0) close (fd);
    unlink (tmp);
4496 4497
    if (vm)
        virDomainObjUnlock(vm);
R
Richard W.M. Jones 已提交
4498 4499 4500
    return ret;
}

4501

4502 4503
static int
qemudDomainEventRegister (virConnectPtr conn,
4504
                          virConnectDomainEventCallback callback,
4505 4506
                          void *opaque,
                          virFreeCallback freecb)
4507
{
4508 4509 4510
    struct qemud_driver *driver = conn->privateData;
    int ret;

4511
    qemuDriverLock(driver);
4512 4513
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
4514
    qemuDriverUnlock(driver);
4515

4516
    return ret;
4517 4518 4519 4520
}

static int
qemudDomainEventDeregister (virConnectPtr conn,
4521
                            virConnectDomainEventCallback callback)
4522
{
4523 4524 4525
    struct qemud_driver *driver = conn->privateData;
    int ret;

4526
    qemuDriverLock(driver);
4527 4528 4529 4530 4531 4532
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
4533
    qemuDriverUnlock(driver);
4534

4535
    return ret;
4536 4537
}

4538 4539 4540 4541 4542
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
                                        virConnectDomainEventCallback cb,
                                        void *cbopaque,
                                        void *opaque)
4543
{
4544
    struct qemud_driver *driver = opaque;
4545

4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589
    /* 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);
4590 4591
}

D
Daniel Veillard 已提交
4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609
/* 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;
4610 4611
    struct qemud_driver *driver = dconn->privateData;
    virDomainDefPtr def = NULL;
D
Daniel Veillard 已提交
4612 4613 4614 4615 4616
    virDomainObjPtr vm = NULL;
    int this_port;
    char hostname [HOST_NAME_MAX+1];
    char migrateFrom [64];
    const char *p;
4617
    virDomainEventPtr event = NULL;
4618 4619 4620
    int ret = -1;;

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

4622
    qemuDriverLock(driver);
D
Daniel Veillard 已提交
4623 4624 4625
    if (!dom_xml) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          "%s", _("no domain XML passed"));
4626
        goto cleanup;
D
Daniel Veillard 已提交
4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644
    }

    /* 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) {
4645 4646
            virReportSystemError (dconn, errno,
                                  "%s", _("failed to determine host name"));
4647
            goto cleanup;
D
Daniel Veillard 已提交
4648 4649 4650
        }

        /* Caller frees */
4651
        if (virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) {
4652
            virReportOOMError (dconn);
4653
            goto cleanup;
D
Daniel Veillard 已提交
4654 4655 4656 4657 4658 4659
        }
    } 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.
         */
4660
        if (!STRPREFIX (uri_in, "tcp:")) {
D
Daniel Veillard 已提交
4661 4662
            qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG,
                  "%s", _("only tcp URIs are supported for KVM migrations"));
4663
            goto cleanup;
D
Daniel Veillard 已提交
4664 4665 4666 4667 4668 4669 4670 4671 4672
        }

        /* 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"));
4673
            goto cleanup;
D
Daniel Veillard 已提交
4674 4675 4676 4677
        }
    }

    /* Parse the domain XML. */
4678 4679
    if (!(def = virDomainDefParseString(dconn, driver->caps, dom_xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
D
Daniel Veillard 已提交
4680 4681
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to parse XML"));
4682
        goto cleanup;
D
Daniel Veillard 已提交
4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698
    }

    /* 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"));
4699
        goto cleanup;
D
Daniel Veillard 已提交
4700 4701 4702 4703 4704 4705 4706 4707 4708
    }
#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);
4709
            goto cleanup;
D
Daniel Veillard 已提交
4710 4711 4712 4713 4714 4715 4716 4717
        }
    }

    if (!(vm = virDomainAssignDef(dconn,
                                  &driver->domains,
                                  def))) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to assign new VM"));
4718
        goto cleanup;
D
Daniel Veillard 已提交
4719
    }
4720
    def = NULL;
D
Daniel Veillard 已提交
4721 4722 4723 4724 4725 4726 4727 4728

    /* 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);
4729
    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
D
Daniel Veillard 已提交
4730 4731
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to start listening VM"));
4732
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4733
            virDomainRemoveInactive(&driver->domains, vm);
4734 4735
            vm = NULL;
        }
4736
        goto cleanup;
D
Daniel Veillard 已提交
4737
    }
4738 4739 4740 4741

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

4744 4745 4746 4747 4748
cleanup:
    virDomainDefFree(def);
    if (ret != 0) {
        VIR_FREE(*uri_out);
    }
4749 4750
    if (vm)
        virDomainObjUnlock(vm);
4751 4752
    if (event)
        qemuDomainEventQueue(driver, event);
4753
    qemuDriverUnlock(driver);
4754
    return ret;
D
Daniel Veillard 已提交
4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766
}

/* 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)
{
4767 4768
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4769
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4770 4771
    char *safe_uri;
    char cmd[HOST_NAME_MAX+50];
4772 4773
    char *info = NULL;
    int ret = -1;
4774
    int paused = 0;
D
Daniel Veillard 已提交
4775

4776
    qemuDriverLock(driver);
4777
    vm = virDomainFindByID(&driver->domains, dom->id);
D
Daniel Veillard 已提交
4778 4779 4780
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4781
        goto cleanup;
D
Daniel Veillard 已提交
4782 4783 4784 4785 4786
    }

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

4790 4791
    if (!(flags & VIR_MIGRATE_LIVE)) {
        /* Pause domain for non-live migration */
4792 4793 4794 4795 4796
        if (qemudMonitorCommand (vm, "stop", &info) < 0) {
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("off-line migration specified, but suspend operation failed"));
            goto cleanup;
        }
4797 4798
        DEBUG ("stop reply: %s", info);
        VIR_FREE(info);
4799
        paused = 1;
4800

4801 4802 4803 4804 4805 4806
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
        event = NULL;
4807 4808
    }

D
Daniel Veillard 已提交
4809 4810 4811
    if (resource > 0) {
        /* Issue migrate_set_speed command.  Don't worry if it fails. */
        snprintf (cmd, sizeof cmd, "migrate_set_speed %lum", resource);
4812
        qemudMonitorCommand (vm, cmd, &info);
D
Daniel Veillard 已提交
4813 4814 4815 4816 4817 4818 4819 4820

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

    /* Issue the migrate command. */
    safe_uri = qemudEscapeMonitorArg (uri);
    if (!safe_uri) {
4821
        virReportOOMError (dom->conn);
4822
        goto cleanup;
D
Daniel Veillard 已提交
4823 4824 4825 4826
    }
    snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri);
    VIR_FREE (safe_uri);

4827
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
D
Daniel Veillard 已提交
4828 4829
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("migrate operation failed"));
4830
        goto cleanup;
D
Daniel Veillard 已提交
4831 4832 4833 4834 4835 4836 4837 4838
    }

    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);
4839
        goto cleanup;
D
Daniel Veillard 已提交
4840 4841 4842 4843
    }

    /* Clean up the source domain. */
    qemudShutdownVMDaemon (dom->conn, driver, vm);
4844
    paused = 0;
4845 4846 4847 4848

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
4849
    if (!vm->persistent) {
D
Daniel Veillard 已提交
4850
        virDomainRemoveInactive(&driver->domains, vm);
4851 4852
        vm = NULL;
    }
4853
    ret = 0;
D
Daniel Veillard 已提交
4854

4855
cleanup:
4856 4857 4858
    /* Note that we have to free info *first*, since we are re-using the
     * variable below (and otherwise might cause a memory leak)
     */
4859
    VIR_FREE(info);
4860 4861 4862 4863 4864 4865 4866 4867

    if (paused) {
        /* we got here through some sort of failure; start the domain again */
        if (qemudMonitorCommand (vm, "cont", &info) < 0) {
            /* Hm, we already know we are in error here.  We don't want to
             * overwrite the previous error, though, so we just throw something
             * to the logs and hope for the best
             */
4868 4869
            VIR_ERROR(_("Failed to resume guest %s after failure\n"),
                      vm->def->name);
4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880
        }
        else {
            DEBUG ("cont reply: %s", info);
            VIR_FREE(info);
        }

        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
    }

4881 4882
    if (vm)
        virDomainObjUnlock(vm);
4883 4884
    if (event)
        qemuDomainEventQueue(driver, event);
4885
    qemuDriverUnlock(driver);
4886
    return ret;
D
Daniel Veillard 已提交
4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898
}

/* 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)
{
4899 4900 4901
    struct qemud_driver *driver = dconn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
4902
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4903 4904
    char *info = NULL;

4905
    qemuDriverLock(driver);
4906
    vm = virDomainFindByName(&driver->domains, dname);
D
Daniel Veillard 已提交
4907 4908 4909
    if (!vm) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching name %s"), dname);
4910
        goto cleanup;
D
Daniel Veillard 已提交
4911 4912 4913 4914 4915 4916 4917 4918 4919
    }

    /* 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;
4920 4921 4922
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
D
Daniel Veillard 已提交
4923 4924
    } else {
        qemudShutdownVMDaemon (dconn, driver, vm);
4925 4926 4927
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
4928
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4929
            virDomainRemoveInactive(&driver->domains, vm);
4930 4931
            vm = NULL;
        }
D
Daniel Veillard 已提交
4932
    }
4933 4934

cleanup:
4935 4936
    if (vm)
        virDomainObjUnlock(vm);
4937 4938
    if (event)
        qemuDomainEventQueue(driver, event);
4939
    qemuDriverUnlock(driver);
4940
    return dom;
D
Daniel Veillard 已提交
4941 4942
}

4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057
static int
qemudNodeDeviceGetPciInfo (virNodeDevicePtr dev,
                           unsigned *domain,
                           unsigned *bus,
                           unsigned *slot,
                           unsigned *function)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

    xml = virNodeDeviceGetXMLDesc(dev, 0);
    if (!xml)
        goto out;

    def = virNodeDeviceDefParseString(dev->conn, xml);
    if (!def)
        goto out;

    cap = def->caps;
    while (cap) {
        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
            *domain   = cap->data.pci_dev.domain;
            *bus      = cap->data.pci_dev.bus;
            *slot     = cap->data.pci_dev.slot;
            *function = cap->data.pci_dev.function;
            break;
        }

        cap = cap->next;
    }

    if (!cap) {
        qemudReportError(dev->conn, NULL, NULL, VIR_ERR_INVALID_ARG,
                         _("device %s is not a PCI device"), dev->name);
        goto out;
    }

    ret = 0;
out:
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
qemudNodeDeviceDettach (virNodeDevicePtr dev)
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (qemudNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
    if (!pci)
        return -1;

    if (pciDettachDevice(dev->conn, pci) < 0)
        goto out;

    ret = 0;
out:
    pciFreeDevice(dev->conn, pci);
    return ret;
}

static int
qemudNodeDeviceReAttach (virNodeDevicePtr dev)
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (qemudNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
    if (!pci)
        return -1;

    if (pciReAttachDevice(dev->conn, pci) < 0)
        goto out;

    ret = 0;
out:
    pciFreeDevice(dev->conn, pci);
    return ret;
}

static int
qemudNodeDeviceReset (virNodeDevicePtr dev)
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (qemudNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
    if (!pci)
        return -1;

    if (pciResetDevice(dev->conn, pci) < 0)
        goto out;

    ret = 0;
out:
    pciFreeDevice(dev->conn, pci);
    return ret;
}

5058 5059 5060 5061 5062
static virDriver qemuDriver = {
    VIR_DRV_QEMU,
    "QEMU",
    qemudOpen, /* open */
    qemudClose, /* close */
D
Daniel Veillard 已提交
5063
    qemudSupportsFeature, /* supports_feature */
5064 5065
    qemudGetType, /* type */
    qemudGetVersion, /* version */
5066
    qemudGetHostname, /* getHostname */
5067 5068 5069 5070 5071
    qemudGetMaxVCPUs, /* getMaxVcpus */
    qemudGetNodeInfo, /* nodeGetInfo */
    qemudGetCapabilities, /* getCapabilities */
    qemudListDomains, /* listDomains */
    qemudNumDomains, /* numOfDomains */
5072
    qemudDomainCreate, /* domainCreateXML */
5073 5074 5075 5076 5077
    qemudDomainLookupByID, /* domainLookupByID */
    qemudDomainLookupByUUID, /* domainLookupByUUID */
    qemudDomainLookupByName, /* domainLookupByName */
    qemudDomainSuspend, /* domainSuspend */
    qemudDomainResume, /* domainResume */
5078
    qemudDomainShutdown, /* domainShutdown */
5079 5080 5081
    NULL, /* domainReboot */
    qemudDomainDestroy, /* domainDestroy */
    qemudDomainGetOSType, /* domainGetOSType */
5082 5083 5084
    qemudDomainGetMaxMemory, /* domainGetMaxMemory */
    qemudDomainSetMaxMemory, /* domainSetMaxMemory */
    qemudDomainSetMemory, /* domainSetMemory */
5085 5086 5087 5088
    qemudDomainGetInfo, /* domainGetInfo */
    qemudDomainSave, /* domainSave */
    qemudDomainRestore, /* domainRestore */
    NULL, /* domainCoreDump */
5089
    qemudDomainSetVcpus, /* domainSetVcpus */
5090 5091 5092 5093
#if HAVE_SCHED_GETAFFINITY
    qemudDomainPinVcpu, /* domainPinVcpu */
    qemudDomainGetVcpus, /* domainGetVcpus */
#else
5094 5095
    NULL, /* domainPinVcpu */
    NULL, /* domainGetVcpus */
5096
#endif
5097
    qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
5098 5099
    qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */
    qemudNodeGetSecurityModel, /* nodeGetSecurityModel */
5100
    qemudDomainDumpXML, /* domainDumpXML */
5101 5102
    qemudListDefinedDomains, /* listDefinedDomains */
    qemudNumDefinedDomains, /* numOfDefinedDomains */
5103 5104 5105
    qemudDomainStart, /* domainCreate */
    qemudDomainDefine, /* domainDefineXML */
    qemudDomainUndefine, /* domainUndefine */
5106
    qemudDomainAttachDevice, /* domainAttachDevice */
5107
    qemudDomainDetachDevice, /* domainDetachDevice */
5108 5109 5110 5111 5112
    qemudDomainGetAutostart, /* domainGetAutostart */
    qemudDomainSetAutostart, /* domainSetAutostart */
    NULL, /* domainGetSchedulerType */
    NULL, /* domainGetSchedulerParameters */
    NULL, /* domainSetSchedulerParameters */
D
Daniel Veillard 已提交
5113 5114
    NULL, /* domainMigratePrepare (v1) */
    qemudDomainMigratePerform, /* domainMigratePerform */
5115
    NULL, /* domainMigrateFinish */
5116
    qemudDomainBlockStats, /* domainBlockStats */
5117
    qemudDomainInterfaceStats, /* domainInterfaceStats */
5118
    qemudDomainBlockPeek, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
5119
    qemudDomainMemoryPeek, /* domainMemoryPeek */
5120 5121 5122 5123
#if HAVE_NUMACTL
    qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    qemudNodeGetFreeMemory,  /* getFreeMemory */
#else
5124
    NULL, /* nodeGetCellsFreeMemory */
5125
    NULL, /* getFreeMemory */
5126
#endif
5127 5128
    qemudDomainEventRegister, /* domainEventRegister */
    qemudDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
5129 5130
    qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
    qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
5131 5132 5133
    qemudNodeDeviceDettach, /* nodeDeviceDettach */
    qemudNodeDeviceReAttach, /* nodeDeviceReAttach */
    qemudNodeDeviceReset, /* nodeDeviceReset */
5134 5135 5136
};


5137
static virStateDriver qemuStateDriver = {
5138 5139 5140 5141
    .initialize = qemudStartup,
    .cleanup = qemudShutdown,
    .reload = qemudReload,
    .active = qemudActive,
5142
};
5143

5144
int qemuRegister(void) {
5145 5146 5147 5148
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}