qemu_driver.c 148.5 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

J
Jim Meyering 已提交
126
static struct qemud_driver *qemu_driver = NULL;
127 128


129 130 131 132 133 134
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 已提交
135
    int ret, fd = -1;
136

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


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


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

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

    virConnectClose(conn);
239 240
}

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257

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


278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
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) {
309 310
            VIR_ERROR(_("Failed to read domain status for %s\n"),
                      vm->def->name);
311 312 313 314 315 316 317 318
            goto next_error;
        }

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

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

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

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

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

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

356 357 358 359 360 361 362 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
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;
}
407

408 409 410 411 412 413 414
/**
 * qemudStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
qemudStartup(void) {
415 416
    uid_t uid = geteuid();
    char *base = NULL;
D
Daniel P. Berrange 已提交
417
    char driverConf[PATH_MAX];
418

419
    if (VIR_ALLOC(qemu_driver) < 0)
420 421
        return -1;

422
    if (virMutexInit(&qemu_driver->lock) < 0) {
423
        VIR_ERROR("%s", _("cannot initialize mutex"));
424 425 426
        VIR_FREE(qemu_driver);
        return -1;
    }
427 428
    qemuDriverLock(qemu_driver);

429 430 431
    /* Don't have a dom0 so start from 1 */
    qemu_driver->nextvmid = 1;

432 433
    /* Init callback list */
    if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
434
        goto out_of_memory;
435 436 437 438 439 440
    if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew()))
        goto out_of_memory;

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

442
    if (!uid) {
443 444
        if (virAsprintf(&qemu_driver->logDir,
                        "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
445
            goto out_of_memory;
446

D
Daniel P. Berrange 已提交
447
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
448
            goto out_of_memory;
449 450 451 452

        if (virAsprintf(&qemu_driver->stateDir,
                      "%s/run/libvirt/qemu/", LOCAL_STATE_DIR) == -1)
            goto out_of_memory;
453
    } else {
454 455
        char *userdir = virGetUserDirectory(NULL, uid);
        if (!userdir)
456
            goto error;
457

458
        if (virAsprintf(&qemu_driver->logDir,
459 460
                        "%s/.libvirt/qemu/log", userdir) == -1) {
            VIR_FREE(userdir);
461
            goto out_of_memory;
462
        }
463

464 465
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
            VIR_FREE(userdir);
466
            goto out_of_memory;
467 468
        }
        VIR_FREE(userdir);
469 470 471 472 473 474

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

    if (virFileMakePath(qemu_driver->stateDir) < 0) {
475
        char ebuf[1024];
476 477
        VIR_ERROR(_("Failed to create state dir '%s': %s\n"),
                  qemu_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
478
        goto error;
479 480 481 482 483
    }

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

488
    if (virAsprintf(&qemu_driver->configDir, "%s/qemu", base) == -1)
489 490
        goto out_of_memory;

491
    if (virAsprintf(&qemu_driver->autostartDir, "%s/qemu/autostart", base) == -1)
492 493
        goto out_of_memory;

494
    VIR_FREE(base);
495 496 497

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

499 500 501 502
    if (qemudSecurityInit(qemu_driver) < 0) {
        goto error;
    }

D
Daniel P. Berrange 已提交
503
    if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
504
        goto error;
D
Daniel P. Berrange 已提交
505 506
    }

507 508 509 510
    if (virDomainLoadAllConfigs(NULL,
                                qemu_driver->caps,
                                &qemu_driver->domains,
                                qemu_driver->configDir,
511
                                qemu_driver->autostartDir,
512 513
                                NULL, NULL) < 0)
        goto error;
514
    qemudReconnectVMs(qemu_driver);
515 516
    qemudAutostartConfigs(qemu_driver);

517 518
    qemuDriverUnlock(qemu_driver);

519 520
    return 0;

521
out_of_memory:
522
    virReportOOMError(NULL);
523 524 525
error:
    if (qemu_driver)
        qemuDriverUnlock(qemu_driver);
526
    VIR_FREE(base);
527
    qemudShutdown();
528 529 530
    return -1;
}

531 532 533 534
static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
{
    struct qemud_driver *driver = opaque;

535 536 537 538 539 540 541 542
    if (newVM) {
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }
543 544
}

545 546 547 548 549 550 551 552
/**
 * qemudReload:
 *
 * Function to restart the QEmu daemon, it will recheck the configuration
 * files and update its state and the networking
 */
static int
qemudReload(void) {
553 554 555
    if (!qemu_driver)
        return 0;

556
    qemuDriverLock(qemu_driver);
557 558 559 560
    virDomainLoadAllConfigs(NULL,
                            qemu_driver->caps,
                            &qemu_driver->domains,
                            qemu_driver->configDir,
561 562
                            qemu_driver->autostartDir,
                            qemudNotifyLoadDomain, qemu_driver);
563

564
    qemudAutostartConfigs(qemu_driver);
565
    qemuDriverUnlock(qemu_driver);
566 567

    return 0;
568 569
}

570 571 572 573 574 575 576 577 578 579
/**
 * 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) {
580
    unsigned int i;
581
    int active = 0;
582

583 584 585
    if (!qemu_driver)
        return 0;

586 587 588 589 590 591 592 593
    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);
    }
594

595 596
    qemuDriverUnlock(qemu_driver);
    return active;
597 598
}

599 600 601 602 603 604 605
/**
 * qemudShutdown:
 *
 * Shutdown the QEmu daemon, it will stop all active domains and networks
 */
static int
qemudShutdown(void) {
606

607
    if (!qemu_driver)
608
        return -1;
609

610
    qemuDriverLock(qemu_driver);
611 612
    virCapabilitiesFree(qemu_driver->caps);

613
    virDomainObjListFree(&qemu_driver->domains);
614

615
    VIR_FREE(qemu_driver->securityDriverName);
616
    VIR_FREE(qemu_driver->logDir);
617 618
    VIR_FREE(qemu_driver->configDir);
    VIR_FREE(qemu_driver->autostartDir);
619
    VIR_FREE(qemu_driver->stateDir);
620
    VIR_FREE(qemu_driver->vncTLSx509certdir);
J
Jim Meyering 已提交
621
    VIR_FREE(qemu_driver->vncListen);
622
    VIR_FREE(qemu_driver->vncPassword);
D
Daniel P. Berrange 已提交
623

624 625
    /* Free domain callback list */
    virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
626 627 628 629
    virDomainEventQueueFree(qemu_driver->domainEventQueue);

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

631 632 633
    if (qemu_driver->brctl)
        brShutdown(qemu_driver->brctl);

634
    qemuDriverUnlock(qemu_driver);
635
    virMutexDestroy(&qemu_driver->lock);
636
    VIR_FREE(qemu_driver);
637 638

    return 0;
639 640 641
}

/* Return -1 for error, 1 to continue reading and 0 for success */
642
typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
643
                                      virDomainObjPtr vm,
644 645 646
                                      const char *output,
                                      int fd);

647 648 649
/*
 * Returns -1 for error, 0 on end-of-file, 1 for success
 */
650
static int
651
qemudReadMonitorOutput(virConnectPtr conn,
652
                       virDomainObjPtr vm,
653 654
                       int fd,
                       char *buf,
G
Guido Günther 已提交
655
                       size_t buflen,
656
                       qemudHandlerMonitorOutput func,
657 658
                       const char *what,
                       int timeout)
659
{
G
Guido Günther 已提交
660
    size_t got = 0;
661
    buf[0] = '\0';
662
    timeout *= 1000; /* poll wants milli seconds */
663

664
    /* Consume & discard the initial greeting */
665
    while (got < (buflen-1)) {
G
Guido Günther 已提交
666
        ssize_t ret;
667 668

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

670 671 672 673 674 675
        if (ret < 0) {
            struct pollfd pfd = { .fd = fd, .events = POLLIN };
            if (errno == EINTR)
                continue;

            if (errno != EAGAIN) {
676 677 678
                virReportSystemError(conn, errno,
                                     _("Failure while reading %s startup output"),
                                     what);
679 680 681
                return -1;
            }

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

700
                qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
701
                                 _("Failure while reading %s startup output"), what);
702 703
                return -1;
            }
704 705
        } else if (ret == 0) {
            return 0;
706 707 708
        } else {
            got += ret;
            buf[got] = '\0';
709 710 711 712 713 714
            ret = func(conn, vm, buf, fd);
            if (ret == -1)
                return -1;
            if (ret == 1)
                continue;
            return 1;
715 716 717
        }
    }

718
    qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
719
                     _("Out of space while reading %s startup output"), what);
720 721 722 723
    return -1;

}

724 725 726 727 728 729 730 731 732

/*
 * Returns -1 for error, 0 on success
 */
static int
qemudReadLogOutput(virConnectPtr conn,
                   virDomainObjPtr vm,
                   int fd,
                   char *buf,
G
Guido Günther 已提交
733
                   size_t buflen,
734 735 736 737 738 739 740 741
                   qemudHandlerMonitorOutput func,
                   const char *what,
                   int timeout)
{
    int retries = timeout*10;
    buf[0] = '\0';

    while (retries) {
G
Guido Günther 已提交
742 743 744
        ssize_t ret;
        size_t got = 0;

745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774
        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;
}

775
static int
776
qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
777
                        virDomainObjPtr vm,
778 779 780 781 782 783 784 785 786 787 788
                        const char *output,
                        int fd)
{
    if (strstr(output, "(qemu) ") == NULL)
        return 1; /* keep reading */

    vm->monitor = fd;

    return 0;
}

789
static int qemudOpenMonitor(virConnectPtr conn,
790
                            struct qemud_driver* driver,
791
                            virDomainObjPtr vm,
792 793
                            const char *monitor,
                            int reconnect) {
794 795 796 797
    int monfd;
    char buf[1024];
    int ret = -1;

D
Daniel Veillard 已提交
798
    if ((monfd = open(monitor, O_RDWR)) < 0) {
799
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
800
                         _("Unable to open monitor path %s"), monitor);
801 802
        return -1;
    }
803
    if (virSetCloseExec(monfd) < 0) {
804
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
805
                         "%s", _("Unable to set monitor close-on-exec flag"));
806 807
        goto error;
    }
808
    if (virSetNonBlock(monfd) < 0) {
809
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
810
                         "%s", _("Unable to put monitor into non-blocking mode"));
811 812 813
        goto error;
    }

814
    if (!reconnect) {
815 816 817 818
        if (qemudReadMonitorOutput(conn,
                                   vm, monfd,
                                   buf, sizeof(buf),
                                   qemudCheckMonitorPrompt,
819
                                   "monitor", 10) <= 0)
820 821 822
            ret = -1;
        else
            ret = 0;
823 824 825 826 827 828 829
    } else {
        vm->monitor = monfd;
        ret = 0;
    }

    if (ret != 0)
         goto error;
830

831
    if (!(vm->monitorpath = strdup(monitor))) {
832
        virReportOOMError(conn);
833 834 835
        goto error;
    }

836 837 838
    if ((vm->monitorWatch = virEventAddHandle(vm->monitor, 0,
                                              qemudDispatchVMEvent,
                                              driver, NULL)) < 0)
839 840 841
        goto error;


842 843 844 845
    /* Keep monitor open upon success */
    if (ret == 0)
        return ret;

846 847 848 849 850
 error:
    close(monfd);
    return ret;
}

851
/* Returns -1 for error, 0 success, 1 continue reading */
852 853
static int qemudExtractMonitorPath(virConnectPtr conn,
                                   const char *haystack,
854
                                   size_t *offset,
855
                                   char **path) {
856
    static const char needle[] = "char device redirected to";
857
    char *tmp, *dev;
858

859
    VIR_FREE(*path);
860
    /* First look for our magic string */
861 862 863 864 865
    if (!(tmp = strstr(haystack + *offset, needle))) {
        return 1;
    }
    tmp += sizeof(needle);
    dev = tmp;
866

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

    /*
     * We found a path, but didn't find any whitespace,
     * so it must be still incomplete - we should at
889 890
     * least see a \n - indicate that we want to carry
     * on trying again
891
     */
892
    return 1;
893 894 895
}

static int
896
qemudFindCharDevicePTYs(virConnectPtr conn,
897
                        virDomainObjPtr vm,
898 899
                        const char *output,
                        int fd ATTRIBUTE_UNUSED)
900
{
901
    struct qemud_driver* driver = conn->privateData;
902
    char *monitor = NULL;
903
    size_t offset = 0;
904
    int ret, i;
905 906 907 908 909

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

911
    /* So first comes the monitor device */
912 913
    if ((ret = qemudExtractMonitorPath(conn, output, &offset, &monitor)) != 0)
        goto cleanup;
914

915
    /* then the serial devices */
916 917
    for (i = 0 ; i < vm->def->nserials ; i++) {
        virDomainChrDefPtr chr = vm->def->serials[i];
918 919 920 921
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
922 923 924 925
        }
    }

    /* and finally the parallel devices */
926 927
    for (i = 0 ; i < vm->def->nparallels ; i++) {
        virDomainChrDefPtr chr = vm->def->parallels[i];
928 929 930 931
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
932 933 934 935
        }
    }

    /* Got them all, so now open the monitor console */
936
    ret = qemudOpenMonitor(conn, driver, vm, monitor, 0);
937 938 939 940

cleanup:
    VIR_FREE(monitor);
    return ret;
941 942
}

943
static int qemudWaitForMonitor(virConnectPtr conn,
944 945 946
                               struct qemud_driver* driver,
                               virDomainObjPtr vm, off_t pos)
{
947
    char buf[1024]; /* Plenty of space to get startup greeting */
948 949 950 951 952
    int logfd;
    int ret;

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

955 956 957
    ret = qemudReadLogOutput(conn, vm, logfd, buf, sizeof(buf),
                             qemudFindCharDevicePTYs,
                             "console", 3);
958 959
    if (close(logfd) < 0) {
        char ebuf[1024];
960
        VIR_WARN(_("Unable to close logfile: %s\n"),
961 962
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
963

964
    if (ret == 0) /* success */
965 966 967 968 969 970
        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;
971 972
}

973 974
static int
qemudDetectVcpuPIDs(virConnectPtr conn,
975
                    virDomainObjPtr vm) {
976 977 978 979 980 981
    char *qemucpus = NULL;
    char *line;
    int lastVcpu = -1;

    /* Only KVM has seperate threads for CPUs,
       others just use main QEMU process for CPU */
982
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM)
983 984 985 986 987
        vm->nvcpupids = 1;
    else
        vm->nvcpupids = vm->def->vcpus;

    if (VIR_ALLOC_N(vm->vcpupids, vm->nvcpupids) < 0) {
988
        virReportOOMError(conn);
989 990 991
        return -1;
    }

992
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
993 994 995 996
        vm->vcpupids[0] = vm->pid;
        return 0;
    }

997
    if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) {
998 999 1000 1001 1002 1003 1004 1005 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
        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;

1056
    VIR_FREE(qemucpus);
1057 1058 1059 1060
    return 0;

error:
    VIR_FREE(vm->vcpupids);
1061 1062
    vm->nvcpupids = 0;
    VIR_FREE(qemucpus);
1063 1064 1065 1066 1067 1068 1069 1070

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

1071 1072
static int
qemudInitCpus(virConnectPtr conn,
D
Daniel Veillard 已提交
1073 1074
              virDomainObjPtr vm,
              const char *migrateFrom) {
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
    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 已提交
1090 1091 1092 1093 1094 1095
    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++)
1096
            CPU_SET(i, &mask);
D
Daniel P. Berrange 已提交
1097
    }
1098 1099 1100 1101

    for (i = 0 ; i < vm->nvcpupids ; i++) {
        if (sched_setaffinity(vm->vcpupids[i],
                              sizeof(mask), &mask) < 0) {
1102 1103
            virReportSystemError(conn, errno, "%s",
                                 _("failed to set CPU affinity"));
1104 1105 1106 1107 1108
            return -1;
        }
    }
#endif /* HAVE_SCHED_GETAFFINITY */

D
Daniel Veillard 已提交
1109 1110
    if (migrateFrom == NULL) {
        /* Allow the CPUS to start executing */
1111
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
D
Daniel Veillard 已提交
1112 1113 1114 1115 1116
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("resume operation failed"));
            return -1;
        }
        VIR_FREE(info);
1117 1118 1119 1120 1121 1122
    }

    return 0;
}


1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
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 &&
1137
        (vm->def->graphics->data.vnc.passwd || driver->vncPassword)) {
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155

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


1156
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
1157 1158 1159 1160 1161 1162 1163 1164 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
    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;
}

1192 1193 1194 1195 1196 1197 1198 1199 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
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;
}

1265 1266 1267 1268 1269 1270 1271 1272 1273
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;
}

1274 1275 1276
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
                                            const char *name);

1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
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;
}

1294 1295
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
1296
                              virDomainObjPtr vm,
1297 1298
                              const char *migrateFrom,
                              int stdin_fd) {
1299
    const char **argv = NULL, **tmp;
1300
    const char **progenv = NULL;
1301
    int i, ret;
1302
    struct stat sb;
1303 1304
    int *tapfds = NULL;
    int ntapfds = 0;
1305
    unsigned int qemuCmdFlags;
1306
    fd_set keepfd;
1307
    const char *emulator;
G
Guido Günther 已提交
1308
    pid_t child;
1309
    int pos = -1;
1310
    char ebuf[1024];
1311

1312 1313 1314 1315 1316
    struct gemudHookData hookData;
    hookData.conn = conn;
    hookData.vm = vm;
    hookData.driver = driver;

1317 1318 1319
   /* 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 &&
D
Daniel P. Berrange 已提交
1320 1321 1322 1323
        driver->securityDriver &&
        driver->securityDriver->domainGenSecurityLabel &&
        driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
        return -1;
1324

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
    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics->data.vnc.autoport) {
1336
        int port = qemudNextFreeVNCPort(driver);
1337
        if (port < 0) {
1338
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
1339
                             "%s", _("Unable to find an unused VNC port"));
1340 1341
            return -1;
        }
1342 1343
        vm->def->graphics->data.vnc.port = port;
    }
1344

1345
    if (virFileMakePath(driver->logDir) < 0) {
1346 1347 1348
        virReportSystemError(conn, errno,
                             _("cannot create log directory %s"),
                             driver->logDir);
1349 1350 1351
        return -1;
    }

1352
    if((vm->logfile = qemudLogFD(conn, driver->logDir, vm->def->name)) < 0)
1353 1354
        return -1;

1355 1356 1357 1358 1359 1360
    emulator = vm->def->emulator;
    if (!emulator)
        emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
    if (!emulator)
        return -1;

1361 1362 1363 1364
    /* 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
     */
1365
    if (stat(emulator, &sb) < 0) {
1366 1367 1368
        virReportSystemError(conn, errno,
                             _("Cannot find QEMU binary %s"),
                             emulator);
1369 1370 1371
        return -1;
    }

1372
    if (qemudExtractVersionInfo(emulator,
1373 1374 1375 1376
                                NULL,
                                &qemuCmdFlags) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Cannot determine QEMU argv syntax %s"),
1377
                         emulator);
1378 1379
        return -1;
    }
1380

1381 1382 1383
    if (qemuPrepareHostDevices(conn, vm->def) < 0)
        return -1;

1384
    vm->def->id = driver->nextvmid++;
1385
    if (qemudBuildCommandLine(conn, driver, vm,
1386
                              qemuCmdFlags, &argv, &progenv,
1387
                              &tapfds, &ntapfds, migrateFrom) < 0) {
1388
        close(vm->logfile);
1389
        vm->def->id = -1;
1390 1391 1392 1393
        vm->logfile = -1;
        return -1;
    }

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

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

1422 1423 1424
    for (i = 0 ; i < ntapfds ; i++)
        FD_SET(tapfds[i], &keepfd);

1425 1426 1427 1428
    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 已提交
1429 1430 1431 1432

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

    if (ret == 0) {
1458
        vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
G
Guido Günther 已提交
1459
    } else
1460
        vm->def->id = -1;
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
    if (ret == 0) {
1478
        if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
1479
            (qemudDetectVcpuPIDs(conn, vm) < 0) ||
1480
            (qemudInitCpus(conn, vm, migrateFrom) < 0) ||
1481 1482
            (qemudInitPasswords(conn, driver, vm) < 0) ||
            (qemudSaveDomainStatus(conn, qemu_driver, vm) < 0)) {
1483 1484 1485
            qemudShutdownVMDaemon(conn, driver, vm);
            return -1;
        }
1486 1487
    }

1488
    return ret;
1489 1490 1491
}


1492
static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
1493 1494
                                  struct qemud_driver *driver,
                                  virDomainObjPtr vm) {
1495
    if (!virDomainIsActive(vm))
1496
        return;
1497

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

G
Guido Günther 已提交
1500 1501
    if (virKillProcess(vm->pid, 0) == 0 &&
        virKillProcess(vm->pid, SIGTERM) < 0)
1502 1503 1504
        virReportSystemError(conn, errno,
                             _("Failed to send SIGTERM to %s (%d)"),
                             vm->def->name, vm->pid);
1505

1506 1507 1508
    if (vm->monitorWatch != -1) {
        virEventRemoveHandle(vm->monitorWatch);
        vm->monitorWatch = -1;
1509
    }
1510

1511 1512
    if (close(vm->logfile) < 0) {
        char ebuf[1024];
1513
        VIR_WARN(_("Unable to close logfile: %s\n"),
1514 1515
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1516 1517 1518 1519 1520
    if (vm->monitor != -1)
        close(vm->monitor);
    vm->logfile = -1;
    vm->monitor = -1;

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

1524 1525 1526 1527
    /* Reset Security Labels */
    if (driver->securityDriver)
        driver->securityDriver->domainRestoreSecurityLabel(conn, vm);

1528 1529 1530 1531 1532 1533 1534
    /* 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);
    }

1535
    if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
1536
        VIR_WARN(_("Failed to remove domain status for %s"),
1537 1538
                 vm->def->name);
    }
1539
    vm->pid = -1;
1540
    vm->def->id = -1;
1541
    vm->state = VIR_DOMAIN_SHUTOFF;
1542
    VIR_FREE(vm->vcpupids);
1543
    vm->nvcpupids = 0;
1544 1545

    if (vm->newDef) {
1546
        virDomainDefFree(vm->def);
1547
        vm->def = vm->newDef;
1548
        vm->def->id = -1;
1549 1550 1551 1552 1553
        vm->newDef = NULL;
    }
}


1554
static void
1555
qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
1556
    struct qemud_driver *driver = opaque;
1557
    virDomainObjPtr vm = NULL;
1558
    virDomainEventPtr event = NULL;
1559
    unsigned int i;
1560
    int quit = 0, failed = 0;
1561

1562
    qemuDriverLock(driver);
1563
    for (i = 0 ; i < driver->domains.count ; i++) {
1564 1565 1566
        virDomainObjPtr tmpvm = driver->domains.objs[i];
        virDomainObjLock(tmpvm);
        if (virDomainIsActive(tmpvm) &&
1567
            tmpvm->monitorWatch == watch) {
1568
            vm = tmpvm;
1569
            break;
1570
        }
1571
        virDomainObjUnlock(tmpvm);
1572 1573 1574
    }

    if (!vm)
1575
        goto cleanup;
1576

1577
    if (vm->monitor != fd) {
1578 1579
        failed = 1;
    } else {
1580
        if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
1581
            quit = 1;
1582
        else {
1583 1584
            VIR_ERROR(_("unhandled fd event %d for %s"),
                      events, vm->def->name);
1585
            failed = 1;
1586
        }
1587 1588
    }

1589
    if (failed || quit) {
1590 1591 1592 1593 1594
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         quit ?
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
        qemudShutdownVMDaemon(NULL, driver, vm);
        if (!vm->persistent) {
            virDomainRemoveInactive(&driver->domains,
                                    vm);
            vm = NULL;
        }
    }

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
1606 1607
    if (event)
        qemuDomainEventQueue(driver, event);
1608
    qemuDriverUnlock(driver);
1609 1610
}

1611
static int
1612 1613 1614 1615 1616
qemudMonitorCommandExtra(const virDomainObjPtr vm,
                         const char *cmd,
                         const char *extra,
                         const char *extraPrompt,
                         char **reply) {
D
Daniel P. Berrange 已提交
1617 1618
    int size = 0;
    char *buf = NULL;
1619
    size_t cmdlen = strlen(cmd);
1620
    size_t extralen = extra ? strlen(extra) : 0;
D
Daniel P. Berrange 已提交
1621

1622 1623 1624
    if (safewrite(vm->monitor, cmd, cmdlen) != cmdlen)
        return -1;
    if (safewrite(vm->monitor, "\r", 1) != 1)
D
Daniel P. Berrange 已提交
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
        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 已提交
1637

1638 1639
            if (got == 0)
                goto error;
D
Daniel P. Berrange 已提交
1640 1641 1642 1643 1644
            if (got < 0) {
                if (errno == EINTR)
                    continue;
                if (errno == EAGAIN)
                    break;
1645
                goto error;
1646
            }
1647
            if (VIR_REALLOC_N(buf, size+got+1) < 0)
1648 1649
                goto error;

D
Daniel P. Berrange 已提交
1650 1651 1652 1653
            memmove(buf+size, data, got);
            buf[size+got] = '\0';
            size += got;
        }
1654

D
Daniel P. Berrange 已提交
1655
        /* Look for QEMU prompt to indicate completion */
1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
        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 已提交
1681

1682 1683
                break;
            }
D
Daniel P. Berrange 已提交
1684 1685 1686 1687 1688 1689
        }
    pollagain:
        /* Need to wait for more data */
        if (poll(&fd, 1, -1) < 0) {
            if (errno == EINTR)
                goto pollagain;
1690
            goto error;
D
Daniel P. Berrange 已提交
1691 1692 1693
        }
    }

1694
    /* Log, but ignore failures to write logfile for VM */
1695 1696
    if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
        char ebuf[1024];
1697
        VIR_WARN(_("Unable to log VM console data: %s\n"),
1698 1699
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1700

D
Daniel P. Berrange 已提交
1701 1702
    *reply = buf;
    return 0;
1703 1704 1705 1706

 error:
    if (buf) {
        /* Log, but ignore failures to write logfile for VM */
1707 1708
        if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
            char ebuf[1024];
1709
            VIR_WARN(_("Unable to log VM console data: %s\n"),
1710 1711
                     virStrerror(errno, ebuf, sizeof ebuf));
        }
1712
        VIR_FREE(buf);
1713 1714
    }
    return -1;
D
Daniel P. Berrange 已提交
1715 1716
}

1717 1718 1719 1720 1721 1722 1723 1724
static int
qemudMonitorCommand(const virDomainObjPtr vm,
                    const char *cmd,
                    char **reply) {
    return qemudMonitorCommandExtra(vm, cmd, NULL, NULL, reply);
}


1725 1726 1727 1728 1729 1730
/**
 * qemudProbe:
 *
 * Probe for the availability of the qemu driver, assume the
 * presence of QEmu emulation if the binaries are installed
 */
1731
static int qemudProbe(void)
1732 1733 1734
{
    if ((virFileExists("/usr/bin/qemu")) ||
        (virFileExists("/usr/bin/qemu-kvm")) ||
G
Guido Günther 已提交
1735
        (virFileExists("/usr/bin/kvm")) ||
1736 1737 1738 1739
        (virFileExists("/usr/bin/xenner")))
        return 1;

    return 0;
1740
}
1741

1742
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
1743
                                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1744
                                  int flags ATTRIBUTE_UNUSED) {
1745 1746 1747
    uid_t uid = getuid();

    if (qemu_driver == NULL)
1748
        goto decline;
1749

1750 1751 1752 1753 1754 1755
    if (!qemudProbe())
        goto decline;

    if (conn->uri == NULL) {
        conn->uri = xmlParseURI(uid ? "qemu:///session" : "qemu:///system");
        if (!conn->uri) {
1756
            virReportOOMError(conn);
1757 1758 1759 1760
            return VIR_DRV_OPEN_ERROR;
        }
    } else if (conn->uri->scheme == NULL ||
               conn->uri->path == NULL)
1761 1762
        goto decline;

1763
    if (STRNEQ (conn->uri->scheme, "qemu"))
1764 1765
        goto decline;

1766
    if (uid != 0) {
1767
        if (STRNEQ (conn->uri->path, "/session"))
1768
            goto decline;
1769
    } else { /* root */
1770 1771
        if (STRNEQ (conn->uri->path, "/system") &&
            STRNEQ (conn->uri->path, "/session"))
1772
            goto decline;
1773 1774 1775 1776 1777
    }

    conn->privateData = qemu_driver;

    return VIR_DRV_OPEN_SUCCESS;
1778 1779

 decline:
1780
    return VIR_DRV_OPEN_DECLINED;
1781 1782 1783
}

static int qemudClose(virConnectPtr conn) {
1784
    struct qemud_driver *driver = conn->privateData;
1785 1786 1787

    /* Get rid of callbacks registered for this conn */
    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
1788 1789 1790 1791 1792 1793

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
1794 1795 1796 1797 1798 1799 1800 1801 1802 1803
/* 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;
    }
}

1804
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1805
    return "QEMU";
1806 1807
}

1808 1809 1810 1811 1812

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

    int r, fd;
1813

1814 1815
    fd = open(KVM_DEVICE, O_RDONLY);
    if (fd < 0) {
1816 1817
        virReportSystemError(NULL, errno, _("Unable to open %s"), KVM_DEVICE);
        return -1;
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828
    }

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

    close(fd);
    return maxvcpus;
}


1829
static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) {
1830 1831 1832
    if (!type)
        return 16;

1833
    if (STRCASEEQ(type, "qemu"))
1834 1835
        return 16;

1836
    if (STRCASEEQ(type, "kvm"))
1837
        return kvmGetMaxVCPUs();
1838

1839
    if (STRCASEEQ(type, "kqemu"))
1840
        return 1;
1841 1842 1843

    qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
                     _("unknown type '%s'"), type);
1844 1845 1846
    return -1;
}

1847 1848 1849
static int qemudGetNodeInfo(virConnectPtr conn,
                            virNodeInfoPtr nodeinfo) {
    return virNodeInfoPopulate(conn, nodeinfo);
1850 1851 1852
}


1853
static char *qemudGetCapabilities(virConnectPtr conn) {
1854
    struct qemud_driver *driver = conn->privateData;
1855
    char *xml;
1856

1857
    qemuDriverLock(driver);
1858
    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
1859
        virReportOOMError(conn);
1860
    qemuDriverUnlock(driver);
1861

1862
    return xml;
1863 1864 1865
}


1866 1867 1868 1869 1870 1871 1872 1873
#if HAVE_NUMACTL
static int
qemudNodeGetCellsFreeMemory(virConnectPtr conn,
                            unsigned long long *freeMems,
                            int startCell,
                            int maxCells)
{
    int n, lastCell, numCells;
1874
    int ret = -1;
1875 1876 1877 1878

    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1879
        goto cleanup;
1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
    }
    lastCell = startCell + maxCells - 1;
    if (lastCell > numa_max_node())
        lastCell = numa_max_node();

    for (numCells = 0, n = startCell ; n <= lastCell ; n++) {
        long long mem;
        if (numa_node_size64(n, &mem) < 0) {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("Failed to query NUMA free memory"));
1890
            goto cleanup;
1891 1892 1893
        }
        freeMems[numCells++] = mem;
    }
1894 1895 1896 1897
    ret = numCells;

cleanup:
    return ret;
1898 1899 1900 1901 1902
}

static unsigned long long
qemudNodeGetFreeMemory (virConnectPtr conn)
{
1903
    unsigned long long freeMem = -1;
1904
    int n;
1905

1906 1907 1908
    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1909
        goto cleanup;
1910 1911 1912 1913 1914 1915 1916
    }

    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"));
1917
            goto cleanup;
1918 1919 1920 1921
        }
        freeMem += mem;
    }

1922
cleanup:
1923 1924 1925 1926
    return freeMem;
}

#endif
1927

D
Daniel P. Berrange 已提交
1928 1929 1930
static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) {
    char proc[PATH_MAX];
    FILE *pidinfo;
1931
    unsigned long long usertime, systime;
D
Daniel P. Berrange 已提交
1932 1933 1934 1935 1936 1937

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

    if (!(pidinfo = fopen(proc, "r"))) {
1938
        /*printf("cannot read pid info");*/
D
Daniel P. Berrange 已提交
1939 1940 1941 1942 1943
        /* VM probably shut down, so fake 0 */
        *cpuTime = 0;
        return 0;
    }

1944
    if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
1945
        qemudDebug("not enough arg");
D
Daniel P. Berrange 已提交
1946 1947 1948 1949 1950 1951 1952 1953
        return -1;
    }

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

1956
    qemudDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
D
Daniel P. Berrange 已提交
1957 1958 1959 1960 1961 1962 1963

    fclose(pidinfo);

    return 0;
}


1964
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
1965
                                          int id) {
1966 1967 1968 1969
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

1970
    qemuDriverLock(driver);
1971
    vm  = virDomainFindByID(&driver->domains, id);
1972
    qemuDriverUnlock(driver);
1973 1974

    if (!vm) {
1975
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
1976
        goto cleanup;
1977 1978
    }

1979
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1980
    if (dom) dom->id = vm->def->id;
1981 1982

cleanup:
1983 1984
    if (vm)
        virDomainObjUnlock(vm);
1985 1986
    return dom;
}
1987

1988
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
1989
                                            const unsigned char *uuid) {
1990 1991 1992
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1993

1994
    qemuDriverLock(driver);
1995
    vm = virDomainFindByUUID(&driver->domains, uuid);
1996 1997
    qemuDriverUnlock(driver);

1998
    if (!vm) {
1999
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
2000
        goto cleanup;
2001 2002
    }

2003
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2004
    if (dom) dom->id = vm->def->id;
2005 2006

cleanup:
2007 2008
    if (vm)
        virDomainObjUnlock(vm);
2009 2010
    return dom;
}
2011

2012
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
2013
                                            const char *name) {
2014 2015 2016
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
2017

2018
    qemuDriverLock(driver);
2019
    vm = virDomainFindByName(&driver->domains, name);
2020 2021
    qemuDriverUnlock(driver);

2022
    if (!vm) {
2023
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
2024
        goto cleanup;
2025 2026
    }

2027
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2028
    if (dom) dom->id = vm->def->id;
2029 2030

cleanup:
2031 2032
    if (vm)
        virDomainObjUnlock(vm);
2033 2034 2035
    return dom;
}

2036
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
2037 2038 2039
    struct qemud_driver *driver = conn->privateData;
    int ret = -1;

2040
    qemuDriverLock(driver);
2041
    if (qemudExtractVersion(conn, driver) < 0)
2042
        goto cleanup;
2043

2044
    *version = qemu_driver->qemuVersion;
2045 2046 2047
    ret = 0;

cleanup:
2048
    qemuDriverUnlock(driver);
2049
    return ret;
D
Daniel P. Berrange 已提交
2050 2051
}

2052 2053 2054
static char *
qemudGetHostname (virConnectPtr conn)
{
2055
    char *result;
2056

2057 2058
    result = virGetHostname();
    if (result == NULL) {
2059 2060
        virReportSystemError (conn, errno,
                              "%s", _("failed to determine host name"));
2061 2062 2063
        return NULL;
    }
    /* Caller frees this string. */
2064
    return result;
2065 2066
}

2067
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
2068
    struct qemud_driver *driver = conn->privateData;
2069 2070
    int got = 0, i;

2071 2072 2073
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count && got < nids ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
2074 2075
        if (virDomainIsActive(driver->domains.objs[i]))
            ids[got++] = driver->domains.objs[i]->def->id;
2076 2077 2078
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
2079

D
Daniel P. Berrange 已提交
2080 2081
    return got;
}
2082

2083
static int qemudNumDomains(virConnectPtr conn) {
2084
    struct qemud_driver *driver = conn->privateData;
2085 2086
    int n = 0, i;

2087 2088 2089
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
2090
        if (virDomainIsActive(driver->domains.objs[i]))
2091
            n++;
2092 2093 2094
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
2095

2096
    return n;
D
Daniel P. Berrange 已提交
2097
}
2098

2099
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
2100
                                      unsigned int flags ATTRIBUTE_UNUSED) {
2101
    struct qemud_driver *driver = conn->privateData;
2102
    virDomainDefPtr def;
2103
    virDomainObjPtr vm = NULL;
2104
    virDomainPtr dom = NULL;
2105
    virDomainEventPtr event = NULL;
D
Daniel P. Berrange 已提交
2106

2107
    qemuDriverLock(driver);
2108 2109
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
2110
        goto cleanup;
2111

2112
    vm = virDomainFindByName(&driver->domains, def->name);
2113
    if (vm) {
2114
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2115
                         _("domain '%s' is already defined"),
2116
                         def->name);
2117
        goto cleanup;
2118
    }
2119
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
2120 2121 2122 2123 2124
    if (vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(def->uuid, uuidstr);
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2125
                         _("domain with uuid '%s' is already defined"),
2126
                         uuidstr);
2127
        goto cleanup;
2128
    }
2129

2130 2131
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
2132 2133 2134 2135
                                  def)))
        goto cleanup;

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

2137
    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
2138 2139
        virDomainRemoveInactive(&driver->domains,
                                vm);
2140
        vm = NULL;
2141
        goto cleanup;
D
Daniel P. Berrange 已提交
2142
    }
2143 2144 2145 2146

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

2148
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2149
    if (dom) dom->id = vm->def->id;
2150 2151 2152

cleanup:
    virDomainDefFree(def);
2153 2154
    if (vm)
        virDomainObjUnlock(vm);
2155 2156
    if (event)
        qemuDomainEventQueue(driver, event);
2157
    qemuDriverUnlock(driver);
2158
    return dom;
D
Daniel P. Berrange 已提交
2159 2160 2161
}


2162
static int qemudDomainSuspend(virDomainPtr dom) {
2163
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
2164
    char *info;
2165 2166
    virDomainObjPtr vm;
    int ret = -1;
2167
    virDomainEventPtr event = NULL;
2168

2169
    qemuDriverLock(driver);
2170
    vm = virDomainFindByID(&driver->domains, dom->id);
2171 2172
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
2173
    if (!vm) {
2174
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
2175
        goto cleanup;
D
Daniel P. Berrange 已提交
2176
    }
2177
    if (!virDomainIsActive(vm)) {
2178 2179
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
2180
        goto cleanup;
D
Daniel P. Berrange 已提交
2181
    }
2182
    if (vm->state != VIR_DOMAIN_PAUSED) {
2183
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
2184 2185 2186 2187 2188 2189
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("suspend operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
2190 2191 2192
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
2193
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
2194
    }
2195 2196
    if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        goto cleanup;
2197 2198 2199
    ret = 0;

cleanup:
2200 2201
    if (vm)
        virDomainObjUnlock(vm);
2202 2203 2204 2205 2206 2207

    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2208
    return ret;
D
Daniel P. Berrange 已提交
2209 2210 2211
}


2212
static int qemudDomainResume(virDomainPtr dom) {
2213
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
2214
    char *info;
2215 2216
    virDomainObjPtr vm;
    int ret = -1;
2217
    virDomainEventPtr event = NULL;
2218

2219
    qemuDriverLock(driver);
2220
    vm = virDomainFindByID(&driver->domains, dom->id);
2221 2222
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
2223
    if (!vm) {
2224 2225
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         _("no domain with matching id %d"), dom->id);
2226
        goto cleanup;
D
Daniel P. Berrange 已提交
2227
    }
2228
    if (!virDomainIsActive(vm)) {
2229 2230
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
2231
        goto cleanup;
D
Daniel P. Berrange 已提交
2232
    }
2233
    if (vm->state == VIR_DOMAIN_PAUSED) {
2234
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
2235 2236 2237 2238 2239 2240
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("resume operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_RUNNING;
        qemudDebug("Reply %s", info);
2241 2242 2243
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
2244
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
2245
    }
2246 2247
    if (qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        goto cleanup;
2248 2249 2250
    ret = 0;

cleanup:
2251 2252
    if (vm)
        virDomainObjUnlock(vm);
2253 2254 2255 2256 2257
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2258
    return ret;
D
Daniel P. Berrange 已提交
2259 2260 2261
}


2262
static int qemudDomainShutdown(virDomainPtr dom) {
2263 2264
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2265
    char* info;
2266
    int ret = -1;
2267

2268
    qemuDriverLock(driver);
2269
    vm = virDomainFindByID(&driver->domains, dom->id);
2270 2271
    qemuDriverUnlock(driver);

2272 2273
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2274
                         _("no domain with matching id %d"), dom->id);
2275
        goto cleanup;
2276 2277
    }

2278
    if (qemudMonitorCommand(vm, "system_powerdown", &info) < 0) {
2279
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2280
                         "%s", _("shutdown operation failed"));
2281
        goto cleanup;
2282
    }
D
Daniel Veillard 已提交
2283
    VIR_FREE(info);
2284 2285 2286
    ret = 0;

cleanup:
2287 2288
    if (vm)
        virDomainObjUnlock(vm);
2289
    return ret;
2290 2291 2292
}


2293
static int qemudDomainDestroy(virDomainPtr dom) {
2294 2295 2296
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2297
    virDomainEventPtr event = NULL;
2298

2299
    qemuDriverLock(driver);
2300
    vm  = virDomainFindByID(&driver->domains, dom->id);
D
Daniel P. Berrange 已提交
2301
    if (!vm) {
2302
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2303
                         _("no domain with matching id %d"), dom->id);
2304
        goto cleanup;
D
Daniel P. Berrange 已提交
2305
    }
2306

2307
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2308 2309 2310
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2311
    if (!vm->persistent) {
2312 2313
        virDomainRemoveInactive(&driver->domains,
                                vm);
2314 2315
        vm = NULL;
    }
2316 2317 2318
    ret = 0;

cleanup:
2319 2320
    if (vm)
        virDomainObjUnlock(vm);
2321 2322
    if (event)
        qemuDomainEventQueue(driver, event);
2323
    qemuDriverUnlock(driver);
2324
    return ret;
D
Daniel P. Berrange 已提交
2325 2326 2327
}


2328
static char *qemudDomainGetOSType(virDomainPtr dom) {
2329 2330 2331
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *type = NULL;
2332

2333
    qemuDriverLock(driver);
2334
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2335
    qemuDriverUnlock(driver);
2336 2337
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2338
                         "%s", _("no domain with matching uuid"));
2339
        goto cleanup;
2340 2341
    }

2342
    if (!(type = strdup(vm->def->os.type)))
2343
        virReportOOMError(dom->conn);
2344 2345

cleanup:
2346 2347
    if (vm)
        virDomainObjUnlock(vm);
2348 2349 2350
    return type;
}

2351 2352
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
2353 2354 2355
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    unsigned long ret = 0;
2356

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

2361
    if (!vm) {
2362 2363 2364
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

2370 2371 2372
    ret = vm->def->maxmem;

cleanup:
2373 2374
    if (vm)
        virDomainObjUnlock(vm);
2375
    return ret;
2376 2377 2378
}

static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
2379 2380 2381
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2382

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

2387
    if (!vm) {
2388 2389 2390
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2391
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2392
                         _("no domain with matching uuid '%s'"), uuidstr);
2393
        goto cleanup;
2394 2395 2396 2397
    }

    if (newmax < vm->def->memory) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2398
                         "%s", _("cannot set max memory lower than current memory"));
2399
        goto cleanup;;
2400 2401 2402
    }

    vm->def->maxmem = newmax;
2403 2404 2405
    ret = 0;

cleanup:
2406 2407
    if (vm)
        virDomainObjUnlock(vm);
2408
    return ret;
2409 2410 2411
}

static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
2412 2413 2414
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2415

2416
    qemuDriverLock(driver);
2417
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2418
    qemuDriverUnlock(driver);
2419
    if (!vm) {
2420 2421 2422
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

2428
    if (virDomainIsActive(vm)) {
2429
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
2430
                         "%s", _("cannot set memory of an active domain"));
2431
        goto cleanup;
2432 2433 2434 2435
    }

    if (newmem > vm->def->maxmem) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2436
                         "%s", _("cannot set memory higher than max memory"));
2437
        goto cleanup;
2438 2439 2440
    }

    vm->def->memory = newmem;
2441 2442 2443
    ret = 0;

cleanup:
2444 2445
    if (vm)
        virDomainObjUnlock(vm);
2446
    return ret;
2447 2448
}

2449
static int qemudDomainGetInfo(virDomainPtr dom,
2450
                              virDomainInfoPtr info) {
2451 2452 2453 2454
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

2455
    qemuDriverLock(driver);
2456
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2457
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
2458
    if (!vm) {
2459 2460
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
2461
        goto cleanup;
D
Daniel P. Berrange 已提交
2462 2463
    }

2464
    info->state = vm->state;
D
Daniel P. Berrange 已提交
2465

2466
    if (!virDomainIsActive(vm)) {
2467
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
2468
    } else {
2469
        if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
2470
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
2471
            goto cleanup;
D
Daniel P. Berrange 已提交
2472 2473 2474
        }
    }

2475 2476 2477
    info->maxMem = vm->def->maxmem;
    info->memory = vm->def->memory;
    info->nrVirtCpu = vm->def->vcpus;
2478 2479 2480
    ret = 0;

cleanup:
2481 2482
    if (vm)
        virDomainObjUnlock(vm);
2483
    return ret;
D
Daniel P. Berrange 已提交
2484 2485 2486
}


D
Daniel P. Berrange 已提交
2487
static char *qemudEscape(const char *in, int shell)
2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508
{
    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 已提交
2509 2510 2511 2512
            if (shell)
                len += 5;
            else
                len += 1;
2513 2514 2515 2516 2517 2518 2519
            break;
        default:
            len += 1;
            break;
        }
    }

2520
    if (VIR_ALLOC_N(out, len + 1) < 0)
2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538
        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 已提交
2539 2540 2541 2542 2543 2544 2545 2546 2547
            if (shell) {
                out[j++] = '\'';
                out[j++] = '\\';
                out[j++] = '\\';
                out[j++] = '\'';
                out[j++] = '\'';
            } else {
                out[j++] = in[i];
            }
2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
            break;
        default:
            out[j++] = in[i];
            break;
        }
    }
    out[j] = '\0';

    return out;
}

2559 2560 2561 2562 2563
static char *qemudEscapeMonitorArg(const char *in)
{
    return qemudEscape(in, 0);
}

D
Daniel P. Berrange 已提交
2564 2565 2566 2567
static char *qemudEscapeShellArg(const char *in)
{
    return qemudEscape(in, 1);
}
2568

2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579
#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];
};

2580
static int qemudDomainSave(virDomainPtr dom,
2581
                           const char *path) {
2582 2583 2584 2585 2586 2587 2588
    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;
2589
    struct qemud_save_header header;
2590
    int ret = -1;
2591
    virDomainEventPtr event = NULL;
2592 2593 2594 2595 2596

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

2597
    qemuDriverLock(driver);
2598 2599
    vm = virDomainFindByID(&driver->domains, dom->id);

D
Daniel P. Berrange 已提交
2600
    if (!vm) {
2601
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2602
                         _("no domain with matching id %d"), dom->id);
2603
        goto cleanup;
D
Daniel P. Berrange 已提交
2604
    }
2605

2606
    if (!virDomainIsActive(vm)) {
2607
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2608
                         "%s", _("domain is not running"));
2609
        goto cleanup;
D
Daniel P. Berrange 已提交
2610
    }
2611 2612 2613 2614

    /* Pause */
    if (vm->state == VIR_DOMAIN_RUNNING) {
        header.was_running = 1;
2615
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
2616
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2617
                             "%s", _("suspend operation failed"));
2618
            goto cleanup;
2619
        }
2620 2621 2622
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
        VIR_FREE(info);
2623 2624 2625
    }

    /* Get XML for the domain */
2626
    xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE);
2627 2628
    if (!xml) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2629
                         "%s", _("failed to get domain xml"));
2630
        goto cleanup;
2631 2632 2633 2634 2635 2636
    }
    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,
2637
                         _("failed to create '%s'"), path);
2638
        goto cleanup;
2639 2640 2641 2642
    }

    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2643
                         "%s", _("failed to write save header"));
2644
        goto cleanup;
2645 2646 2647 2648
    }

    if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2649
                         "%s", _("failed to write xml"));
2650
        goto cleanup;
2651 2652
    }

2653
    if (close(fd) < 0) {
2654 2655 2656
        virReportSystemError(dom->conn, errno,
                             _("unable to save file %s"),
                             path);
2657 2658 2659
        goto cleanup;
    }
    fd = -1;
2660 2661 2662 2663

    /* Migrate to file */
    safe_path = qemudEscapeShellArg(path);
    if (!safe_path) {
2664
        virReportOOMError(dom->conn);
2665
        goto cleanup;
2666
    }
2667
    if (virAsprintf(&command, "migrate \"exec:"
2668
                  "dd of='%s' oflag=append conv=notrunc 2>/dev/null"
2669
                  "\"", safe_path) == -1) {
2670
        virReportOOMError(dom->conn);
2671 2672
        command = NULL;
        goto cleanup;
2673 2674
    }

2675
    if (qemudMonitorCommand(vm, command, &info) < 0) {
2676
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2677
                         "%s", _("migrate operation failed"));
2678
        goto cleanup;
2679 2680
    }

2681 2682 2683 2684 2685 2686 2687 2688
    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"));
2689
        goto cleanup;
2690 2691
    }

2692 2693
    /* Shut it down */
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2694 2695 2696
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2697
    if (!vm->persistent) {
2698 2699
        virDomainRemoveInactive(&driver->domains,
                                vm);
2700 2701
        vm = NULL;
    }
2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712
    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);
2713 2714
    if (vm)
        virDomainObjUnlock(vm);
2715 2716
    if (event)
        qemuDomainEventQueue(driver, event);
2717
    qemuDriverUnlock(driver);
2718
    return ret;
D
Daniel P. Berrange 已提交
2719 2720 2721
}


2722
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
2723 2724
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2725
    int max;
2726
    int ret = -1;
2727

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

2732
    if (!vm) {
2733 2734 2735
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

2741
    if (virDomainIsActive(vm)) {
2742
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
2743
                         _("cannot change vcpu count of an active domain"));
2744
        goto cleanup;
2745 2746 2747 2748 2749
    }

    if ((max = qemudDomainGetMaxVcpus(dom)) < 0) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                         _("could not determine max vcpus for the domain"));
2750
        goto cleanup;
2751 2752 2753 2754 2755 2756
    }

    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);
2757
        goto cleanup;
2758 2759 2760
    }

    vm->def->vcpus = nvcpus;
2761 2762 2763
    ret = 0;

cleanup:
2764 2765
    if (vm)
        virDomainObjUnlock(vm);
2766
    return ret;
2767 2768
}

2769 2770 2771 2772 2773 2774 2775

#if HAVE_SCHED_GETAFFINITY
static int
qemudDomainPinVcpu(virDomainPtr dom,
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
2776 2777
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2778 2779 2780
    cpu_set_t mask;
    int i, maxcpu;
    virNodeInfo nodeinfo;
2781
    int ret = -1;
2782

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

2787
    if (!virDomainIsActive(vm)) {
2788 2789
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         "%s",_("cannot pin vcpus on an inactive domain"));
2790
        goto cleanup;
2791 2792 2793 2794 2795 2796
    }

    if (vcpu > (vm->nvcpupids-1)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         _("vcpu number out of range %d > %d"),
                         vcpu, vm->nvcpupids);
2797
        goto cleanup;
2798 2799 2800
    }

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2801
        goto cleanup;
2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814

    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) {
2815 2816
            virReportSystemError(dom->conn, errno, "%s",
                                 _("cannot set affinity"));
2817
            goto cleanup;
2818 2819 2820 2821
        }
    } else {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("cpu affinity is not supported"));
2822
        goto cleanup;
2823
    }
2824
    ret = 0;
2825

2826
cleanup:
2827 2828
    if (vm)
        virDomainObjUnlock(vm);
2829
    return ret;
2830 2831 2832 2833 2834 2835 2836 2837
}

static int
qemudDomainGetVcpus(virDomainPtr dom,
                    virVcpuInfoPtr info,
                    int maxinfo,
                    unsigned char *cpumaps,
                    int maplen) {
2838 2839
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2840 2841
    virNodeInfo nodeinfo;
    int i, v, maxcpu;
2842
    int ret = -1;
2843

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

2848
    if (!virDomainIsActive(vm)) {
2849 2850
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         "%s",_("cannot pin vcpus on an inactive domain"));
2851
        goto cleanup;
2852 2853 2854
    }

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2855
        goto cleanup;
2856 2857 2858 2859 2860 2861 2862 2863 2864

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

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

2865 2866 2867 2868 2869 2870 2871 2872
    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 */
            }
2873 2874
        }

2875 2876 2877 2878 2879 2880 2881 2882 2883
        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) {
2884 2885
                        virReportSystemError(dom->conn, errno, "%s",
                                             _("cannot get affinity"));
2886 2887 2888 2889 2890 2891
                        goto cleanup;
                    }

                    for (i = 0 ; i < maxcpu ; i++)
                        if (CPU_ISSET(i, &mask))
                            VIR_USE_CPU(cpumap, i);
2892
                }
2893 2894 2895 2896
            } else {
                qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                                 "%s", _("cpu affinity is not available"));
                goto cleanup;
2897 2898 2899
            }
        }
    }
2900
    ret = maxinfo;
2901

2902
cleanup:
2903 2904
    if (vm)
        virDomainObjUnlock(vm);
2905
    return ret;
2906 2907 2908 2909
}
#endif /* HAVE_SCHED_GETAFFINITY */


2910
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
2911 2912
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2913
    const char *type;
2914
    int ret = -1;
2915

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

2920
    if (!vm) {
2921 2922 2923
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

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

2936
    ret = qemudGetMaxVCPUs(dom->conn, type);
2937

2938
cleanup:
2939 2940
    if (vm)
        virDomainObjUnlock(vm);
2941 2942 2943
    return ret;
}

2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009
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;
3010

3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031
    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 */
3032
static int qemudDomainRestore(virConnectPtr conn,
3033 3034 3035
                              const char *path) {
    struct qemud_driver *driver = conn->privateData;
    virDomainDefPtr def = NULL;
3036
    virDomainObjPtr vm = NULL;
3037 3038 3039
    int fd = -1;
    int ret = -1;
    char *xml = NULL;
3040
    struct qemud_save_header header;
3041
    virDomainEventPtr event = NULL;
3042

3043
    qemuDriverLock(driver);
3044 3045 3046
    /* Verify the header and read the XML */
    if ((fd = open(path, O_RDONLY)) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3047
                         "%s", _("cannot read domain image"));
3048
        goto cleanup;
3049 3050 3051 3052
    }

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3053
                         "%s", _("failed to read qemu header"));
3054
        goto cleanup;
3055 3056 3057 3058
    }

    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3059
                         "%s", _("image magic is incorrect"));
3060
        goto cleanup;
3061 3062 3063 3064
    }

    if (header.version > QEMUD_SAVE_VERSION) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3065
                         _("image version is not supported (%d > %d)"),
3066
                         header.version, QEMUD_SAVE_VERSION);
3067
        goto cleanup;
3068 3069
    }

3070
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
3071
        virReportOOMError(conn);
3072
        goto cleanup;
3073 3074 3075 3076
    }

    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3077
                         "%s", _("failed to read XML"));
3078
        goto cleanup;
3079 3080 3081
    }

    /* Create a domain from this XML */
3082 3083
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
3084
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3085
                         "%s", _("failed to parse XML"));
3086
        goto cleanup;
3087 3088 3089
    }

    /* Ensure the name and UUID don't already exist in an active VM */
3090
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
3091
    if (!vm)
3092
        vm = virDomainFindByName(&driver->domains, def->name);
3093 3094 3095 3096 3097 3098 3099 3100
    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);
        }
3101 3102
    }

3103 3104 3105
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
3106
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3107
                         "%s", _("failed to assign new VM"));
3108
        goto cleanup;
3109
    }
3110
    def = NULL;
3111 3112

    /* Set the migration source and start it up. */
3113
    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
3114
    close(fd);
3115
    fd = -1;
3116
    if (ret < 0) {
3117
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3118
                         "%s", _("failed to start VM"));
3119
        if (!vm->persistent) {
3120 3121
            virDomainRemoveInactive(&driver->domains,
                                    vm);
3122 3123
            vm = NULL;
        }
3124
        goto cleanup;
3125 3126
    }

3127 3128 3129
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
3130

3131 3132 3133
    /* If it was running before, resume it now. */
    if (header.was_running) {
        char *info;
3134
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
3135
            qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3136
                             "%s", _("failed to resume domain"));
3137
            goto cleanup;
3138
        }
3139
        VIR_FREE(info);
3140 3141
        vm->state = VIR_DOMAIN_RUNNING;
    }
3142
    ret = 0;
3143

3144 3145 3146 3147 3148
cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
3149 3150
    if (vm)
        virDomainObjUnlock(vm);
3151 3152
    if (event)
        qemuDomainEventQueue(driver, event);
3153
    qemuDriverUnlock(driver);
3154
    return ret;
D
Daniel P. Berrange 已提交
3155 3156 3157
}


3158
static char *qemudDomainDumpXML(virDomainPtr dom,
3159
                                int flags) {
3160 3161 3162 3163
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;

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

D
Daniel P. Berrange 已提交
3168
    if (!vm) {
3169 3170
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3171
        goto cleanup;
D
Daniel P. Berrange 已提交
3172 3173
    }

3174 3175 3176 3177 3178 3179
    ret = virDomainDefFormat(dom->conn,
                             (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
                             vm->newDef : vm->def,
                             flags);

cleanup:
3180 3181
    if (vm)
        virDomainObjUnlock(vm);
3182
    return ret;
D
Daniel P. Berrange 已提交
3183 3184 3185
}


3186
static int qemudListDefinedDomains(virConnectPtr conn,
3187
                            char **const names, int nnames) {
3188
    struct qemud_driver *driver = conn->privateData;
3189
    int got = 0, i;
3190

3191
    qemuDriverLock(driver);
3192
    for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
3193
        virDomainObjLock(driver->domains.objs[i]);
3194 3195
        if (!virDomainIsActive(driver->domains.objs[i])) {
            if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) {
3196
                virReportOOMError(conn);
3197
                virDomainObjUnlock(driver->domains.objs[i]);
3198 3199
                goto cleanup;
            }
3200
        }
3201
        virDomainObjUnlock(driver->domains.objs[i]);
D
Daniel P. Berrange 已提交
3202
    }
3203

3204
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
3205
    return got;
3206 3207 3208

 cleanup:
    for (i = 0 ; i < got ; i++)
3209
        VIR_FREE(names[i]);
3210
    qemuDriverUnlock(driver);
3211
    return -1;
D
Daniel P. Berrange 已提交
3212 3213
}

3214
static int qemudNumDefinedDomains(virConnectPtr conn) {
3215
    struct qemud_driver *driver = conn->privateData;
3216 3217
    int n = 0, i;

3218
    qemuDriverLock(driver);
3219 3220
    for (i = 0 ; i < driver->domains.count ; i++)
        if (!virDomainIsActive(driver->domains.objs[i]))
3221
            n++;
3222
    qemuDriverUnlock(driver);
3223

3224
    return n;
D
Daniel P. Berrange 已提交
3225 3226 3227
}


3228
static int qemudDomainStart(virDomainPtr dom) {
3229 3230 3231
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3232
    virDomainEventPtr event = NULL;
3233

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

3238
    if (!vm) {
3239
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
3240
                         "%s", _("no domain with matching uuid"));
3241
        goto cleanup;
3242 3243
    }

3244
    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
3245
    if (ret != -1)
3246 3247 3248
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
3249 3250

cleanup:
3251 3252
    if (vm)
        virDomainObjUnlock(vm);
3253 3254 3255 3256 3257
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
3258
    return ret;
D
Daniel P. Berrange 已提交
3259 3260 3261
}


3262
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
3263
    struct qemud_driver *driver = conn->privateData;
3264
    virDomainDefPtr def;
3265
    virDomainObjPtr vm = NULL;
3266
    virDomainPtr dom = NULL;
3267
    virDomainEventPtr event = NULL;
3268
    int newVM = 1;
3269

3270
    qemuDriverLock(driver);
3271 3272
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
3273
        goto cleanup;
3274

3275
    vm = virDomainFindByName(&driver->domains, def->name);
3276 3277
    if (vm) {
        virDomainObjUnlock(vm);
3278
        newVM = 0;
3279
    }
3280

3281 3282 3283 3284
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
        virDomainDefFree(def);
3285
        goto cleanup;
3286
    }
3287
    vm->persistent = 1;
3288

3289 3290
    if (virDomainSaveConfig(conn,
                            driver->configDir,
3291
                            vm->newDef ? vm->newDef : vm->def) < 0) {
3292 3293
        virDomainRemoveInactive(&driver->domains,
                                vm);
3294
        vm = NULL;
3295
        goto cleanup;
3296 3297
    }

3298 3299 3300 3301 3302
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     newVM ?
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
3303

3304
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3305
    if (dom) dom->id = vm->def->id;
3306 3307

cleanup:
3308 3309
    if (vm)
        virDomainObjUnlock(vm);
3310 3311
    if (event)
        qemuDomainEventQueue(driver, event);
3312
    qemuDriverUnlock(driver);
3313
    return dom;
D
Daniel P. Berrange 已提交
3314 3315
}

3316
static int qemudDomainUndefine(virDomainPtr dom) {
3317 3318
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3319
    virDomainEventPtr event = NULL;
3320
    int ret = -1;
D
Daniel P. Berrange 已提交
3321

3322
    qemuDriverLock(driver);
3323
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3324

D
Daniel P. Berrange 已提交
3325
    if (!vm) {
3326 3327
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3328
        goto cleanup;
D
Daniel P. Berrange 已提交
3329 3330
    }

3331
    if (virDomainIsActive(vm)) {
3332 3333
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot delete active domain"));
3334
        goto cleanup;
D
Daniel P. Berrange 已提交
3335 3336
    }

3337 3338 3339
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot undefine transient domain"));
3340
        goto cleanup;
3341 3342 3343
    }

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

3346 3347 3348
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
3349

3350 3351
    virDomainRemoveInactive(&driver->domains,
                            vm);
3352
    vm = NULL;
3353
    ret = 0;
D
Daniel P. Berrange 已提交
3354

3355
cleanup:
3356 3357
    if (vm)
        virDomainObjUnlock(vm);
3358 3359
    if (event)
        qemuDomainEventQueue(driver, event);
3360
    qemuDriverUnlock(driver);
3361
    return ret;
D
Daniel P. Berrange 已提交
3362 3363
}

3364
/* Return the disks name for use in monitor commands */
3365
static char *qemudDiskDeviceName(const virConnectPtr conn,
3366
                                 const virDomainDiskDefPtr disk) {
3367 3368 3369 3370 3371 3372

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

    if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) {
3373
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
3374 3375 3376 3377 3378 3379 3380
                         _("cannot convert disk '%s' to bus/device index"),
                         disk->dst);
        return NULL;
    }

    switch (disk->bus) {
        case VIR_DOMAIN_DISK_BUS_IDE:
3381
            if (disk->device== VIR_DOMAIN_DISK_DEVICE_DISK)
3382
                ret = virAsprintf(&devname, "ide%d-hd%d", busid, devid);
3383
            else
3384
                ret = virAsprintf(&devname, "ide%d-cd%d", busid, devid);
3385 3386
            break;
        case VIR_DOMAIN_DISK_BUS_SCSI:
3387
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
3388
                ret = virAsprintf(&devname, "scsi%d-hd%d", busid, devid);
3389
            else
3390
                ret = virAsprintf(&devname, "scsi%d-cd%d", busid, devid);
3391 3392
            break;
        case VIR_DOMAIN_DISK_BUS_FDC:
3393
            ret = virAsprintf(&devname, "floppy%d", devid);
3394 3395
            break;
        case VIR_DOMAIN_DISK_BUS_VIRTIO:
3396
            ret = virAsprintf(&devname, "virtio%d", devid);
3397 3398
            break;
        default:
3399
            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
3400 3401 3402 3403 3404 3405
                             _("Unsupported disk name mapping for bus '%s'"),
                             virDomainDiskBusTypeToString(disk->bus));
            return NULL;
    }

    if (ret == -1) {
3406
        virReportOOMError(conn);
3407 3408 3409 3410 3411 3412
        return NULL;
    }

    return devname;
}

3413 3414
static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
                                           virDomainObjPtr vm,
3415 3416
                                           virDomainDeviceDefPtr dev)
{
3417
    virDomainDiskDefPtr origdisk = NULL, newdisk;
3418
    char *cmd, *reply, *safe_path;
3419
    char *devname = NULL;
3420
    unsigned int qemuCmdFlags;
3421
    int i;
3422

3423
    origdisk = NULL;
3424
    newdisk = dev->data.disk;
3425 3426 3427 3428
    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];
3429
            break;
3430
        }
3431 3432 3433
    }

    if (!origdisk) {
3434
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3435 3436 3437 3438 3439 3440 3441 3442 3443
                         _("No device with bus '%s' and target '%s'"),
                         virDomainDiskBusTypeToString(newdisk->bus),
                         newdisk->dst);
        return -1;
    }

    if (qemudExtractVersionInfo(vm->def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0) {
3444
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3445 3446 3447 3448 3449 3450
                         _("Cannot determine QEMU argv syntax %s"),
                         vm->def->emulator);
        return -1;
    }

    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
3451
        if (!(devname = qemudDiskDeviceName(conn, newdisk)))
3452 3453 3454 3455 3456 3457 3458 3459 3460
            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 {
3461
            qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3462 3463 3464 3465 3466 3467 3468 3469
                             _("Emulator version does not support removable "
                               "media for device '%s' and target '%s'"),
                               virDomainDiskDeviceTypeToString(newdisk->device),
                               newdisk->dst);
            return -1;
        }

        if (!devname) {
3470
            virReportOOMError(conn);
3471 3472 3473
            return -1;
        }
    }
3474

3475
    if (newdisk->src) {
3476 3477
        safe_path = qemudEscapeMonitorArg(newdisk->src);
        if (!safe_path) {
3478
            virReportOOMError(conn);
3479
            VIR_FREE(devname);
3480 3481
            return -1;
        }
3482
        if (virAsprintf(&cmd, "change %s \"%s\"", devname, safe_path) == -1) {
3483
            virReportOOMError(conn);
3484
            VIR_FREE(safe_path);
3485
            VIR_FREE(devname);
3486 3487
            return -1;
        }
3488
        VIR_FREE(safe_path);
3489

3490
    } else if (virAsprintf(&cmd, "eject %s", devname) == -1) {
3491
        virReportOOMError(conn);
3492
        VIR_FREE(devname);
3493 3494
        return -1;
    }
3495
    VIR_FREE(devname);
3496

3497
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3498
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3499
                         "%s", _("could not change cdrom media"));
3500
        VIR_FREE(cmd);
3501 3502
        return -1;
    }
3503 3504 3505 3506

    /* If the command failed qemu prints:
     * device not found, device is locked ...
     * No message is printed on success it seems */
3507
    DEBUG ("ejectable media change reply: %s", reply);
3508
    if (strstr(reply, "\ndevice ")) {
3509
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3510
                          _("changing cdrom media failed: %s"), reply);
3511 3512 3513 3514
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3515 3516
    VIR_FREE(reply);
    VIR_FREE(cmd);
3517

3518 3519
    VIR_FREE(origdisk->src);
    origdisk->src = newdisk->src;
3520
    newdisk->src = NULL;
3521
    origdisk->type = newdisk->type;
3522 3523 3524
    return 0;
}

3525 3526 3527
static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm,
                                          virDomainDeviceDefPtr dev)
3528 3529
{
    int ret, i;
3530
    char *cmd, *reply, *s;
3531 3532 3533 3534 3535
    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)) {
3536
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3537 3538 3539 3540 3541 3542
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3543
        virReportOOMError(conn);
3544 3545 3546 3547 3548
        return -1;
    }

    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3549
        virReportOOMError(conn);
3550 3551 3552
        return -1;
    }

3553 3554
    ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
                      safe_path, type);
3555 3556
    VIR_FREE(safe_path);
    if (ret == -1) {
3557
        virReportOOMError(conn);
3558 3559 3560
        return ret;
    }

3561
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3562
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3563 3564 3565 3566 3567 3568 3569 3570
                         _("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... */
3571 3572 3573 3574 3575 3576
#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)
3577
            VIR_WARN("%s", _("Unable to parse slot number\n"));
3578
    } else {
3579
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593
                          _("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;
}
3594

3595 3596 3597
static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
                                                 virDomainObjPtr vm,
                                                 virDomainDeviceDefPtr dev)
3598
{
3599 3600
    int ret, i;
    char *safe_path;
3601 3602
    char *cmd, *reply;

3603 3604
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
3605
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3606 3607 3608 3609 3610
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

3611
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3612
        virReportOOMError(conn);
3613
        return -1;
3614 3615
    }

3616 3617
    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3618
        virReportOOMError(conn);
3619 3620 3621
        return -1;
    }

3622
    ret = virAsprintf(&cmd, "usb_add disk:%s", safe_path);
3623
    VIR_FREE(safe_path);
3624
    if (ret == -1) {
3625
        virReportOOMError(conn);
3626 3627 3628
        return ret;
    }

3629
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3630
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3631
                         "%s", _("cannot attach usb disk"));
3632 3633 3634 3635 3636 3637 3638 3639
        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 ")) {
3640
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3641
                          "%s",
3642
                          _("adding usb disk failed"));
3643 3644 3645 3646
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3647

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

3652 3653 3654 3655 3656
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return 0;
}

3657 3658 3659
static int qemudDomainAttachHostDevice(virConnectPtr conn,
                                       virDomainObjPtr vm,
                                       virDomainDeviceDefPtr dev)
3660 3661 3662 3663
{
    int ret;
    char *cmd, *reply;

3664
    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
3665
        virReportOOMError(conn);
3666 3667
        return -1;
    }
3668

3669
    if (dev->data.hostdev->source.subsys.u.usb.vendor) {
3670 3671 3672
        ret = virAsprintf(&cmd, "usb_add host:%.4x:%.4x",
                          dev->data.hostdev->source.subsys.u.usb.vendor,
                          dev->data.hostdev->source.subsys.u.usb.product);
3673
    } else {
3674 3675 3676
        ret = virAsprintf(&cmd, "usb_add host:%.3d.%.3d",
                          dev->data.hostdev->source.subsys.u.usb.bus,
                          dev->data.hostdev->source.subsys.u.usb.device);
3677 3678
    }
    if (ret == -1) {
3679
        virReportOOMError(conn);
3680 3681 3682
        return -1;
    }

3683
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3684
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3685 3686 3687 3688 3689 3690 3691 3692 3693
                         "%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 ")) {
3694
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3695 3696 3697 3698 3699 3700
                          "%s",
                          _("adding usb device failed"));
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3701

3702
    vm->def->hostdevs[vm->def->nhostdevs++] = dev->data.hostdev;
3703

3704 3705
    VIR_FREE(reply);
    VIR_FREE(cmd);
3706 3707 3708
    return 0;
}

3709 3710
static int qemudDomainAttachDevice(virDomainPtr dom,
                                   const char *xml) {
3711 3712 3713 3714
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
3715

3716
    qemuDriverLock(driver);
3717
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3718
    if (!vm) {
3719
        qemuDriverUnlock(driver);
3720 3721
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3722
        goto cleanup;
3723 3724 3725
    }

    if (!virDomainIsActive(vm)) {
3726
        qemuDriverUnlock(driver);
3727 3728
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot attach device on inactive domain"));
3729
        goto cleanup;
3730 3731
    }

3732 3733
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
3734
    qemuDriverUnlock(driver);
3735 3736 3737
    if (dev == NULL)
        goto cleanup;

3738

3739 3740
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        switch (dev->data.disk->device) {
3741 3742
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
        case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
3743
            ret = qemudDomainChangeEjectableMedia(dom->conn, vm, dev);
3744
            break;
3745

3746 3747
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
3748
                ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, vm, dev);
3749 3750
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
                       dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
3751
                ret = qemudDomainAttachPciDiskDevice(dom->conn, vm, dev);
3752 3753 3754 3755 3756
            } else {
                qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                                 _("disk bus '%s' cannot be hotplugged."),
                                 virDomainDiskBusTypeToString(dev->data.disk->bus));
                goto cleanup;
3757
            }
3758 3759
            if (driver->securityDriver)
                driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev);
3760
            break;
3761

3762 3763
        default:
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
3764 3765
                             _("disk device type '%s' cannot be hotplugged"),
                             virDomainDiskDeviceTypeToString(dev->data.disk->device));
3766
            goto cleanup;
3767
        }
3768
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
3769 3770
               dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
               dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
3771
        ret = qemudDomainAttachHostDevice(dom->conn, vm, dev);
3772
    } else {
3773
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
3774 3775
                         _("device type '%s' cannot be attached"),
                         virDomainDeviceTypeToString(dev->type));
3776
        goto cleanup;
3777 3778
    }

3779 3780 3781
    if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        ret = -1;

3782
cleanup:
G
Guido Günther 已提交
3783 3784
    if (ret < 0)
        virDomainDeviceDefFree(dev);
3785 3786
    if (vm)
        virDomainObjUnlock(vm);
3787 3788 3789
    return ret;
}

3790 3791
static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3792 3793
{
    int i, ret = -1;
3794 3795
    char *cmd = NULL;
    char *reply = NULL;
3796 3797 3798 3799 3800 3801 3802 3803 3804 3805
    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) {
3806
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3807
                         _("disk %s not found"), dev->data.disk->dst);
3808
        goto cleanup;
3809 3810 3811
    }

    if (detach->slotnum < 1) {
3812
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3813
                         _("disk %s cannot be detached - invalid slot number %d"),
3814
                           detach->dst, detach->slotnum);
3815
        goto cleanup;
3816 3817
    }

3818
    if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
3819
        virReportOOMError(conn);
3820
        goto cleanup;
3821 3822
    }

3823
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3824
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3825
                          _("failed to execute detach disk %s command"), detach->dst);
3826
        goto cleanup;
3827 3828 3829 3830 3831 3832
    }

    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")) {
3833
        qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3834
                          _("failed to detach disk %s: invalid slot %d"),
3835 3836
                          detach->dst, detach->slotnum);
        goto cleanup;
3837 3838 3839 3840 3841
    }

    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) {
3842
            virReportOOMError(conn);
3843
            goto cleanup;
3844 3845 3846 3847 3848 3849 3850 3851
        }
        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;
3852 3853

cleanup:
3854 3855 3856 3857 3858 3859 3860
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}

static int qemudDomainDetachDevice(virDomainPtr dom,
                                   const char *xml) {
3861 3862 3863 3864
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
3865

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

    if (!virDomainIsActive(vm)) {
3876
        qemuDriverUnlock(driver);
3877
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
G
Guido Günther 已提交
3878
                         "%s", _("cannot detach device on inactive domain"));
3879
        goto cleanup;
3880 3881
    }

3882 3883
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
3884
    qemuDriverUnlock(driver);
3885 3886 3887
    if (dev == NULL)
        goto cleanup;

3888 3889 3890 3891

    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 ||
3892
         dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)) {
3893
        ret = qemudDomainDetachPciDiskDevice(dom->conn, vm, dev);
3894 3895 3896
        if (driver->securityDriver)
            driver->securityDriver->domainRestoreSecurityImageLabel(dom->conn, vm, dev);
    }
3897
    else
3898 3899 3900
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("only SCSI or virtio disk device can be detached dynamically"));

3901 3902 3903
    if (!ret && qemudSaveDomainStatus(dom->conn, driver, vm) < 0)
        ret = -1;

3904 3905
cleanup:
    virDomainDeviceDefFree(dev);
3906 3907
    if (vm)
        virDomainObjUnlock(vm);
3908 3909 3910
    return ret;
}

3911
static int qemudDomainGetAutostart(virDomainPtr dom,
3912
                                   int *autostart) {
3913 3914 3915
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3916

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

3921
    if (!vm) {
3922 3923
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3924
        goto cleanup;
3925 3926 3927
    }

    *autostart = vm->autostart;
3928
    ret = 0;
3929

3930
cleanup:
3931 3932
    if (vm)
        virDomainObjUnlock(vm);
3933
    return ret;
3934 3935
}

3936
static int qemudDomainSetAutostart(virDomainPtr dom,
3937
                                   int autostart) {
3938 3939
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3940 3941
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
3942

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

3947
    if (!vm) {
3948 3949
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3950
        goto cleanup;
3951 3952
    }

3953 3954 3955
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot set autostart for transient domain"));
3956
        goto cleanup;
3957 3958
    }

3959 3960
    autostart = (autostart != 0);

3961 3962 3963 3964 3965
    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;
3966

3967 3968
        if (autostart) {
            int err;
3969

3970
            if ((err = virFileMakePath(driver->autostartDir))) {
3971 3972 3973
                virReportSystemError(dom->conn, err,
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
3974 3975
                goto cleanup;
            }
3976

3977
            if (symlink(configFile, autostartLink) < 0) {
3978 3979 3980
                virReportSystemError(dom->conn, errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
3981 3982 3983 3984
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
3985 3986 3987
                virReportSystemError(dom->conn, errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
3988 3989
                goto cleanup;
            }
3990 3991
        }

3992
        vm->autostart = autostart;
3993
    }
3994
    ret = 0;
3995

3996 3997 3998
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
3999 4000
    if (vm)
        virDomainObjUnlock(vm);
4001
    return ret;
4002 4003
}

4004 4005 4006 4007 4008 4009 4010 4011 4012
/* 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)
{
4013
    struct qemud_driver *driver = dom->conn->privateData;
4014
    char *dummy, *info = NULL;
4015
    const char *p, *eol;
4016
    const char *qemu_dev_name = NULL;
4017
    size_t len;
4018
    int i, ret = -1;
4019
    virDomainObjPtr vm;
4020
    virDomainDiskDefPtr disk = NULL;
4021

4022
    qemuDriverLock(driver);
4023
    vm = virDomainFindByID(&driver->domains, dom->id);
4024
    qemuDriverUnlock(driver);
4025 4026 4027
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4028
        goto cleanup;
4029
    }
4030
    if (!virDomainIsActive (vm)) {
4031 4032
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
4033
        goto cleanup;
4034 4035
    }

4036 4037 4038 4039 4040 4041 4042 4043
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(path, vm->def->disks[i]->dst)) {
            disk = vm->def->disks[i];
            break;
        }
    }

    if (!disk) {
4044 4045
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          _("invalid path: %s"), path);
4046
        goto cleanup;
4047 4048
    }

4049
    qemu_dev_name = qemudDiskDeviceName(dom->conn, disk);
4050
    if (!qemu_dev_name)
4051
        goto cleanup;
4052 4053
    len = strlen (qemu_dev_name);

4054
    if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) {
4055 4056
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("'info blockstats' command failed"));
4057
        goto cleanup;
4058 4059 4060 4061 4062 4063 4064 4065
    }
    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 已提交
4066
    if (strstr(info, "\ninfo ")) {
4067 4068 4069
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s",
                          _("'info blockstats' not supported by this qemu"));
4070
        goto cleanup;
4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096
    }

    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) {
4097
                if (STRPREFIX (p, "rd_bytes=")) {
4098 4099 4100
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1)
                        DEBUG ("error reading rd_bytes: %s", p);
4101
                } else if (STRPREFIX (p, "wr_bytes=")) {
4102 4103 4104
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1)
                        DEBUG ("error reading wr_bytes: %s", p);
4105
                } else if (STRPREFIX (p, "rd_operations=")) {
4106 4107 4108
                    p += 14;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1)
                        DEBUG ("error reading rd_req: %s", p);
4109
                } else if (STRPREFIX (p, "wr_operations=")) {
4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120
                    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++;
            }
4121
            ret = 0;
4122
            goto cleanup;
4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133
        }

        /* 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);
4134
 cleanup:
4135 4136
    VIR_FREE(qemu_dev_name);
    VIR_FREE(info);
4137 4138
    if (vm)
        virDomainObjUnlock(vm);
4139
    return ret;
4140 4141
}

4142
#ifdef __linux__
4143 4144 4145 4146 4147
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path,
                           struct _virDomainInterfaceStats *stats)
{
4148 4149
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4150
    int i;
4151
    int ret = -1;
4152

4153
    qemuDriverLock(driver);
4154
    vm = virDomainFindByID(&driver->domains, dom->id);
4155 4156
    qemuDriverUnlock(driver);

4157 4158
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
4159
                          _("no domain with matching id %d"), dom->id);
4160
        goto cleanup;
4161 4162
    }

4163
    if (!virDomainIsActive(vm)) {
4164
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
4165
                         "%s", _("domain is not running"));
4166
        goto cleanup;
4167 4168 4169 4170
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
4171
                         "%s", _("NULL or empty path"));
4172
        goto cleanup;
4173 4174 4175
    }

    /* Check the path is one of the domain's network interfaces. */
4176 4177
    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (vm->def->nets[i]->ifname &&
4178 4179 4180 4181
            STREQ (vm->def->nets[i]->ifname, path)) {
            ret = 0;
            break;
        }
4182 4183
    }

4184 4185 4186 4187 4188
    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);
4189

4190
cleanup:
4191 4192
    if (vm)
        virDomainObjUnlock(vm);
4193 4194
    return ret;
}
4195
#else
4196 4197 4198 4199
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path ATTRIBUTE_UNUSED,
                           struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
4200 4201 4202 4203
    qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                      "%s", __FUNCTION__);
    return -1;
}
4204
#endif
4205

4206 4207 4208 4209 4210 4211 4212
static int
qemudDomainBlockPeek (virDomainPtr dom,
                      const char *path,
                      unsigned long long offset, size_t size,
                      void *buffer,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
4213 4214 4215
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int fd = -1, ret = -1, i;
4216

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

4221 4222
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
4223
                          "%s", _("no domain with matching uuid"));
4224
        goto cleanup;
4225 4226 4227 4228
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
4229
                         "%s", _("NULL or empty path"));
4230
        goto cleanup;
4231 4232 4233
    }

    /* Check the path belongs to this domain. */
4234 4235
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (vm->def->disks[i]->src != NULL &&
4236 4237 4238 4239
            STREQ (vm->def->disks[i]->src, path)) {
            ret = 0;
            break;
        }
4240 4241
    }

4242 4243 4244 4245 4246
    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) {
4247 4248
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to open"), path);
4249 4250
            goto cleanup;
        }
4251

4252 4253 4254 4255 4256 4257
        /* 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) {
4258 4259
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to seek or read"), path);
4260 4261 4262 4263 4264 4265 4266
            goto cleanup;
        }

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

4269 4270 4271
cleanup:
    if (fd >= 0)
        close (fd);
4272 4273
    if (vm)
        virDomainObjUnlock(vm);
4274 4275 4276
    return ret;
}

R
Richard W.M. Jones 已提交
4277 4278 4279 4280 4281 4282
static int
qemudDomainMemoryPeek (virDomainPtr dom,
                       unsigned long long offset, size_t size,
                       void *buffer,
                       unsigned int flags)
{
4283 4284 4285
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char cmd[256], *info = NULL;
R
Richard W.M. Jones 已提交
4286 4287 4288
    char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
    int fd = -1, ret = -1;

4289
    qemuDriverLock(driver);
4290
    vm = virDomainFindByID(&driver->domains, dom->id);
4291
    qemuDriverUnlock(driver);
R
Richard W.M. Jones 已提交
4292 4293 4294 4295

    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4296 4297 4298 4299 4300 4301 4302
        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 已提交
4303 4304
    }

4305
    if (!virDomainIsActive(vm)) {
R
Richard W.M. Jones 已提交
4306 4307
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
4308
        goto cleanup;
R
Richard W.M. Jones 已提交
4309 4310 4311 4312
    }

    /* Create a temporary filename. */
    if ((fd = mkstemp (tmp)) == -1) {
4313 4314
        virReportSystemError (dom->conn, errno,
                              _("mkstemp(\"%s\") failed"), tmp);
4315
        goto cleanup;
R
Richard W.M. Jones 已提交
4316 4317 4318 4319
    }

    /* Issue the memsave command. */
    snprintf (cmd, sizeof cmd, "memsave %llu %zi \"%s\"", offset, size, tmp);
4320
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
R
Richard W.M. Jones 已提交
4321
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
4322
                          "%s", _("'memsave' command failed"));
4323
        goto cleanup;
R
Richard W.M. Jones 已提交
4324 4325 4326 4327 4328 4329
    }

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

    /* Read the memory file into buffer. */
    if (saferead (fd, buffer, size) == (ssize_t) -1) {
4330 4331 4332
        virReportSystemError (dom->conn, errno,
                              _("failed to read temporary file "
                                "created with template %s"), tmp);
4333
        goto cleanup;
R
Richard W.M. Jones 已提交
4334 4335 4336
    }

    ret = 0;
4337 4338 4339

cleanup:
    VIR_FREE(info);
R
Richard W.M. Jones 已提交
4340 4341
    if (fd >= 0) close (fd);
    unlink (tmp);
4342 4343
    if (vm)
        virDomainObjUnlock(vm);
R
Richard W.M. Jones 已提交
4344 4345 4346
    return ret;
}

4347

4348 4349
static int
qemudDomainEventRegister (virConnectPtr conn,
4350
                          virConnectDomainEventCallback callback,
4351 4352
                          void *opaque,
                          virFreeCallback freecb)
4353
{
4354 4355 4356
    struct qemud_driver *driver = conn->privateData;
    int ret;

4357
    qemuDriverLock(driver);
4358 4359
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
4360
    qemuDriverUnlock(driver);
4361

4362
    return ret;
4363 4364 4365 4366
}

static int
qemudDomainEventDeregister (virConnectPtr conn,
4367
                            virConnectDomainEventCallback callback)
4368
{
4369 4370 4371
    struct qemud_driver *driver = conn->privateData;
    int ret;

4372
    qemuDriverLock(driver);
4373 4374 4375 4376 4377 4378
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
4379
    qemuDriverUnlock(driver);
4380

4381
    return ret;
4382 4383
}

4384 4385 4386 4387 4388
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
                                        virConnectDomainEventCallback cb,
                                        void *cbopaque,
                                        void *opaque)
4389
{
4390
    struct qemud_driver *driver = opaque;
4391

4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435
    /* 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);
4436 4437
}

D
Daniel Veillard 已提交
4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455
/* 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;
4456 4457
    struct qemud_driver *driver = dconn->privateData;
    virDomainDefPtr def = NULL;
D
Daniel Veillard 已提交
4458 4459 4460 4461 4462
    virDomainObjPtr vm = NULL;
    int this_port;
    char hostname [HOST_NAME_MAX+1];
    char migrateFrom [64];
    const char *p;
4463
    virDomainEventPtr event = NULL;
4464 4465 4466
    int ret = -1;;

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

4468
    qemuDriverLock(driver);
D
Daniel Veillard 已提交
4469 4470 4471
    if (!dom_xml) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          "%s", _("no domain XML passed"));
4472
        goto cleanup;
D
Daniel Veillard 已提交
4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490
    }

    /* 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) {
4491 4492
            virReportSystemError (dconn, errno,
                                  "%s", _("failed to determine host name"));
4493
            goto cleanup;
D
Daniel Veillard 已提交
4494 4495 4496
        }

        /* Caller frees */
4497
        if (virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) {
4498
            virReportOOMError (dconn);
4499
            goto cleanup;
D
Daniel Veillard 已提交
4500 4501 4502 4503 4504 4505 4506 4507 4508
        }
    } else {
        /* Check the URI starts with "tcp:".  We will escape the
         * URI when passing it to the qemu monitor, so bad
         * characters in hostname part don't matter.
         */
        if (!STREQLEN (uri_in, "tcp:", 6)) {
            qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG,
                  "%s", _("only tcp URIs are supported for KVM migrations"));
4509
            goto cleanup;
D
Daniel Veillard 已提交
4510 4511 4512 4513 4514 4515 4516 4517 4518
        }

        /* 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"));
4519
            goto cleanup;
D
Daniel Veillard 已提交
4520 4521 4522 4523
        }
    }

    /* Parse the domain XML. */
4524 4525
    if (!(def = virDomainDefParseString(dconn, driver->caps, dom_xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
D
Daniel Veillard 已提交
4526 4527
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to parse XML"));
4528
        goto cleanup;
D
Daniel Veillard 已提交
4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544
    }

    /* 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"));
4545
        goto cleanup;
D
Daniel Veillard 已提交
4546 4547 4548 4549 4550 4551 4552 4553 4554
    }
#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);
4555
            goto cleanup;
D
Daniel Veillard 已提交
4556 4557 4558 4559 4560 4561 4562 4563
        }
    }

    if (!(vm = virDomainAssignDef(dconn,
                                  &driver->domains,
                                  def))) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to assign new VM"));
4564
        goto cleanup;
D
Daniel Veillard 已提交
4565
    }
4566
    def = NULL;
D
Daniel Veillard 已提交
4567 4568 4569 4570 4571 4572 4573 4574

    /* 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);
4575
    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
D
Daniel Veillard 已提交
4576 4577
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to start listening VM"));
4578
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4579
            virDomainRemoveInactive(&driver->domains, vm);
4580 4581
            vm = NULL;
        }
4582
        goto cleanup;
D
Daniel Veillard 已提交
4583
    }
4584 4585 4586 4587

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

4590 4591 4592 4593 4594
cleanup:
    virDomainDefFree(def);
    if (ret != 0) {
        VIR_FREE(*uri_out);
    }
4595 4596
    if (vm)
        virDomainObjUnlock(vm);
4597 4598
    if (event)
        qemuDomainEventQueue(driver, event);
4599
    qemuDriverUnlock(driver);
4600
    return ret;
D
Daniel Veillard 已提交
4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612
}

/* 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)
{
4613 4614
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4615
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4616 4617
    char *safe_uri;
    char cmd[HOST_NAME_MAX+50];
4618 4619
    char *info = NULL;
    int ret = -1;
4620
    int paused = 0;
D
Daniel Veillard 已提交
4621

4622
    qemuDriverLock(driver);
4623
    vm = virDomainFindByID(&driver->domains, dom->id);
D
Daniel Veillard 已提交
4624 4625 4626
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4627
        goto cleanup;
D
Daniel Veillard 已提交
4628 4629 4630 4631 4632
    }

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

4636 4637
    if (!(flags & VIR_MIGRATE_LIVE)) {
        /* Pause domain for non-live migration */
4638 4639 4640 4641 4642
        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;
        }
4643 4644
        DEBUG ("stop reply: %s", info);
        VIR_FREE(info);
4645
        paused = 1;
4646

4647 4648 4649 4650 4651 4652
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
        event = NULL;
4653 4654
    }

D
Daniel Veillard 已提交
4655 4656 4657
    if (resource > 0) {
        /* Issue migrate_set_speed command.  Don't worry if it fails. */
        snprintf (cmd, sizeof cmd, "migrate_set_speed %lum", resource);
4658
        qemudMonitorCommand (vm, cmd, &info);
D
Daniel Veillard 已提交
4659 4660 4661 4662 4663 4664 4665 4666

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

    /* Issue the migrate command. */
    safe_uri = qemudEscapeMonitorArg (uri);
    if (!safe_uri) {
4667
        virReportOOMError (dom->conn);
4668
        goto cleanup;
D
Daniel Veillard 已提交
4669 4670 4671 4672
    }
    snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri);
    VIR_FREE (safe_uri);

4673
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
D
Daniel Veillard 已提交
4674 4675
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("migrate operation failed"));
4676
        goto cleanup;
D
Daniel Veillard 已提交
4677 4678 4679 4680 4681 4682 4683 4684
    }

    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);
4685
        goto cleanup;
D
Daniel Veillard 已提交
4686 4687 4688 4689
    }

    /* Clean up the source domain. */
    qemudShutdownVMDaemon (dom->conn, driver, vm);
4690
    paused = 0;
4691 4692 4693 4694

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
4695
    if (!vm->persistent) {
D
Daniel Veillard 已提交
4696
        virDomainRemoveInactive(&driver->domains, vm);
4697 4698
        vm = NULL;
    }
4699
    ret = 0;
D
Daniel Veillard 已提交
4700

4701
cleanup:
4702 4703 4704
    /* Note that we have to free info *first*, since we are re-using the
     * variable below (and otherwise might cause a memory leak)
     */
4705
    VIR_FREE(info);
4706 4707 4708 4709 4710 4711 4712 4713

    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
             */
4714 4715
            VIR_ERROR(_("Failed to resume guest %s after failure\n"),
                      vm->def->name);
4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726
        }
        else {
            DEBUG ("cont reply: %s", info);
            VIR_FREE(info);
        }

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

4727 4728
    if (vm)
        virDomainObjUnlock(vm);
4729 4730
    if (event)
        qemuDomainEventQueue(driver, event);
4731
    qemuDriverUnlock(driver);
4732
    return ret;
D
Daniel Veillard 已提交
4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744
}

/* 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)
{
4745 4746 4747
    struct qemud_driver *driver = dconn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
4748
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4749 4750
    char *info = NULL;

4751
    qemuDriverLock(driver);
4752
    vm = virDomainFindByName(&driver->domains, dname);
D
Daniel Veillard 已提交
4753 4754 4755
    if (!vm) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching name %s"), dname);
4756
        goto cleanup;
D
Daniel Veillard 已提交
4757 4758 4759 4760 4761 4762 4763 4764 4765
    }

    /* 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;
4766 4767 4768
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
D
Daniel Veillard 已提交
4769 4770
    } else {
        qemudShutdownVMDaemon (dconn, driver, vm);
4771 4772 4773
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
4774
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4775
            virDomainRemoveInactive(&driver->domains, vm);
4776 4777
            vm = NULL;
        }
D
Daniel Veillard 已提交
4778
    }
4779 4780

cleanup:
4781 4782
    if (vm)
        virDomainObjUnlock(vm);
4783 4784
    if (event)
        qemuDomainEventQueue(driver, event);
4785
    qemuDriverUnlock(driver);
4786
    return dom;
D
Daniel Veillard 已提交
4787 4788
}

4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903
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;
}

4904 4905 4906 4907 4908
static virDriver qemuDriver = {
    VIR_DRV_QEMU,
    "QEMU",
    qemudOpen, /* open */
    qemudClose, /* close */
D
Daniel Veillard 已提交
4909
    qemudSupportsFeature, /* supports_feature */
4910 4911
    qemudGetType, /* type */
    qemudGetVersion, /* version */
4912
    qemudGetHostname, /* hostname */
4913
    NULL, /* URI  */
4914 4915 4916 4917 4918
    qemudGetMaxVCPUs, /* getMaxVcpus */
    qemudGetNodeInfo, /* nodeGetInfo */
    qemudGetCapabilities, /* getCapabilities */
    qemudListDomains, /* listDomains */
    qemudNumDomains, /* numOfDomains */
4919
    qemudDomainCreate, /* domainCreateXML */
4920 4921 4922 4923 4924
    qemudDomainLookupByID, /* domainLookupByID */
    qemudDomainLookupByUUID, /* domainLookupByUUID */
    qemudDomainLookupByName, /* domainLookupByName */
    qemudDomainSuspend, /* domainSuspend */
    qemudDomainResume, /* domainResume */
4925
    qemudDomainShutdown, /* domainShutdown */
4926 4927 4928
    NULL, /* domainReboot */
    qemudDomainDestroy, /* domainDestroy */
    qemudDomainGetOSType, /* domainGetOSType */
4929 4930 4931
    qemudDomainGetMaxMemory, /* domainGetMaxMemory */
    qemudDomainSetMaxMemory, /* domainSetMaxMemory */
    qemudDomainSetMemory, /* domainSetMemory */
4932 4933 4934 4935
    qemudDomainGetInfo, /* domainGetInfo */
    qemudDomainSave, /* domainSave */
    qemudDomainRestore, /* domainRestore */
    NULL, /* domainCoreDump */
4936
    qemudDomainSetVcpus, /* domainSetVcpus */
4937 4938 4939 4940
#if HAVE_SCHED_GETAFFINITY
    qemudDomainPinVcpu, /* domainPinVcpu */
    qemudDomainGetVcpus, /* domainGetVcpus */
#else
4941 4942
    NULL, /* domainPinVcpu */
    NULL, /* domainGetVcpus */
4943
#endif
4944
    qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
4945 4946
    qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */
    qemudNodeGetSecurityModel, /* nodeGetSecurityModel */
4947 4948 4949 4950 4951 4952
    qemudDomainDumpXML, /* domainDumpXML */
    qemudListDefinedDomains, /* listDomains */
    qemudNumDefinedDomains, /* numOfDomains */
    qemudDomainStart, /* domainCreate */
    qemudDomainDefine, /* domainDefineXML */
    qemudDomainUndefine, /* domainUndefine */
4953
    qemudDomainAttachDevice, /* domainAttachDevice */
4954
    qemudDomainDetachDevice, /* domainDetachDevice */
4955 4956 4957 4958 4959
    qemudDomainGetAutostart, /* domainGetAutostart */
    qemudDomainSetAutostart, /* domainSetAutostart */
    NULL, /* domainGetSchedulerType */
    NULL, /* domainGetSchedulerParameters */
    NULL, /* domainSetSchedulerParameters */
D
Daniel Veillard 已提交
4960 4961
    NULL, /* domainMigratePrepare (v1) */
    qemudDomainMigratePerform, /* domainMigratePerform */
4962
    NULL, /* domainMigrateFinish */
4963
    qemudDomainBlockStats, /* domainBlockStats */
4964
    qemudDomainInterfaceStats, /* domainInterfaceStats */
4965
    qemudDomainBlockPeek, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
4966
    qemudDomainMemoryPeek, /* domainMemoryPeek */
4967 4968 4969 4970
#if HAVE_NUMACTL
    qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    qemudNodeGetFreeMemory,  /* getFreeMemory */
#else
4971
    NULL, /* nodeGetCellsFreeMemory */
4972
    NULL, /* getFreeMemory */
4973
#endif
4974 4975
    qemudDomainEventRegister, /* domainEventRegister */
    qemudDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
4976 4977
    qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
    qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
4978 4979 4980
    qemudNodeDeviceDettach, /* nodeDeviceDettach */
    qemudNodeDeviceReAttach, /* nodeDeviceReAttach */
    qemudNodeDeviceReset, /* nodeDeviceReset */
4981 4982 4983
};


4984
static virStateDriver qemuStateDriver = {
4985 4986 4987 4988
    .initialize = qemudStartup,
    .cleanup = qemudShutdown,
    .reload = qemudReload,
    .active = qemudActive,
4989
};
4990

4991
int qemuRegister(void) {
4992 4993 4994 4995
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}