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

24
#include <config.h>
25

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

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

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

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

72 73
#define VIR_FROM_THIS VIR_FROM_QEMU

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

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


81 82
static int qemudShutdown(void);

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

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

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

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

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

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

113
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
114

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

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


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

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

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


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

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


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


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

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

    virConnectClose(conn);
237 238
}

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

441
    VIR_FREE(base);
442 443 444

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

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

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

460 461
    qemuDriverUnlock(qemu_driver);

462 463
    return 0;

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

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

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

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

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

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

    return 0;
511 512
}

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

526 527 528
    if (!qemu_driver)
        return 0;

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

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

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

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

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

556
    virDomainObjListFree(&qemu_driver->domains);
557

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

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

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

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

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

    return 0;
581 582 583
}

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

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

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

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

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

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

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

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

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

}

static int
666
qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
667
                        virDomainObjPtr vm,
668 669 670 671 672 673 674 675 676 677 678
                        const char *output,
                        int fd)
{
    if (strstr(output, "(qemu) ") == NULL)
        return 1; /* keep reading */

    vm->monitor = fd;

    return 0;
}

679
static int qemudOpenMonitor(virConnectPtr conn,
680
                            struct qemud_driver* driver,
681
                            virDomainObjPtr vm,
682 683
                            const char *monitor,
                            int reconnect) {
684 685 686 687
    int monfd;
    char buf[1024];
    int ret = -1;

D
Daniel Veillard 已提交
688
    if ((monfd = open(monitor, O_RDWR)) < 0) {
689
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
690
                         _("Unable to open monitor path %s"), monitor);
691 692
        return -1;
    }
693
    if (virSetCloseExec(monfd) < 0) {
694
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
695
                         "%s", _("Unable to set monitor close-on-exec flag"));
696 697
        goto error;
    }
698
    if (virSetNonBlock(monfd) < 0) {
699
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
700
                         "%s", _("Unable to put monitor into non-blocking mode"));
701 702 703
        goto error;
    }

704
    if (!reconnect) {
705 706 707 708 709 710 711 712
        if (qemudReadMonitorOutput(conn,
                                   vm, monfd,
                                   buf, sizeof(buf),
                                   qemudCheckMonitorPrompt,
                                   "monitor", 10000) <= 0)
            ret = -1;
        else
            ret = 0;
713 714 715 716 717 718 719
    } else {
        vm->monitor = monfd;
        ret = 0;
    }

    if (ret != 0)
         goto error;
720

721
    if (!(vm->monitorpath = strdup(monitor))) {
722
        virReportOOMError(conn);
723 724 725
        goto error;
    }

726 727 728 729 730 731
    if ((vm->monitor_watch = virEventAddHandle(vm->monitor, 0,
                                               qemudDispatchVMEvent,
                                               driver, NULL)) < 0)
        goto error;


732 733 734 735
    /* Keep monitor open upon success */
    if (ret == 0)
        return ret;

736 737 738 739 740
 error:
    close(monfd);
    return ret;
}

741 742
static int qemudExtractMonitorPath(virConnectPtr conn,
                                   const char *haystack,
743
                                   size_t *offset,
744
                                   char **path) {
745
    static const char needle[] = "char device redirected to";
746
    char *tmp, *dev;
747

748
    VIR_FREE(*path);
749
    /* First look for our magic string */
750 751 752 753 754
    if (!(tmp = strstr(haystack + *offset, needle))) {
        return 1;
    }
    tmp += sizeof(needle);
    dev = tmp;
755

756 757 758 759 760
    /*
     * And look for first whitespace character and nul terminate
     * to mark end of the pty path
     */
    while (*tmp) {
761
        if (c_isspace(*tmp)) {
762
            if (VIR_ALLOC_N(*path, (tmp-dev)+1) < 0) {
763
                virReportOOMError(conn);
764 765 766 767
                return -1;
            }
            strncpy(*path, dev, (tmp-dev));
            (*path)[(tmp-dev)] = '\0';
768
            /* ... now further update offset till we get EOL */
769
            *offset = tmp - haystack;
770 771
            return 0;
        }
772
        tmp++;
773 774 775 776 777
    }

    /*
     * We found a path, but didn't find any whitespace,
     * so it must be still incomplete - we should at
778 779
     * least see a \n - indicate that we want to carry
     * on trying again
780
     */
781
    return 1;
782 783 784
}

static int
785
qemudFindCharDevicePTYs(virConnectPtr conn,
786
                        virDomainObjPtr vm,
787 788
                        const char *output,
                        int fd ATTRIBUTE_UNUSED)
789
{
790
    struct qemud_driver* driver = conn->privateData;
791
    char *monitor = NULL;
792
    size_t offset = 0;
793
    int ret, i;
794 795 796 797 798

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

800
    /* So first comes the monitor device */
801 802
    if ((ret = qemudExtractMonitorPath(conn, output, &offset, &monitor)) != 0)
        goto cleanup;
803

804
    /* then the serial devices */
805 806
    for (i = 0 ; i < vm->def->nserials ; i++) {
        virDomainChrDefPtr chr = vm->def->serials[i];
807 808 809 810
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
811 812 813 814
        }
    }

    /* and finally the parallel devices */
815 816
    for (i = 0 ; i < vm->def->nparallels ; i++) {
        virDomainChrDefPtr chr = vm->def->parallels[i];
817 818 819 820
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
            if ((ret = qemudExtractMonitorPath(conn, output, &offset,
                                               &chr->data.file.path)) != 0)
                goto cleanup;
821 822 823 824
        }
    }

    /* Got them all, so now open the monitor console */
825
    ret = qemudOpenMonitor(conn, driver, vm, monitor, 0);
826 827 828 829

cleanup:
    VIR_FREE(monitor);
    return ret;
830 831
}

832
static int qemudWaitForMonitor(virConnectPtr conn,
833 834 835
                               struct qemud_driver* driver,
                               virDomainObjPtr vm, off_t pos)
{
836
    char buf[1024]; /* Plenty of space to get startup greeting */
837 838 839 840 841
    int logfd;
    int ret;

    if ((logfd = qemudLogReadFD(conn, driver->logDir, vm->def->name, pos))
        < 0)
842
        return -1;
843 844 845 846

    ret = qemudReadMonitorOutput(conn, vm, logfd, buf, sizeof(buf),
                                 qemudFindCharDevicePTYs,
                                 "console", 3000);
847 848
    if (close(logfd) < 0) {
        char ebuf[1024];
849
        qemudLog(QEMUD_WARN, _("Unable to close logfile: %s\n"),
850 851
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
852 853 854 855 856 857 858 859 860 861 862

    if (ret == 1) /* Success */
        return 0;

    if (ret == -1)
        return -1;

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

865 866
static int
qemudDetectVcpuPIDs(virConnectPtr conn,
867
                    virDomainObjPtr vm) {
868 869 870 871 872 873
    char *qemucpus = NULL;
    char *line;
    int lastVcpu = -1;

    /* Only KVM has seperate threads for CPUs,
       others just use main QEMU process for CPU */
874
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM)
875 876 877 878 879
        vm->nvcpupids = 1;
    else
        vm->nvcpupids = vm->def->vcpus;

    if (VIR_ALLOC_N(vm->vcpupids, vm->nvcpupids) < 0) {
880
        virReportOOMError(conn);
881 882 883
        return -1;
    }

884
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
885 886 887 888
        vm->vcpupids[0] = vm->pid;
        return 0;
    }

889
    if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) {
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
        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;

948
    VIR_FREE(qemucpus);
949 950 951 952
    return 0;

error:
    VIR_FREE(vm->vcpupids);
953 954
    vm->nvcpupids = 0;
    VIR_FREE(qemucpus);
955 956 957 958 959 960 961 962

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

963 964
static int
qemudInitCpus(virConnectPtr conn,
D
Daniel Veillard 已提交
965 966
              virDomainObjPtr vm,
              const char *migrateFrom) {
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
    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 已提交
982 983 984 985 986 987
    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++)
988
            CPU_SET(i, &mask);
D
Daniel P. Berrange 已提交
989
    }
990 991 992 993

    for (i = 0 ; i < vm->nvcpupids ; i++) {
        if (sched_setaffinity(vm->vcpupids[i],
                              sizeof(mask), &mask) < 0) {
994 995
            virReportSystemError(conn, errno, "%s",
                                 _("failed to set CPU affinity"));
996 997 998 999 1000
            return -1;
        }
    }
#endif /* HAVE_SCHED_GETAFFINITY */

D
Daniel Veillard 已提交
1001 1002
    if (migrateFrom == NULL) {
        /* Allow the CPUS to start executing */
1003
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
D
Daniel Veillard 已提交
1004 1005 1006 1007 1008
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                             "%s", _("resume operation failed"));
            return -1;
        }
        VIR_FREE(info);
1009 1010 1011 1012 1013 1014
    }

    return 0;
}


1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
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 &&
1029
        (vm->def->graphics->data.vnc.passwd || driver->vncPassword)) {
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047

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


1048
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
    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;
}

1084 1085 1086
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
                                            const char *name);

1087 1088
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
1089
                              virDomainObjPtr vm,
1090 1091
                              const char *migrateFrom,
                              int stdin_fd) {
1092
    const char **argv = NULL, **tmp;
1093
    const char **progenv = NULL;
1094
    int i, ret;
1095
    struct stat sb;
1096 1097
    int *tapfds = NULL;
    int ntapfds = 0;
1098
    unsigned int qemuCmdFlags;
1099
    fd_set keepfd;
1100
    const char *emulator;
G
Guido Günther 已提交
1101
    pid_t child;
1102
    int pos = -1;
1103
    char ebuf[1024];
1104 1105

    FD_ZERO(&keepfd);
1106

1107
    if (virDomainIsActive(vm)) {
1108
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
1109
                         "%s", _("VM is already active"));
1110 1111 1112
        return -1;
    }

1113 1114 1115
    if (vm->def->graphics &&
        vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics->data.vnc.autoport) {
1116
        int port = qemudNextFreeVNCPort(driver);
1117
        if (port < 0) {
1118
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
1119
                             "%s", _("Unable to find an unused VNC port"));
1120 1121
            return -1;
        }
1122 1123
        vm->def->graphics->data.vnc.port = port;
    }
1124

1125
    if (virFileMakePath(driver->logDir) < 0) {
1126 1127 1128
        virReportSystemError(conn, errno,
                             _("cannot create log directory %s"),
                             driver->logDir);
1129 1130 1131
        return -1;
    }

1132
    if((vm->logfile = qemudLogFD(conn, driver->logDir, vm->def->name)) < 0)
1133 1134
        return -1;

1135 1136 1137 1138 1139 1140
    emulator = vm->def->emulator;
    if (!emulator)
        emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
    if (!emulator)
        return -1;

1141 1142 1143 1144
    /* 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
     */
1145
    if (stat(emulator, &sb) < 0) {
1146 1147 1148
        virReportSystemError(conn, errno,
                             _("Cannot find QEMU binary %s"),
                             emulator);
1149 1150 1151
        return -1;
    }

1152
    if (qemudExtractVersionInfo(emulator,
1153 1154 1155 1156
                                NULL,
                                &qemuCmdFlags) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                         _("Cannot determine QEMU argv syntax %s"),
1157
                         emulator);
1158 1159
        return -1;
    }
1160

1161
    vm->def->id = driver->nextvmid++;
1162
    if (qemudBuildCommandLine(conn, driver, vm,
1163
                              qemuCmdFlags, &argv, &progenv,
1164
                              &tapfds, &ntapfds, migrateFrom) < 0) {
1165
        close(vm->logfile);
1166
        vm->def->id = -1;
1167 1168 1169 1170
        vm->logfile = -1;
        return -1;
    }

1171 1172 1173
    tmp = progenv;
    while (*tmp) {
        if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
1174
            qemudLog(QEMUD_WARN, _("Unable to write envv to logfile: %s\n"),
1175
                     virStrerror(errno, ebuf, sizeof ebuf));
1176
        if (safewrite(vm->logfile, " ", 1) < 0)
1177
            qemudLog(QEMUD_WARN, _("Unable to write envv to logfile: %s\n"),
1178
                     virStrerror(errno, ebuf, sizeof ebuf));
1179 1180
        tmp++;
    }
1181 1182
    tmp = argv;
    while (*tmp) {
1183
        if (safewrite(vm->logfile, *tmp, strlen(*tmp)) < 0)
1184
            qemudLog(QEMUD_WARN, _("Unable to write argv to logfile: %s\n"),
1185
                     virStrerror(errno, ebuf, sizeof ebuf));
1186
        if (safewrite(vm->logfile, " ", 1) < 0)
1187
            qemudLog(QEMUD_WARN, _("Unable to write argv to logfile: %s\n"),
1188
                     virStrerror(errno, ebuf, sizeof ebuf));
1189 1190
        tmp++;
    }
1191
    if (safewrite(vm->logfile, "\n", 1) < 0)
1192
        qemudLog(QEMUD_WARN, _("Unable to write argv to logfile: %s\n"),
1193
                 virStrerror(errno, ebuf, sizeof ebuf));
1194

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

1199 1200 1201
    for (i = 0 ; i < ntapfds ; i++)
        FD_SET(tapfds[i], &keepfd);

G
Guido Günther 已提交
1202
    ret = virExec(conn, argv, progenv, &keepfd, &child,
1203
                  stdin_fd, &vm->logfile, &vm->logfile,
G
Guido Günther 已提交
1204 1205 1206 1207 1208
                  VIR_EXEC_NONBLOCK | VIR_EXEC_DAEMON);

    /* wait for qemu process to to show up */
    if (ret == 0) {
        int retries = 100;
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
        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--;
            }
            if (ret)
                qemudLog(QEMUD_WARN, _("Domain %s didn't show up\n"), vm->def->name);
        } else {
            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1225
                             "%s", _("Unable to daemonize QEMU process"));
1226
            ret = -1;
G
Guido Günther 已提交
1227 1228 1229 1230
        }
    }

    if (ret == 0) {
1231
        vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
G
Guido Günther 已提交
1232
    } else
1233
        vm->def->id = -1;
1234

1235
    for (i = 0 ; argv[i] ; i++)
1236 1237
        VIR_FREE(argv[i]);
    VIR_FREE(argv);
1238

1239 1240 1241 1242
    for (i = 0 ; progenv[i] ; i++)
        VIR_FREE(progenv[i]);
    VIR_FREE(progenv);

1243 1244 1245
    if (tapfds) {
        for (i = 0 ; i < ntapfds ; i++) {
            close(tapfds[i]);
1246
        }
1247
        VIR_FREE(tapfds);
1248 1249
    }

1250
    if (ret == 0) {
1251
        if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
1252
            (qemudDetectVcpuPIDs(conn, vm) < 0) ||
1253 1254
            (qemudInitCpus(conn, vm, migrateFrom) < 0) ||
            (qemudInitPasswords(conn, driver, vm) < 0)) {
1255 1256 1257
            qemudShutdownVMDaemon(conn, driver, vm);
            return -1;
        }
1258
    }
1259
    qemudSaveDomainStatus(conn, qemu_driver, vm);
1260

1261
    return ret;
1262 1263 1264
}


1265
static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
1266 1267
                                  struct qemud_driver *driver,
                                  virDomainObjPtr vm) {
1268
    if (!virDomainIsActive(vm))
1269
        return;
1270

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

G
Guido Günther 已提交
1273 1274
    if (virKillProcess(vm->pid, 0) == 0 &&
        virKillProcess(vm->pid, SIGTERM) < 0)
1275 1276 1277
        virReportSystemError(conn, errno,
                             _("Failed to send SIGTERM to %s (%d)"),
                             vm->def->name, vm->pid);
1278

1279 1280 1281 1282
    if (vm->monitor_watch != -1) {
        virEventRemoveHandle(vm->monitor_watch);
        vm->monitor_watch = -1;
    }
1283

1284 1285
    if (close(vm->logfile) < 0) {
        char ebuf[1024];
1286
        qemudLog(QEMUD_WARN, _("Unable to close logfile: %s\n"),
1287 1288
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1289 1290 1291 1292 1293
    if (vm->monitor != -1)
        close(vm->monitor);
    vm->logfile = -1;
    vm->monitor = -1;

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

G
Guido Günther 已提交
1297
    qemudRemoveDomainStatus(conn, driver, vm);
1298
    vm->pid = -1;
1299
    vm->def->id = -1;
1300
    vm->state = VIR_DOMAIN_SHUTOFF;
1301
    VIR_FREE(vm->vcpupids);
1302
    vm->nvcpupids = 0;
1303 1304

    if (vm->newDef) {
1305
        virDomainDefFree(vm->def);
1306
        vm->def = vm->newDef;
1307
        vm->def->id = -1;
1308 1309 1310 1311 1312
        vm->newDef = NULL;
    }
}


1313
static void
1314
qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
1315
    struct qemud_driver *driver = opaque;
1316
    virDomainObjPtr vm = NULL;
1317
    virDomainEventPtr event = NULL;
1318
    unsigned int i;
1319
    int quit = 0, failed = 0;
1320

1321
    qemuDriverLock(driver);
1322
    for (i = 0 ; i < driver->domains.count ; i++) {
1323 1324 1325
        virDomainObjPtr tmpvm = driver->domains.objs[i];
        virDomainObjLock(tmpvm);
        if (virDomainIsActive(tmpvm) &&
1326
            tmpvm->monitor_watch == watch) {
1327
            vm = tmpvm;
1328
            break;
1329
        }
1330
        virDomainObjUnlock(tmpvm);
1331 1332 1333
    }

    if (!vm)
1334
        goto cleanup;
1335

1336
    if (vm->monitor != fd) {
1337 1338
        failed = 1;
    } else {
1339
        if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
1340
            quit = 1;
1341 1342 1343 1344
        else {
            qemudLog(QEMUD_ERROR, _("unhandled fd event %d for %s"),
                                    events, vm->def->name);
            failed = 1;
1345
        }
1346 1347
    }

1348
    if (failed || quit) {
1349 1350 1351 1352 1353
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         quit ?
                                         VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364
        qemudShutdownVMDaemon(NULL, driver, vm);
        if (!vm->persistent) {
            virDomainRemoveInactive(&driver->domains,
                                    vm);
            vm = NULL;
        }
    }

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
1365 1366
    if (event)
        qemuDomainEventQueue(driver, event);
1367
    qemuDriverUnlock(driver);
1368 1369
}

1370
static int
1371 1372 1373 1374 1375
qemudMonitorCommandExtra(const virDomainObjPtr vm,
                         const char *cmd,
                         const char *extra,
                         const char *extraPrompt,
                         char **reply) {
D
Daniel P. Berrange 已提交
1376 1377
    int size = 0;
    char *buf = NULL;
1378
    size_t cmdlen = strlen(cmd);
1379
    size_t extralen = extra ? strlen(extra) : 0;
D
Daniel P. Berrange 已提交
1380

1381 1382 1383
    if (safewrite(vm->monitor, cmd, cmdlen) != cmdlen)
        return -1;
    if (safewrite(vm->monitor, "\r", 1) != 1)
D
Daniel P. Berrange 已提交
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
        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 已提交
1396

1397 1398
            if (got == 0)
                goto error;
D
Daniel P. Berrange 已提交
1399 1400 1401 1402 1403
            if (got < 0) {
                if (errno == EINTR)
                    continue;
                if (errno == EAGAIN)
                    break;
1404
                goto error;
1405
            }
1406
            if (VIR_REALLOC_N(buf, size+got+1) < 0)
1407 1408
                goto error;

D
Daniel P. Berrange 已提交
1409 1410 1411 1412
            memmove(buf+size, data, got);
            buf[size+got] = '\0';
            size += got;
        }
1413

D
Daniel P. Berrange 已提交
1414
        /* Look for QEMU prompt to indicate completion */
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439
        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 已提交
1440

1441 1442
                break;
            }
D
Daniel P. Berrange 已提交
1443 1444 1445 1446 1447 1448
        }
    pollagain:
        /* Need to wait for more data */
        if (poll(&fd, 1, -1) < 0) {
            if (errno == EINTR)
                goto pollagain;
1449
            goto error;
D
Daniel P. Berrange 已提交
1450 1451 1452
        }
    }

1453
    /* Log, but ignore failures to write logfile for VM */
1454 1455
    if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
        char ebuf[1024];
1456
        qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s\n"),
1457 1458
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1459

D
Daniel P. Berrange 已提交
1460 1461
    *reply = buf;
    return 0;
1462 1463 1464 1465

 error:
    if (buf) {
        /* Log, but ignore failures to write logfile for VM */
1466 1467
        if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
            char ebuf[1024];
1468
            qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s\n"),
1469 1470
                     virStrerror(errno, ebuf, sizeof ebuf));
        }
1471
        VIR_FREE(buf);
1472 1473
    }
    return -1;
D
Daniel P. Berrange 已提交
1474 1475
}

1476 1477 1478 1479 1480 1481 1482 1483
static int
qemudMonitorCommand(const virDomainObjPtr vm,
                    const char *cmd,
                    char **reply) {
    return qemudMonitorCommandExtra(vm, cmd, NULL, NULL, reply);
}


1484 1485 1486 1487 1488 1489
/**
 * qemudProbe:
 *
 * Probe for the availability of the qemu driver, assume the
 * presence of QEmu emulation if the binaries are installed
 */
1490
static int qemudProbe(void)
1491 1492 1493
{
    if ((virFileExists("/usr/bin/qemu")) ||
        (virFileExists("/usr/bin/qemu-kvm")) ||
G
Guido Günther 已提交
1494
        (virFileExists("/usr/bin/kvm")) ||
1495 1496 1497 1498
        (virFileExists("/usr/bin/xenner")))
        return 1;

    return 0;
1499
}
1500

1501
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
1502
                                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1503
                                  int flags ATTRIBUTE_UNUSED) {
1504 1505 1506
    uid_t uid = getuid();

    if (qemu_driver == NULL)
1507
        goto decline;
1508

1509 1510 1511 1512 1513 1514
    if (!qemudProbe())
        goto decline;

    if (conn->uri == NULL) {
        conn->uri = xmlParseURI(uid ? "qemu:///session" : "qemu:///system");
        if (!conn->uri) {
1515
            virReportOOMError(conn);
1516 1517 1518 1519
            return VIR_DRV_OPEN_ERROR;
        }
    } else if (conn->uri->scheme == NULL ||
               conn->uri->path == NULL)
1520 1521
        goto decline;

1522
    if (STRNEQ (conn->uri->scheme, "qemu"))
1523 1524
        goto decline;

1525
    if (uid != 0) {
1526
        if (STRNEQ (conn->uri->path, "/session"))
1527
            goto decline;
1528
    } else { /* root */
1529 1530
        if (STRNEQ (conn->uri->path, "/system") &&
            STRNEQ (conn->uri->path, "/session"))
1531
            goto decline;
1532 1533 1534 1535 1536
    }

    conn->privateData = qemu_driver;

    return VIR_DRV_OPEN_SUCCESS;
1537 1538

 decline:
1539
    return VIR_DRV_OPEN_DECLINED;
1540 1541 1542
}

static int qemudClose(virConnectPtr conn) {
1543
    struct qemud_driver *driver = conn->privateData;
1544 1545 1546

    /* Get rid of callbacks registered for this conn */
    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
1547 1548 1549 1550 1551 1552

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562
/* 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;
    }
}

1563
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1564
    return "QEMU";
1565 1566
}

1567 1568 1569 1570 1571

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

    int r, fd;
1572

1573 1574
    fd = open(KVM_DEVICE, O_RDONLY);
    if (fd < 0) {
1575 1576
        virReportSystemError(NULL, errno, _("Unable to open %s"), KVM_DEVICE);
        return -1;
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587
    }

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

    close(fd);
    return maxvcpus;
}


1588
static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) {
1589 1590 1591
    if (!type)
        return 16;

1592
    if (STRCASEEQ(type, "qemu"))
1593 1594
        return 16;

1595
    if (STRCASEEQ(type, "kvm"))
1596
        return kvmGetMaxVCPUs();
1597

1598
    if (STRCASEEQ(type, "kqemu"))
1599
        return 1;
1600 1601 1602

    qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG,
                     _("unknown type '%s'"), type);
1603 1604 1605
    return -1;
}

1606 1607 1608
static int qemudGetNodeInfo(virConnectPtr conn,
                            virNodeInfoPtr nodeinfo) {
    return virNodeInfoPopulate(conn, nodeinfo);
1609 1610 1611
}


1612
static char *qemudGetCapabilities(virConnectPtr conn) {
1613
    struct qemud_driver *driver = conn->privateData;
1614
    char *xml;
1615

1616
    qemuDriverLock(driver);
1617
    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
1618
        virReportOOMError(conn);
1619
    qemuDriverUnlock(driver);
1620

1621
    return xml;
1622 1623 1624
}


1625 1626 1627 1628 1629 1630 1631 1632
#if HAVE_NUMACTL
static int
qemudNodeGetCellsFreeMemory(virConnectPtr conn,
                            unsigned long long *freeMems,
                            int startCell,
                            int maxCells)
{
    int n, lastCell, numCells;
1633
    int ret = -1;
1634 1635 1636 1637

    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1638
        goto cleanup;
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
    }
    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"));
1649
            goto cleanup;
1650 1651 1652
        }
        freeMems[numCells++] = mem;
    }
1653 1654 1655 1656
    ret = numCells;

cleanup:
    return ret;
1657 1658 1659 1660 1661
}

static unsigned long long
qemudNodeGetFreeMemory (virConnectPtr conn)
{
1662
    unsigned long long freeMem = -1;
1663
    int n;
1664

1665 1666 1667
    if (numa_available() < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("NUMA not supported on this host"));
1668
        goto cleanup;
1669 1670 1671 1672 1673 1674 1675
    }

    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"));
1676
            goto cleanup;
1677 1678 1679 1680
        }
        freeMem += mem;
    }

1681
cleanup:
1682 1683 1684 1685
    return freeMem;
}

#endif
1686

D
Daniel P. Berrange 已提交
1687 1688 1689
static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) {
    char proc[PATH_MAX];
    FILE *pidinfo;
1690
    unsigned long long usertime, systime;
D
Daniel P. Berrange 已提交
1691 1692 1693 1694 1695 1696

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

    if (!(pidinfo = fopen(proc, "r"))) {
1697
        /*printf("cannot read pid info");*/
D
Daniel P. Berrange 已提交
1698 1699 1700 1701 1702
        /* VM probably shut down, so fake 0 */
        *cpuTime = 0;
        return 0;
    }

1703
    if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
1704
        qemudDebug("not enough arg");
D
Daniel P. Berrange 已提交
1705 1706 1707 1708 1709 1710 1711 1712
        return -1;
    }

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

1715
    qemudDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
D
Daniel P. Berrange 已提交
1716 1717 1718 1719 1720 1721 1722

    fclose(pidinfo);

    return 0;
}


1723
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
1724
                                          int id) {
1725 1726 1727 1728
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

1729
    qemuDriverLock(driver);
1730
    vm  = virDomainFindByID(&driver->domains, id);
1731
    qemuDriverUnlock(driver);
1732 1733

    if (!vm) {
1734
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
1735
        goto cleanup;
1736 1737
    }

1738
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1739
    if (dom) dom->id = vm->def->id;
1740 1741

cleanup:
1742 1743
    if (vm)
        virDomainObjUnlock(vm);
1744 1745
    return dom;
}
1746

1747
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
1748
                                            const unsigned char *uuid) {
1749 1750 1751
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1752

1753
    qemuDriverLock(driver);
1754
    vm = virDomainFindByUUID(&driver->domains, uuid);
1755 1756
    qemuDriverUnlock(driver);

1757
    if (!vm) {
1758
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
1759
        goto cleanup;
1760 1761
    }

1762
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1763
    if (dom) dom->id = vm->def->id;
1764 1765

cleanup:
1766 1767
    if (vm)
        virDomainObjUnlock(vm);
1768 1769
    return dom;
}
1770

1771
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
1772
                                            const char *name) {
1773 1774 1775
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1776

1777
    qemuDriverLock(driver);
1778
    vm = virDomainFindByName(&driver->domains, name);
1779 1780
    qemuDriverUnlock(driver);

1781
    if (!vm) {
1782
        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
1783
        goto cleanup;
1784 1785
    }

1786
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1787
    if (dom) dom->id = vm->def->id;
1788 1789

cleanup:
1790 1791
    if (vm)
        virDomainObjUnlock(vm);
1792 1793 1794
    return dom;
}

1795
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
1796 1797 1798
    struct qemud_driver *driver = conn->privateData;
    int ret = -1;

1799
    qemuDriverLock(driver);
1800
    if (qemudExtractVersion(conn, driver) < 0)
1801
        goto cleanup;
1802

1803
    *version = qemu_driver->qemuVersion;
1804 1805 1806
    ret = 0;

cleanup:
1807
    qemuDriverUnlock(driver);
1808
    return ret;
D
Daniel P. Berrange 已提交
1809 1810
}

1811 1812 1813
static char *
qemudGetHostname (virConnectPtr conn)
{
1814
    char *result;
1815

1816 1817
    result = virGetHostname();
    if (result == NULL) {
1818 1819
        virReportSystemError (conn, errno,
                              "%s", _("failed to determine host name"));
1820 1821 1822
        return NULL;
    }
    /* Caller frees this string. */
1823
    return result;
1824 1825
}

1826
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
1827
    struct qemud_driver *driver = conn->privateData;
1828 1829
    int got = 0, i;

1830 1831 1832
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count && got < nids ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1833 1834
        if (virDomainIsActive(driver->domains.objs[i]))
            ids[got++] = driver->domains.objs[i]->def->id;
1835 1836 1837
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
1838

D
Daniel P. Berrange 已提交
1839 1840
    return got;
}
1841

1842
static int qemudNumDomains(virConnectPtr conn) {
1843
    struct qemud_driver *driver = conn->privateData;
1844 1845
    int n = 0, i;

1846 1847 1848
    qemuDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1849
        if (virDomainIsActive(driver->domains.objs[i]))
1850
            n++;
1851 1852 1853
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    qemuDriverUnlock(driver);
1854

1855
    return n;
D
Daniel P. Berrange 已提交
1856
}
1857

1858
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
1859
                                      unsigned int flags ATTRIBUTE_UNUSED) {
1860
    struct qemud_driver *driver = conn->privateData;
1861
    virDomainDefPtr def;
1862
    virDomainObjPtr vm = NULL;
1863
    virDomainPtr dom = NULL;
1864
    virDomainEventPtr event = NULL;
D
Daniel P. Berrange 已提交
1865

1866
    qemuDriverLock(driver);
1867 1868
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
1869
        goto cleanup;
1870

1871
    vm = virDomainFindByName(&driver->domains, def->name);
1872
    if (vm) {
1873
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
1874
                         _("domain '%s' is already defined"),
1875
                         def->name);
1876
        goto cleanup;
1877
    }
1878
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
1879 1880 1881 1882 1883
    if (vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(def->uuid, uuidstr);
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
1884
                         _("domain with uuid '%s' is already defined"),
1885
                         uuidstr);
1886
        goto cleanup;
1887
    }
1888

1889 1890
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
1891 1892 1893 1894
                                  def)))
        goto cleanup;

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

1896
    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
1897 1898
        virDomainRemoveInactive(&driver->domains,
                                vm);
1899
        vm = NULL;
1900
        goto cleanup;
D
Daniel P. Berrange 已提交
1901
    }
1902 1903 1904 1905

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

1907
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1908
    if (dom) dom->id = vm->def->id;
1909 1910 1911

cleanup:
    virDomainDefFree(def);
1912 1913
    if (vm)
        virDomainObjUnlock(vm);
1914 1915
    if (event)
        qemuDomainEventQueue(driver, event);
1916
    qemuDriverUnlock(driver);
1917
    return dom;
D
Daniel P. Berrange 已提交
1918 1919 1920
}


1921
static int qemudDomainSuspend(virDomainPtr dom) {
1922
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
1923
    char *info;
1924 1925
    virDomainObjPtr vm;
    int ret = -1;
1926
    virDomainEventPtr event = NULL;
1927

1928
    qemuDriverLock(driver);
1929
    vm = virDomainFindByID(&driver->domains, dom->id);
1930 1931
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
1932
    if (!vm) {
1933
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
1934
        goto cleanup;
D
Daniel P. Berrange 已提交
1935
    }
1936
    if (!virDomainIsActive(vm)) {
1937 1938
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
1939
        goto cleanup;
D
Daniel P. Berrange 已提交
1940
    }
1941
    if (vm->state != VIR_DOMAIN_PAUSED) {
1942
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
1943 1944 1945 1946 1947 1948
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("suspend operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
1949 1950 1951
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1952
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
1953
    }
1954
    qemudSaveDomainStatus(dom->conn, driver, vm);
1955 1956 1957
    ret = 0;

cleanup:
1958 1959
    if (vm)
        virDomainObjUnlock(vm);
1960 1961 1962 1963 1964 1965

    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
1966
    return ret;
D
Daniel P. Berrange 已提交
1967 1968 1969
}


1970
static int qemudDomainResume(virDomainPtr dom) {
1971
    struct qemud_driver *driver = dom->conn->privateData;
D
Daniel P. Berrange 已提交
1972
    char *info;
1973 1974
    virDomainObjPtr vm;
    int ret = -1;
1975
    virDomainEventPtr event = NULL;
1976

1977
    qemuDriverLock(driver);
1978
    vm = virDomainFindByID(&driver->domains, dom->id);
1979 1980
    qemuDriverUnlock(driver);

D
Daniel P. Berrange 已提交
1981
    if (!vm) {
1982 1983
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         _("no domain with matching id %d"), dom->id);
1984
        goto cleanup;
D
Daniel P. Berrange 已提交
1985
    }
1986
    if (!virDomainIsActive(vm)) {
1987 1988
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
1989
        goto cleanup;
D
Daniel P. Berrange 已提交
1990
    }
1991
    if (vm->state == VIR_DOMAIN_PAUSED) {
1992
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
1993 1994 1995 1996 1997 1998
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                             "%s", _("resume operation failed"));
            goto cleanup;
        }
        vm->state = VIR_DOMAIN_RUNNING;
        qemudDebug("Reply %s", info);
1999 2000 2001
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
2002
        VIR_FREE(info);
D
Daniel P. Berrange 已提交
2003
    }
2004
    qemudSaveDomainStatus(dom->conn, driver, vm);
2005 2006 2007
    ret = 0;

cleanup:
2008 2009
    if (vm)
        virDomainObjUnlock(vm);
2010 2011 2012 2013 2014
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2015
    return ret;
D
Daniel P. Berrange 已提交
2016 2017 2018
}


2019
static int qemudDomainShutdown(virDomainPtr dom) {
2020 2021
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2022
    char* info;
2023
    int ret = -1;
2024

2025
    qemuDriverLock(driver);
2026
    vm = virDomainFindByID(&driver->domains, dom->id);
2027 2028
    qemuDriverUnlock(driver);

2029 2030
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2031
                         _("no domain with matching id %d"), dom->id);
2032
        goto cleanup;
2033 2034
    }

2035
    if (qemudMonitorCommand(vm, "system_powerdown", &info) < 0) {
2036
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2037
                         "%s", _("shutdown operation failed"));
2038
        goto cleanup;
2039
    }
D
Daniel Veillard 已提交
2040
    VIR_FREE(info);
2041 2042 2043
    ret = 0;

cleanup:
2044 2045
    if (vm)
        virDomainObjUnlock(vm);
2046
    return ret;
2047 2048 2049
}


2050
static int qemudDomainDestroy(virDomainPtr dom) {
2051 2052 2053
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2054
    virDomainEventPtr event = NULL;
2055

2056
    qemuDriverLock(driver);
2057
    vm  = virDomainFindByID(&driver->domains, dom->id);
D
Daniel P. Berrange 已提交
2058
    if (!vm) {
2059
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2060
                         _("no domain with matching id %d"), dom->id);
2061
        goto cleanup;
D
Daniel P. Berrange 已提交
2062
    }
2063

2064
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2065 2066 2067
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2068
    if (!vm->persistent) {
2069 2070
        virDomainRemoveInactive(&driver->domains,
                                vm);
2071 2072
        vm = NULL;
    }
2073 2074 2075
    ret = 0;

cleanup:
2076 2077
    if (vm)
        virDomainObjUnlock(vm);
2078 2079
    if (event)
        qemuDomainEventQueue(driver, event);
2080
    qemuDriverUnlock(driver);
2081
    return ret;
D
Daniel P. Berrange 已提交
2082 2083 2084
}


2085
static char *qemudDomainGetOSType(virDomainPtr dom) {
2086 2087 2088
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *type = NULL;
2089

2090
    qemuDriverLock(driver);
2091
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2092
    qemuDriverUnlock(driver);
2093 2094
    if (!vm) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2095
                         "%s", _("no domain with matching uuid"));
2096
        goto cleanup;
2097 2098
    }

2099
    if (!(type = strdup(vm->def->os.type)))
2100
        virReportOOMError(dom->conn);
2101 2102

cleanup:
2103 2104
    if (vm)
        virDomainObjUnlock(vm);
2105 2106 2107
    return type;
}

2108 2109
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
2110 2111 2112
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    unsigned long ret = 0;
2113

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

2118
    if (!vm) {
2119 2120 2121
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

2127 2128 2129
    ret = vm->def->maxmem;

cleanup:
2130 2131
    if (vm)
        virDomainObjUnlock(vm);
2132
    return ret;
2133 2134 2135
}

static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
2136 2137 2138
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2139

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

2144
    if (!vm) {
2145 2146 2147
        char uuidstr[VIR_UUID_STRING_BUFLEN];

        virUUIDFormat(dom->uuid, uuidstr);
2148
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2149
                         _("no domain with matching uuid '%s'"), uuidstr);
2150
        goto cleanup;
2151 2152 2153 2154
    }

    if (newmax < vm->def->memory) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2155
                         "%s", _("cannot set max memory lower than current memory"));
2156
        goto cleanup;;
2157 2158 2159
    }

    vm->def->maxmem = newmax;
2160 2161 2162
    ret = 0;

cleanup:
2163 2164
    if (vm)
        virDomainObjUnlock(vm);
2165
    return ret;
2166 2167 2168
}

static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
2169 2170 2171
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2172

2173
    qemuDriverLock(driver);
2174
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2175
    qemuDriverUnlock(driver);
2176
    if (!vm) {
2177 2178 2179
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

2185
    if (virDomainIsActive(vm)) {
2186
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
2187
                         "%s", _("cannot set memory of an active domain"));
2188
        goto cleanup;
2189 2190 2191 2192
    }

    if (newmem > vm->def->maxmem) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
2193
                         "%s", _("cannot set memory higher than max memory"));
2194
        goto cleanup;
2195 2196 2197
    }

    vm->def->memory = newmem;
2198 2199 2200
    ret = 0;

cleanup:
2201 2202
    if (vm)
        virDomainObjUnlock(vm);
2203
    return ret;
2204 2205
}

2206
static int qemudDomainGetInfo(virDomainPtr dom,
2207
                              virDomainInfoPtr info) {
2208 2209 2210 2211
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

2212
    qemuDriverLock(driver);
2213
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2214
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
2215
    if (!vm) {
2216 2217
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
2218
        goto cleanup;
D
Daniel P. Berrange 已提交
2219 2220
    }

2221
    info->state = vm->state;
D
Daniel P. Berrange 已提交
2222

2223
    if (!virDomainIsActive(vm)) {
2224
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
2225
    } else {
2226
        if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
2227
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
2228
            goto cleanup;
D
Daniel P. Berrange 已提交
2229 2230 2231
        }
    }

2232 2233 2234
    info->maxMem = vm->def->maxmem;
    info->memory = vm->def->memory;
    info->nrVirtCpu = vm->def->vcpus;
2235 2236 2237
    ret = 0;

cleanup:
2238 2239
    if (vm)
        virDomainObjUnlock(vm);
2240
    return ret;
D
Daniel P. Berrange 已提交
2241 2242 2243
}


D
Daniel P. Berrange 已提交
2244
static char *qemudEscape(const char *in, int shell)
2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265
{
    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 已提交
2266 2267 2268 2269
            if (shell)
                len += 5;
            else
                len += 1;
2270 2271 2272 2273 2274 2275 2276
            break;
        default:
            len += 1;
            break;
        }
    }

2277
    if (VIR_ALLOC_N(out, len + 1) < 0)
2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295
        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 已提交
2296 2297 2298 2299 2300 2301 2302 2303 2304
            if (shell) {
                out[j++] = '\'';
                out[j++] = '\\';
                out[j++] = '\\';
                out[j++] = '\'';
                out[j++] = '\'';
            } else {
                out[j++] = in[i];
            }
2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315
            break;
        default:
            out[j++] = in[i];
            break;
        }
    }
    out[j] = '\0';

    return out;
}

2316 2317 2318 2319 2320
static char *qemudEscapeMonitorArg(const char *in)
{
    return qemudEscape(in, 0);
}

D
Daniel P. Berrange 已提交
2321 2322 2323 2324
static char *qemudEscapeShellArg(const char *in)
{
    return qemudEscape(in, 1);
}
2325

2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336
#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];
};

2337
static int qemudDomainSave(virDomainPtr dom,
2338
                           const char *path) {
2339 2340 2341 2342 2343 2344 2345
    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;
2346
    struct qemud_save_header header;
2347
    int ret = -1;
2348
    virDomainEventPtr event = NULL;
2349 2350 2351 2352 2353

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

2354
    qemuDriverLock(driver);
2355 2356
    vm = virDomainFindByID(&driver->domains, dom->id);

D
Daniel P. Berrange 已提交
2357
    if (!vm) {
2358
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2359
                         _("no domain with matching id %d"), dom->id);
2360
        goto cleanup;
D
Daniel P. Berrange 已提交
2361
    }
2362

2363
    if (!virDomainIsActive(vm)) {
2364
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2365
                         "%s", _("domain is not running"));
2366
        goto cleanup;
D
Daniel P. Berrange 已提交
2367
    }
2368 2369 2370 2371

    /* Pause */
    if (vm->state == VIR_DOMAIN_RUNNING) {
        header.was_running = 1;
2372
        if (qemudMonitorCommand(vm, "stop", &info) < 0) {
2373
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2374
                             "%s", _("suspend operation failed"));
2375
            goto cleanup;
2376
        }
2377 2378 2379
        vm->state = VIR_DOMAIN_PAUSED;
        qemudDebug("Reply %s", info);
        VIR_FREE(info);
2380 2381 2382
    }

    /* Get XML for the domain */
2383
    xml = virDomainDefFormat(dom->conn, vm->def, VIR_DOMAIN_XML_SECURE);
2384 2385
    if (!xml) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2386
                         "%s", _("failed to get domain xml"));
2387
        goto cleanup;
2388 2389 2390 2391 2392 2393
    }
    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,
2394
                         _("failed to create '%s'"), path);
2395
        goto cleanup;
2396 2397 2398 2399
    }

    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2400
                         "%s", _("failed to write save header"));
2401
        goto cleanup;
2402 2403 2404 2405
    }

    if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2406
                         "%s", _("failed to write xml"));
2407
        goto cleanup;
2408 2409
    }

2410
    if (close(fd) < 0) {
2411 2412 2413
        virReportSystemError(dom->conn, errno,
                             _("unable to save file %s"),
                             path);
2414 2415 2416
        goto cleanup;
    }
    fd = -1;
2417 2418 2419 2420

    /* Migrate to file */
    safe_path = qemudEscapeShellArg(path);
    if (!safe_path) {
2421
        virReportOOMError(dom->conn);
2422
        goto cleanup;
2423
    }
2424
    if (virAsprintf(&command, "migrate \"exec:"
2425
                  "dd of='%s' oflag=append conv=notrunc 2>/dev/null"
2426
                  "\"", safe_path) == -1) {
2427
        virReportOOMError(dom->conn);
2428 2429
        command = NULL;
        goto cleanup;
2430 2431
    }

2432
    if (qemudMonitorCommand(vm, command, &info) < 0) {
2433
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
2434
                         "%s", _("migrate operation failed"));
2435
        goto cleanup;
2436 2437
    }

2438 2439 2440 2441 2442 2443 2444 2445
    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"));
2446
        goto cleanup;
2447 2448
    }

2449 2450
    /* Shut it down */
    qemudShutdownVMDaemon(dom->conn, driver, vm);
2451 2452 2453
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2454
    if (!vm->persistent) {
2455 2456
        virDomainRemoveInactive(&driver->domains,
                                vm);
2457 2458
        vm = NULL;
    }
2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
    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);
2470 2471
    if (vm)
        virDomainObjUnlock(vm);
2472 2473
    if (event)
        qemuDomainEventQueue(driver, event);
2474
    qemuDriverUnlock(driver);
2475
    return ret;
D
Daniel P. Berrange 已提交
2476 2477 2478
}


2479
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
2480 2481
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2482
    int max;
2483
    int ret = -1;
2484

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

2489
    if (!vm) {
2490 2491 2492
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

2498
    if (virDomainIsActive(vm)) {
2499
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
2500
                         _("cannot change vcpu count of an active domain"));
2501
        goto cleanup;
2502 2503 2504 2505 2506
    }

    if ((max = qemudDomainGetMaxVcpus(dom)) < 0) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
                         _("could not determine max vcpus for the domain"));
2507
        goto cleanup;
2508 2509 2510 2511 2512 2513
    }

    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);
2514
        goto cleanup;
2515 2516 2517
    }

    vm->def->vcpus = nvcpus;
2518 2519 2520
    ret = 0;

cleanup:
2521 2522
    if (vm)
        virDomainObjUnlock(vm);
2523
    return ret;
2524 2525
}

2526 2527 2528 2529 2530 2531 2532

#if HAVE_SCHED_GETAFFINITY
static int
qemudDomainPinVcpu(virDomainPtr dom,
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
2533 2534
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2535 2536 2537
    cpu_set_t mask;
    int i, maxcpu;
    virNodeInfo nodeinfo;
2538
    int ret = -1;
2539

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

2544
    if (!virDomainIsActive(vm)) {
2545 2546
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         "%s",_("cannot pin vcpus on an inactive domain"));
2547
        goto cleanup;
2548 2549 2550 2551 2552 2553
    }

    if (vcpu > (vm->nvcpupids-1)) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                         _("vcpu number out of range %d > %d"),
                         vcpu, vm->nvcpupids);
2554
        goto cleanup;
2555 2556 2557
    }

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2558
        goto cleanup;
2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571

    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) {
2572 2573
            virReportSystemError(dom->conn, errno, "%s",
                                 _("cannot set affinity"));
2574
            goto cleanup;
2575 2576 2577 2578
        }
    } else {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                         "%s", _("cpu affinity is not supported"));
2579
        goto cleanup;
2580
    }
2581
    ret = 0;
2582

2583
cleanup:
2584 2585
    if (vm)
        virDomainObjUnlock(vm);
2586
    return ret;
2587 2588 2589 2590 2591 2592 2593 2594
}

static int
qemudDomainGetVcpus(virDomainPtr dom,
                    virVcpuInfoPtr info,
                    int maxinfo,
                    unsigned char *cpumaps,
                    int maplen) {
2595 2596
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2597 2598
    virNodeInfo nodeinfo;
    int i, v, maxcpu;
2599
    int ret = -1;
2600

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

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

    if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
2612
        goto cleanup;
2613 2614 2615 2616 2617 2618 2619 2620 2621

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

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

2622 2623 2624 2625 2626 2627 2628 2629
    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 */
            }
2630 2631
        }

2632 2633 2634 2635 2636 2637 2638 2639 2640
        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) {
2641 2642
                        virReportSystemError(dom->conn, errno, "%s",
                                             _("cannot get affinity"));
2643 2644 2645 2646 2647 2648
                        goto cleanup;
                    }

                    for (i = 0 ; i < maxcpu ; i++)
                        if (CPU_ISSET(i, &mask))
                            VIR_USE_CPU(cpumap, i);
2649
                }
2650 2651 2652 2653
            } else {
                qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                                 "%s", _("cpu affinity is not available"));
                goto cleanup;
2654 2655 2656
            }
        }
    }
2657
    ret = maxinfo;
2658

2659
cleanup:
2660 2661
    if (vm)
        virDomainObjUnlock(vm);
2662
    return ret;
2663 2664 2665 2666
}
#endif /* HAVE_SCHED_GETAFFINITY */


2667
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
2668 2669
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2670
    const char *type;
2671
    int ret = -1;
2672

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

2677
    if (!vm) {
2678 2679 2680
        char uuidstr[VIR_UUID_STRING_BUFLEN];

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

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

2693
    ret = qemudGetMaxVCPUs(dom->conn, type);
2694

2695
cleanup:
2696 2697
    if (vm)
        virDomainObjUnlock(vm);
2698 2699 2700 2701
    return ret;
}


2702
static int qemudDomainRestore(virConnectPtr conn,
2703 2704 2705
                              const char *path) {
    struct qemud_driver *driver = conn->privateData;
    virDomainDefPtr def = NULL;
2706
    virDomainObjPtr vm = NULL;
2707 2708 2709
    int fd = -1;
    int ret = -1;
    char *xml = NULL;
2710
    struct qemud_save_header header;
2711
    virDomainEventPtr event = NULL;
2712

2713
    qemuDriverLock(driver);
2714 2715 2716
    /* Verify the header and read the XML */
    if ((fd = open(path, O_RDONLY)) < 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2717
                         "%s", _("cannot read domain image"));
2718
        goto cleanup;
2719 2720 2721 2722
    }

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2723
                         "%s", _("failed to read qemu header"));
2724
        goto cleanup;
2725 2726 2727 2728
    }

    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2729
                         "%s", _("image magic is incorrect"));
2730
        goto cleanup;
2731 2732 2733 2734
    }

    if (header.version > QEMUD_SAVE_VERSION) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2735
                         _("image version is not supported (%d > %d)"),
2736
                         header.version, QEMUD_SAVE_VERSION);
2737
        goto cleanup;
2738 2739
    }

2740
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
2741
        virReportOOMError(conn);
2742
        goto cleanup;
2743 2744 2745 2746
    }

    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2747
                         "%s", _("failed to read XML"));
2748
        goto cleanup;
2749 2750 2751
    }

    /* Create a domain from this XML */
2752 2753
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
2754
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2755
                         "%s", _("failed to parse XML"));
2756
        goto cleanup;
2757 2758 2759
    }

    /* Ensure the name and UUID don't already exist in an active VM */
2760
    vm = virDomainFindByUUID(&driver->domains, def->uuid);
2761
    if (!vm)
2762
        vm = virDomainFindByName(&driver->domains, def->name);
2763 2764 2765 2766 2767 2768 2769 2770
    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);
        }
2771 2772
    }

2773 2774 2775
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
2776
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2777
                         "%s", _("failed to assign new VM"));
2778
        goto cleanup;
2779
    }
2780
    def = NULL;
2781 2782

    /* Set the migration source and start it up. */
2783
    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
2784
    close(fd);
2785
    fd = -1;
2786
    if (ret < 0) {
2787
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2788
                         "%s", _("failed to start VM"));
2789
        if (!vm->persistent) {
2790 2791
            virDomainRemoveInactive(&driver->domains,
                                    vm);
2792 2793
            vm = NULL;
        }
2794
        goto cleanup;
2795 2796
    }

2797 2798 2799
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
2800

2801 2802 2803
    /* If it was running before, resume it now. */
    if (header.was_running) {
        char *info;
2804
        if (qemudMonitorCommand(vm, "cont", &info) < 0) {
2805
            qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
2806
                             "%s", _("failed to resume domain"));
2807
            goto cleanup;
2808
        }
2809
        VIR_FREE(info);
2810 2811
        vm->state = VIR_DOMAIN_RUNNING;
    }
2812
    ret = 0;
2813

2814 2815 2816 2817 2818
cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
2819 2820
    if (vm)
        virDomainObjUnlock(vm);
2821 2822
    if (event)
        qemuDomainEventQueue(driver, event);
2823
    qemuDriverUnlock(driver);
2824
    return ret;
D
Daniel P. Berrange 已提交
2825 2826 2827
}


2828
static char *qemudDomainDumpXML(virDomainPtr dom,
2829
                                int flags ATTRIBUTE_UNUSED) {
2830 2831 2832 2833
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;

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

D
Daniel P. Berrange 已提交
2838
    if (!vm) {
2839 2840
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
2841
        goto cleanup;
D
Daniel P. Berrange 已提交
2842 2843
    }

2844 2845 2846 2847 2848 2849
    ret = virDomainDefFormat(dom->conn,
                             (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
                             vm->newDef : vm->def,
                             flags);

cleanup:
2850 2851
    if (vm)
        virDomainObjUnlock(vm);
2852
    return ret;
D
Daniel P. Berrange 已提交
2853 2854 2855
}


2856
static int qemudListDefinedDomains(virConnectPtr conn,
2857
                            char **const names, int nnames) {
2858
    struct qemud_driver *driver = conn->privateData;
2859
    int got = 0, i;
2860

2861
    qemuDriverLock(driver);
2862
    for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
2863
        virDomainObjLock(driver->domains.objs[i]);
2864 2865
        if (!virDomainIsActive(driver->domains.objs[i])) {
            if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) {
2866
                virReportOOMError(conn);
2867
                virDomainObjUnlock(driver->domains.objs[i]);
2868 2869
                goto cleanup;
            }
2870
        }
2871
        virDomainObjUnlock(driver->domains.objs[i]);
D
Daniel P. Berrange 已提交
2872
    }
2873

2874
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
2875
    return got;
2876 2877 2878

 cleanup:
    for (i = 0 ; i < got ; i++)
2879
        VIR_FREE(names[i]);
2880
    qemuDriverUnlock(driver);
2881
    return -1;
D
Daniel P. Berrange 已提交
2882 2883
}

2884
static int qemudNumDefinedDomains(virConnectPtr conn) {
2885
    struct qemud_driver *driver = conn->privateData;
2886 2887
    int n = 0, i;

2888
    qemuDriverLock(driver);
2889 2890
    for (i = 0 ; i < driver->domains.count ; i++)
        if (!virDomainIsActive(driver->domains.objs[i]))
2891
            n++;
2892
    qemuDriverUnlock(driver);
2893

2894
    return n;
D
Daniel P. Berrange 已提交
2895 2896 2897
}


2898
static int qemudDomainStart(virDomainPtr dom) {
2899 2900 2901
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
2902
    virDomainEventPtr event = NULL;
2903

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

2908
    if (!vm) {
2909
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
2910
                         "%s", _("no domain with matching uuid"));
2911
        goto cleanup;
2912 2913
    }

2914
    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
2915
    if (ret != -1)
2916 2917 2918
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
2919 2920

cleanup:
2921 2922
    if (vm)
        virDomainObjUnlock(vm);
2923 2924 2925 2926 2927
    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
2928
    return ret;
D
Daniel P. Berrange 已提交
2929 2930 2931
}


2932
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
2933
    struct qemud_driver *driver = conn->privateData;
2934
    virDomainDefPtr def;
2935
    virDomainObjPtr vm = NULL;
2936
    virDomainPtr dom = NULL;
2937
    virDomainEventPtr event = NULL;
2938
    int newVM = 1;
2939

2940
    qemuDriverLock(driver);
2941 2942
    if (!(def = virDomainDefParseString(conn, driver->caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
2943
        goto cleanup;
2944

2945
    vm = virDomainFindByName(&driver->domains, def->name);
2946 2947
    if (vm) {
        virDomainObjUnlock(vm);
2948
        newVM = 0;
2949
    }
2950

2951 2952 2953 2954
    if (!(vm = virDomainAssignDef(conn,
                                  &driver->domains,
                                  def))) {
        virDomainDefFree(def);
2955
        goto cleanup;
2956
    }
2957
    vm->persistent = 1;
2958

2959 2960
    if (virDomainSaveConfig(conn,
                            driver->configDir,
2961
                            vm->newDef ? vm->newDef : vm->def) < 0) {
2962 2963
        virDomainRemoveInactive(&driver->domains,
                                vm);
2964
        vm = NULL;
2965
        goto cleanup;
2966 2967
    }

2968 2969 2970 2971 2972
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     newVM ?
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
2973

2974
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
2975
    if (dom) dom->id = vm->def->id;
2976 2977

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

2986
static int qemudDomainUndefine(virDomainPtr dom) {
2987 2988
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
2989
    virDomainEventPtr event = NULL;
2990
    int ret = -1;
D
Daniel P. Berrange 已提交
2991

2992
    qemuDriverLock(driver);
2993
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2994

D
Daniel P. Berrange 已提交
2995
    if (!vm) {
2996 2997
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
2998
        goto cleanup;
D
Daniel P. Berrange 已提交
2999 3000
    }

3001
    if (virDomainIsActive(vm)) {
3002 3003
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot delete active domain"));
3004
        goto cleanup;
D
Daniel P. Berrange 已提交
3005 3006
    }

3007 3008 3009
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot undefine transient domain"));
3010
        goto cleanup;
3011 3012 3013
    }

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

3016 3017 3018
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
3019

3020 3021
    virDomainRemoveInactive(&driver->domains,
                            vm);
3022
    vm = NULL;
3023
    ret = 0;
D
Daniel P. Berrange 已提交
3024

3025
cleanup:
3026 3027
    if (vm)
        virDomainObjUnlock(vm);
3028 3029
    if (event)
        qemuDomainEventQueue(driver, event);
3030
    qemuDriverUnlock(driver);
3031
    return ret;
D
Daniel P. Berrange 已提交
3032 3033
}

3034
/* Return the disks name for use in monitor commands */
3035
static char *qemudDiskDeviceName(const virConnectPtr conn,
3036
                                 const virDomainDiskDefPtr disk) {
3037 3038 3039 3040 3041 3042

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

    if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) {
3043
        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
3044 3045 3046 3047 3048 3049 3050
                         _("cannot convert disk '%s' to bus/device index"),
                         disk->dst);
        return NULL;
    }

    switch (disk->bus) {
        case VIR_DOMAIN_DISK_BUS_IDE:
3051
            if (disk->device== VIR_DOMAIN_DISK_DEVICE_DISK)
3052
                ret = virAsprintf(&devname, "ide%d-hd%d", busid, devid);
3053
            else
3054
                ret = virAsprintf(&devname, "ide%d-cd%d", busid, devid);
3055 3056
            break;
        case VIR_DOMAIN_DISK_BUS_SCSI:
3057
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
3058
                ret = virAsprintf(&devname, "scsi%d-hd%d", busid, devid);
3059
            else
3060
                ret = virAsprintf(&devname, "scsi%d-cd%d", busid, devid);
3061 3062
            break;
        case VIR_DOMAIN_DISK_BUS_FDC:
3063
            ret = virAsprintf(&devname, "floppy%d", devid);
3064 3065
            break;
        case VIR_DOMAIN_DISK_BUS_VIRTIO:
3066
            ret = virAsprintf(&devname, "virtio%d", devid);
3067 3068
            break;
        default:
3069
            qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
3070 3071 3072 3073 3074 3075
                             _("Unsupported disk name mapping for bus '%s'"),
                             virDomainDiskBusTypeToString(disk->bus));
            return NULL;
    }

    if (ret == -1) {
3076
        virReportOOMError(conn);
3077 3078 3079 3080 3081 3082
        return NULL;
    }

    return devname;
}

3083 3084
static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
                                           virDomainObjPtr vm,
3085 3086
                                           virDomainDeviceDefPtr dev)
{
3087
    virDomainDiskDefPtr origdisk = NULL, newdisk;
3088
    char *cmd, *reply, *safe_path;
3089
    char *devname = NULL;
3090
    unsigned int qemuCmdFlags;
3091
    int i;
3092

3093
    origdisk = NULL;
3094
    newdisk = dev->data.disk;
3095 3096 3097 3098
    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];
3099
            break;
3100
        }
3101 3102 3103
    }

    if (!origdisk) {
3104
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3105 3106 3107 3108 3109 3110 3111 3112 3113
                         _("No device with bus '%s' and target '%s'"),
                         virDomainDiskBusTypeToString(newdisk->bus),
                         newdisk->dst);
        return -1;
    }

    if (qemudExtractVersionInfo(vm->def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0) {
3114
        qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3115 3116 3117 3118 3119 3120
                         _("Cannot determine QEMU argv syntax %s"),
                         vm->def->emulator);
        return -1;
    }

    if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
3121
        if (!(devname = qemudDiskDeviceName(conn, newdisk)))
3122 3123 3124 3125 3126 3127 3128 3129 3130
            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 {
3131
            qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
3132 3133 3134 3135 3136 3137 3138 3139
                             _("Emulator version does not support removable "
                               "media for device '%s' and target '%s'"),
                               virDomainDiskDeviceTypeToString(newdisk->device),
                               newdisk->dst);
            return -1;
        }

        if (!devname) {
3140
            virReportOOMError(conn);
3141 3142 3143
            return -1;
        }
    }
3144

3145
    if (newdisk->src) {
3146 3147
        safe_path = qemudEscapeMonitorArg(newdisk->src);
        if (!safe_path) {
3148
            virReportOOMError(conn);
3149
            VIR_FREE(devname);
3150 3151
            return -1;
        }
3152
        if (virAsprintf(&cmd, "change %s \"%s\"", devname, safe_path) == -1) {
3153
            virReportOOMError(conn);
3154
            VIR_FREE(safe_path);
3155
            VIR_FREE(devname);
3156 3157
            return -1;
        }
3158
        VIR_FREE(safe_path);
3159

3160
    } else if (virAsprintf(&cmd, "eject %s", devname) == -1) {
3161
        virReportOOMError(conn);
3162
        VIR_FREE(devname);
3163 3164
        return -1;
    }
3165
    VIR_FREE(devname);
3166

3167
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3168
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3169
                         "%s", _("could not change cdrom media"));
3170
        VIR_FREE(cmd);
3171 3172
        return -1;
    }
3173 3174 3175 3176

    /* If the command failed qemu prints:
     * device not found, device is locked ...
     * No message is printed on success it seems */
3177
    DEBUG ("ejectable media change reply: %s", reply);
3178
    if (strstr(reply, "\ndevice ")) {
3179
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
C
Cole Robinson 已提交
3180
                          _("changing cdrom media failed: %s"), reply);
3181 3182 3183 3184
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3185 3186
    VIR_FREE(reply);
    VIR_FREE(cmd);
3187

3188 3189
    VIR_FREE(origdisk->src);
    origdisk->src = newdisk->src;
3190
    newdisk->src = NULL;
3191
    origdisk->type = newdisk->type;
3192 3193 3194
    return 0;
}

3195 3196 3197
static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm,
                                          virDomainDeviceDefPtr dev)
3198 3199
{
    int ret, i;
3200
    char *cmd, *reply, *s;
3201 3202 3203 3204 3205
    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)) {
3206
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3207 3208 3209 3210 3211 3212
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3213
        virReportOOMError(conn);
3214 3215 3216 3217 3218
        return -1;
    }

    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3219
        virReportOOMError(conn);
3220 3221 3222
        return -1;
    }

3223 3224
    ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
                      safe_path, type);
3225 3226
    VIR_FREE(safe_path);
    if (ret == -1) {
3227
        virReportOOMError(conn);
3228 3229 3230
        return ret;
    }

3231
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3232
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3233 3234 3235 3236 3237 3238 3239 3240
                         _("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... */
3241 3242 3243 3244 3245 3246
#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
    if ((s=strstr(reply, PCI_ATTACH_OK_MSG))) {
        char* dummy = s;
        s += strlen(PCI_ATTACH_OK_MSG);

        if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
J
Jim Meyering 已提交
3247
            qemudLog(QEMUD_WARN, "%s", _("Unable to parse slot number\n"));
3248
    } else {
3249
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263
                          _("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;
}
3264

3265 3266 3267
static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
                                                 virDomainObjPtr vm,
                                                 virDomainDeviceDefPtr dev)
3268
{
3269 3270
    int ret, i;
    char *safe_path;
3271 3272
    char *cmd, *reply;

3273 3274
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
3275
            qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3276 3277 3278 3279 3280
                           _("target %s already exists"), dev->data.disk->dst);
            return -1;
        }
    }

3281
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
3282
        virReportOOMError(conn);
3283
        return -1;
3284 3285
    }

3286 3287
    safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
    if (!safe_path) {
3288
        virReportOOMError(conn);
3289 3290 3291
        return -1;
    }

3292
    ret = virAsprintf(&cmd, "usb_add disk:%s", safe_path);
3293
    VIR_FREE(safe_path);
3294
    if (ret == -1) {
3295
        virReportOOMError(conn);
3296 3297 3298
        return ret;
    }

3299
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3300
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3301
                         "%s", _("cannot attach usb disk"));
3302 3303 3304 3305 3306 3307 3308 3309
        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 ")) {
3310
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3311
                          "%s",
3312
                          _("adding usb disk failed"));
3313 3314 3315 3316
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3317

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

3322 3323 3324 3325 3326
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return 0;
}

3327 3328 3329
static int qemudDomainAttachHostDevice(virConnectPtr conn,
                                       virDomainObjPtr vm,
                                       virDomainDeviceDefPtr dev)
3330 3331 3332 3333
{
    int ret;
    char *cmd, *reply;

3334
    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
3335
        virReportOOMError(conn);
3336 3337
        return -1;
    }
3338

3339
    if (dev->data.hostdev->source.subsys.u.usb.vendor) {
3340 3341 3342
        ret = virAsprintf(&cmd, "usb_add host:%.4x:%.4x",
                          dev->data.hostdev->source.subsys.u.usb.vendor,
                          dev->data.hostdev->source.subsys.u.usb.product);
3343
    } else {
3344 3345 3346
        ret = virAsprintf(&cmd, "usb_add host:%.3d.%.3d",
                          dev->data.hostdev->source.subsys.u.usb.bus,
                          dev->data.hostdev->source.subsys.u.usb.device);
3347 3348
    }
    if (ret == -1) {
3349
        virReportOOMError(conn);
3350 3351 3352
        return -1;
    }

3353
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3354
        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3355 3356 3357 3358 3359 3360 3361 3362 3363
                         "%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 ")) {
3364
        qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3365 3366 3367 3368 3369 3370
                          "%s",
                          _("adding usb device failed"));
        VIR_FREE(reply);
        VIR_FREE(cmd);
        return -1;
    }
3371

3372
    vm->def->hostdevs[vm->def->nhostdevs++] = dev->data.hostdev;
3373

3374 3375
    VIR_FREE(reply);
    VIR_FREE(cmd);
3376 3377 3378
    return 0;
}

3379 3380
static int qemudDomainAttachDevice(virDomainPtr dom,
                                   const char *xml) {
3381 3382 3383 3384
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
3385

3386
    qemuDriverLock(driver);
3387
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3388
    if (!vm) {
3389
        qemuDriverUnlock(driver);
3390 3391
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3392
        goto cleanup;
3393 3394 3395
    }

    if (!virDomainIsActive(vm)) {
3396
        qemuDriverUnlock(driver);
3397 3398
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot attach device on inactive domain"));
3399
        goto cleanup;
3400 3401
    }

3402 3403
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
3404
    qemuDriverUnlock(driver);
3405 3406 3407
    if (dev == NULL)
        goto cleanup;

3408

3409 3410
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
        switch (dev->data.disk->device) {
3411 3412
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
        case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
3413
            ret = qemudDomainChangeEjectableMedia(dom->conn, vm, dev);
3414 3415 3416
            break;
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
3417
                ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, vm, dev);
3418 3419
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
                       dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
3420
                ret = qemudDomainAttachPciDiskDevice(dom->conn, vm, dev);
3421 3422 3423 3424 3425 3426
            }
            break;
        default:
            qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                             "%s", _("this disk device type cannot be attached"));
            goto cleanup;
3427
        }
3428
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
3429 3430
               dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
               dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
3431
        ret = qemudDomainAttachHostDevice(dom->conn, vm, dev);
3432
    } else {
3433
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
3434
                         "%s", _("this device type cannot be attached"));
3435
        goto cleanup;
3436 3437
    }

3438
    qemudSaveDomainStatus(dom->conn, driver, vm);
3439
cleanup:
G
Guido Günther 已提交
3440 3441
    if (ret < 0)
        virDomainDeviceDefFree(dev);
3442 3443
    if (vm)
        virDomainObjUnlock(vm);
3444 3445 3446
    return ret;
}

3447 3448
static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
                                          virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3449 3450
{
    int i, ret = -1;
3451 3452
    char *cmd = NULL;
    char *reply = NULL;
3453 3454 3455 3456 3457 3458 3459 3460 3461 3462
    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) {
3463
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3464
                         _("disk %s not found"), dev->data.disk->dst);
3465
        goto cleanup;
3466 3467 3468
    }

    if (detach->slotnum < 1) {
3469
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3470
                         _("disk %s cannot be detached - invalid slot number %d"),
3471
                           detach->dst, detach->slotnum);
3472
        goto cleanup;
3473 3474
    }

3475
    if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
3476
        virReportOOMError(conn);
3477
        goto cleanup;
3478 3479
    }

3480
    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
3481
        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3482
                          _("failed to execute detach disk %s command"), detach->dst);
3483
        goto cleanup;
3484 3485 3486 3487 3488 3489
    }

    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")) {
3490
        qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
3491
                          _("failed to detach disk %s: invalid slot %d"),
3492 3493
                          detach->dst, detach->slotnum);
        goto cleanup;
3494 3495 3496 3497 3498
    }

    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) {
3499
            virReportOOMError(conn);
3500
            goto cleanup;
3501 3502 3503 3504 3505 3506 3507 3508
        }
        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;
3509 3510

cleanup:
3511 3512 3513 3514 3515 3516 3517
    VIR_FREE(reply);
    VIR_FREE(cmd);
    return ret;
}

static int qemudDomainDetachDevice(virDomainPtr dom,
                                   const char *xml) {
3518 3519 3520 3521
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
3522

3523
    qemuDriverLock(driver);
3524
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3525
    if (!vm) {
3526
        qemuDriverUnlock(driver);
3527 3528
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3529
        goto cleanup;
3530 3531 3532
    }

    if (!virDomainIsActive(vm)) {
3533
        qemuDriverUnlock(driver);
3534
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
G
Guido Günther 已提交
3535
                         "%s", _("cannot detach device on inactive domain"));
3536
        goto cleanup;
3537 3538
    }

3539 3540
    dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml,
                                  VIR_DOMAIN_XML_INACTIVE);
3541
    qemuDriverUnlock(driver);
3542 3543 3544
    if (dev == NULL)
        goto cleanup;

3545 3546 3547 3548 3549

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

3555
    qemudSaveDomainStatus(dom->conn, driver, vm);
3556 3557
cleanup:
    virDomainDeviceDefFree(dev);
3558 3559
    if (vm)
        virDomainObjUnlock(vm);
3560 3561 3562
    return ret;
}

3563
static int qemudDomainGetAutostart(virDomainPtr dom,
3564
                                   int *autostart) {
3565 3566 3567
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3568

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

3573
    if (!vm) {
3574 3575
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3576
        goto cleanup;
3577 3578 3579
    }

    *autostart = vm->autostart;
3580
    ret = 0;
3581

3582
cleanup:
3583 3584
    if (vm)
        virDomainObjUnlock(vm);
3585
    return ret;
3586 3587
}

3588
static int qemudDomainSetAutostart(virDomainPtr dom,
3589
                                   int autostart) {
3590 3591
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3592 3593
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
3594

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

3599
    if (!vm) {
3600 3601
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                         "%s", _("no domain with matching uuid"));
3602
        goto cleanup;
3603 3604
    }

3605 3606 3607
    if (!vm->persistent) {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
                         "%s", _("cannot set autostart for transient domain"));
3608
        goto cleanup;
3609 3610
    }

3611 3612
    autostart = (autostart != 0);

3613 3614 3615 3616 3617
    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;
3618

3619 3620
        if (autostart) {
            int err;
3621

3622
            if ((err = virFileMakePath(driver->autostartDir))) {
3623 3624 3625
                virReportSystemError(dom->conn, err,
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
3626 3627
                goto cleanup;
            }
3628

3629
            if (symlink(configFile, autostartLink) < 0) {
3630 3631 3632
                virReportSystemError(dom->conn, errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
3633 3634 3635 3636
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
3637 3638 3639
                virReportSystemError(dom->conn, errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
3640 3641
                goto cleanup;
            }
3642 3643
        }

3644
        vm->autostart = autostart;
3645
    }
3646
    ret = 0;
3647

3648 3649 3650
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
3651 3652
    if (vm)
        virDomainObjUnlock(vm);
3653
    return ret;
3654 3655
}

3656 3657 3658 3659 3660 3661 3662 3663 3664
/* 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)
{
3665
    struct qemud_driver *driver = dom->conn->privateData;
3666
    char *dummy, *info = NULL;
3667
    const char *p, *eol;
3668
    const char *qemu_dev_name = NULL;
3669
    size_t len;
3670
    int i, ret = -1;
3671
    virDomainObjPtr vm;
3672
    virDomainDiskDefPtr disk = NULL;
3673

3674
    qemuDriverLock(driver);
3675
    vm = virDomainFindByID(&driver->domains, dom->id);
3676
    qemuDriverUnlock(driver);
3677 3678 3679
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
3680
        goto cleanup;
3681
    }
3682
    if (!virDomainIsActive (vm)) {
3683 3684
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("domain is not running"));
3685
        goto cleanup;
3686 3687
    }

3688 3689 3690 3691 3692 3693 3694 3695
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(path, vm->def->disks[i]->dst)) {
            disk = vm->def->disks[i];
            break;
        }
    }

    if (!disk) {
3696 3697
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          _("invalid path: %s"), path);
3698
        goto cleanup;
3699 3700
    }

3701
    qemu_dev_name = qemudDiskDeviceName(dom->conn, disk);
3702
    if (!qemu_dev_name)
3703
        goto cleanup;
3704 3705
    len = strlen (qemu_dev_name);

3706
    if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) {
3707 3708
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("'info blockstats' command failed"));
3709
        goto cleanup;
3710 3711 3712 3713 3714 3715 3716 3717
    }
    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 已提交
3718
    if (strstr(info, "\ninfo ")) {
3719 3720 3721
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                          "%s",
                          _("'info blockstats' not supported by this qemu"));
3722
        goto cleanup;
3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748
    }

    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) {
3749
                if (STRPREFIX (p, "rd_bytes=")) {
3750 3751 3752
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1)
                        DEBUG ("error reading rd_bytes: %s", p);
3753
                } else if (STRPREFIX (p, "wr_bytes=")) {
3754 3755 3756
                    p += 9;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1)
                        DEBUG ("error reading wr_bytes: %s", p);
3757
                } else if (STRPREFIX (p, "rd_operations=")) {
3758 3759 3760
                    p += 14;
                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1)
                        DEBUG ("error reading rd_req: %s", p);
3761
                } else if (STRPREFIX (p, "wr_operations=")) {
3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772
                    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++;
            }
3773
            ret = 0;
3774
            goto cleanup;
3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785
        }

        /* 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);
3786
 cleanup:
3787 3788
    VIR_FREE(qemu_dev_name);
    VIR_FREE(info);
3789 3790
    if (vm)
        virDomainObjUnlock(vm);
3791
    return ret;
3792 3793
}

3794
#ifdef __linux__
3795 3796 3797 3798 3799
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path,
                           struct _virDomainInterfaceStats *stats)
{
3800 3801
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
3802
    int i;
3803
    int ret = -1;
3804

3805
    qemuDriverLock(driver);
3806
    vm = virDomainFindByID(&driver->domains, dom->id);
3807 3808
    qemuDriverUnlock(driver);

3809 3810
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
3811
                          _("no domain with matching id %d"), dom->id);
3812
        goto cleanup;
3813 3814
    }

3815
    if (!virDomainIsActive(vm)) {
3816
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3817
                         "%s", _("domain is not running"));
3818
        goto cleanup;
3819 3820 3821 3822
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
3823
                         "%s", _("NULL or empty path"));
3824
        goto cleanup;
3825 3826 3827
    }

    /* Check the path is one of the domain's network interfaces. */
3828 3829
    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (vm->def->nets[i]->ifname &&
3830 3831 3832 3833
            STREQ (vm->def->nets[i]->ifname, path)) {
            ret = 0;
            break;
        }
3834 3835
    }

3836 3837 3838 3839 3840
    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);
3841

3842
cleanup:
3843 3844
    if (vm)
        virDomainObjUnlock(vm);
3845 3846
    return ret;
}
3847
#else
3848 3849 3850 3851
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path ATTRIBUTE_UNUSED,
                           struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
3852 3853 3854 3855
    qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                      "%s", __FUNCTION__);
    return -1;
}
3856
#endif
3857

3858 3859 3860 3861 3862 3863 3864
static int
qemudDomainBlockPeek (virDomainPtr dom,
                      const char *path,
                      unsigned long long offset, size_t size,
                      void *buffer,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
3865 3866 3867
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int fd = -1, ret = -1, i;
3868

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

3873 3874
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
3875
                          "%s", _("no domain with matching uuid"));
3876
        goto cleanup;
3877 3878 3879 3880
    }

    if (!path || path[0] == '\0') {
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
3881
                         "%s", _("NULL or empty path"));
3882
        goto cleanup;
3883 3884 3885
    }

    /* Check the path belongs to this domain. */
3886 3887
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (vm->def->disks[i]->src != NULL &&
3888 3889 3890 3891
            STREQ (vm->def->disks[i]->src, path)) {
            ret = 0;
            break;
        }
3892 3893
    }

3894 3895 3896 3897 3898
    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) {
3899 3900
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to open"), path);
3901 3902
            goto cleanup;
        }
3903

3904 3905 3906 3907 3908 3909
        /* 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) {
3910 3911
            virReportSystemError (dom->conn, errno,
                                  _("%s: failed to seek or read"), path);
3912 3913 3914 3915 3916 3917 3918
            goto cleanup;
        }

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

3921 3922 3923
cleanup:
    if (fd >= 0)
        close (fd);
3924 3925
    if (vm)
        virDomainObjUnlock(vm);
3926 3927 3928
    return ret;
}

R
Richard W.M. Jones 已提交
3929 3930 3931 3932 3933 3934
static int
qemudDomainMemoryPeek (virDomainPtr dom,
                       unsigned long long offset, size_t size,
                       void *buffer,
                       unsigned int flags)
{
3935 3936 3937
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char cmd[256], *info = NULL;
R
Richard W.M. Jones 已提交
3938 3939 3940
    char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
    int fd = -1, ret = -1;

3941
    qemuDriverLock(driver);
3942
    vm = virDomainFindByID(&driver->domains, dom->id);
3943
    qemuDriverUnlock(driver);
R
Richard W.M. Jones 已提交
3944 3945 3946 3947

    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
3948 3949 3950 3951 3952 3953 3954
        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 已提交
3955 3956
    }

3957
    if (!virDomainIsActive(vm)) {
R
Richard W.M. Jones 已提交
3958 3959
        qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                         "%s", _("domain is not running"));
3960
        goto cleanup;
R
Richard W.M. Jones 已提交
3961 3962 3963 3964
    }

    /* Create a temporary filename. */
    if ((fd = mkstemp (tmp)) == -1) {
3965 3966
        virReportSystemError (dom->conn, errno,
                              _("mkstemp(\"%s\") failed"), tmp);
3967
        goto cleanup;
R
Richard W.M. Jones 已提交
3968 3969 3970 3971
    }

    /* Issue the memsave command. */
    snprintf (cmd, sizeof cmd, "memsave %llu %zi \"%s\"", offset, size, tmp);
3972
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
R
Richard W.M. Jones 已提交
3973
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
3974
                          "%s", _("'memsave' command failed"));
3975
        goto cleanup;
R
Richard W.M. Jones 已提交
3976 3977 3978 3979 3980 3981
    }

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

    /* Read the memory file into buffer. */
    if (saferead (fd, buffer, size) == (ssize_t) -1) {
3982 3983 3984
        virReportSystemError (dom->conn, errno,
                              _("failed to read temporary file "
                                "created with template %s"), tmp);
3985
        goto cleanup;
R
Richard W.M. Jones 已提交
3986 3987 3988
    }

    ret = 0;
3989 3990 3991

cleanup:
    VIR_FREE(info);
R
Richard W.M. Jones 已提交
3992 3993
    if (fd >= 0) close (fd);
    unlink (tmp);
3994 3995
    if (vm)
        virDomainObjUnlock(vm);
R
Richard W.M. Jones 已提交
3996 3997 3998
    return ret;
}

3999

4000 4001
static int
qemudDomainEventRegister (virConnectPtr conn,
4002
                          virConnectDomainEventCallback callback,
4003 4004
                          void *opaque,
                          virFreeCallback freecb)
4005
{
4006 4007 4008
    struct qemud_driver *driver = conn->privateData;
    int ret;

4009
    qemuDriverLock(driver);
4010 4011
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
4012
    qemuDriverUnlock(driver);
4013

4014
    return ret;
4015 4016 4017 4018
}

static int
qemudDomainEventDeregister (virConnectPtr conn,
4019
                            virConnectDomainEventCallback callback)
4020
{
4021 4022 4023
    struct qemud_driver *driver = conn->privateData;
    int ret;

4024
    qemuDriverLock(driver);
4025 4026 4027 4028 4029 4030
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
4031
    qemuDriverUnlock(driver);
4032

4033
    return ret;
4034 4035
}

4036 4037 4038 4039 4040
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
                                        virConnectDomainEventCallback cb,
                                        void *cbopaque,
                                        void *opaque)
4041
{
4042
    struct qemud_driver *driver = opaque;
4043

4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087
    /* 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);
4088 4089
}

D
Daniel Veillard 已提交
4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107
/* 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;
4108 4109
    struct qemud_driver *driver = dconn->privateData;
    virDomainDefPtr def = NULL;
D
Daniel Veillard 已提交
4110 4111 4112 4113 4114
    virDomainObjPtr vm = NULL;
    int this_port;
    char hostname [HOST_NAME_MAX+1];
    char migrateFrom [64];
    const char *p;
4115
    virDomainEventPtr event = NULL;
4116 4117 4118
    int ret = -1;;

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

4120
    qemuDriverLock(driver);
D
Daniel Veillard 已提交
4121 4122 4123
    if (!dom_xml) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          "%s", _("no domain XML passed"));
4124
        goto cleanup;
D
Daniel Veillard 已提交
4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142
    }

    /* 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) {
4143 4144
            virReportSystemError (dconn, errno,
                                  "%s", _("failed to determine host name"));
4145
            goto cleanup;
D
Daniel Veillard 已提交
4146 4147 4148
        }

        /* Caller frees */
4149
        if (virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) {
4150
            virReportOOMError (dconn);
4151
            goto cleanup;
D
Daniel Veillard 已提交
4152 4153 4154 4155 4156 4157 4158 4159 4160
        }
    } 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"));
4161
            goto cleanup;
D
Daniel Veillard 已提交
4162 4163 4164 4165 4166 4167 4168 4169 4170
        }

        /* 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"));
4171
            goto cleanup;
D
Daniel Veillard 已提交
4172 4173 4174 4175
        }
    }

    /* Parse the domain XML. */
4176 4177
    if (!(def = virDomainDefParseString(dconn, driver->caps, dom_xml,
                                        VIR_DOMAIN_XML_INACTIVE))) {
D
Daniel Veillard 已提交
4178 4179
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to parse XML"));
4180
        goto cleanup;
D
Daniel Veillard 已提交
4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196
    }

    /* 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"));
4197
        goto cleanup;
D
Daniel Veillard 已提交
4198 4199 4200 4201 4202 4203 4204 4205 4206
    }
#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);
4207
            goto cleanup;
D
Daniel Veillard 已提交
4208 4209 4210 4211 4212 4213 4214 4215
        }
    }

    if (!(vm = virDomainAssignDef(dconn,
                                  &driver->domains,
                                  def))) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to assign new VM"));
4216
        goto cleanup;
D
Daniel Veillard 已提交
4217
    }
4218
    def = NULL;
D
Daniel Veillard 已提交
4219 4220 4221 4222 4223 4224 4225 4226

    /* 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);
4227
    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
D
Daniel Veillard 已提交
4228 4229
        qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to start listening VM"));
4230
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4231
            virDomainRemoveInactive(&driver->domains, vm);
4232 4233
            vm = NULL;
        }
4234
        goto cleanup;
D
Daniel Veillard 已提交
4235
    }
4236 4237 4238 4239

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

4242 4243 4244 4245 4246
cleanup:
    virDomainDefFree(def);
    if (ret != 0) {
        VIR_FREE(*uri_out);
    }
4247 4248
    if (vm)
        virDomainObjUnlock(vm);
4249 4250
    if (event)
        qemuDomainEventQueue(driver, event);
4251
    qemuDriverUnlock(driver);
4252
    return ret;
D
Daniel Veillard 已提交
4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264
}

/* 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)
{
4265 4266
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4267
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4268 4269
    char *safe_uri;
    char cmd[HOST_NAME_MAX+50];
4270 4271
    char *info = NULL;
    int ret = -1;
D
Daniel Veillard 已提交
4272

4273
    qemuDriverLock(driver);
4274
    vm = virDomainFindByID(&driver->domains, dom->id);
D
Daniel Veillard 已提交
4275 4276 4277
    if (!vm) {
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
4278
        goto cleanup;
D
Daniel Veillard 已提交
4279 4280 4281 4282 4283
    }

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

4287 4288 4289
    if (!(flags & VIR_MIGRATE_LIVE)) {
        /* Pause domain for non-live migration */
        snprintf(cmd, sizeof cmd, "%s", "stop");
4290
        qemudMonitorCommand (vm, cmd, &info);
4291 4292 4293
        DEBUG ("stop reply: %s", info);
        VIR_FREE(info);

4294 4295 4296 4297 4298 4299
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
        event = NULL;
4300 4301
    }

D
Daniel Veillard 已提交
4302 4303 4304
    if (resource > 0) {
        /* Issue migrate_set_speed command.  Don't worry if it fails. */
        snprintf (cmd, sizeof cmd, "migrate_set_speed %lum", resource);
4305
        qemudMonitorCommand (vm, cmd, &info);
D
Daniel Veillard 已提交
4306 4307 4308 4309 4310 4311 4312 4313

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

    /* Issue the migrate command. */
    safe_uri = qemudEscapeMonitorArg (uri);
    if (!safe_uri) {
4314
        virReportOOMError (dom->conn);
4315
        goto cleanup;
D
Daniel Veillard 已提交
4316 4317 4318 4319
    }
    snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri);
    VIR_FREE (safe_uri);

4320
    if (qemudMonitorCommand (vm, cmd, &info) < 0) {
D
Daniel Veillard 已提交
4321 4322
        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("migrate operation failed"));
4323
        goto cleanup;
D
Daniel Veillard 已提交
4324 4325 4326 4327 4328 4329 4330 4331
    }

    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);
4332
        goto cleanup;
D
Daniel Veillard 已提交
4333 4334 4335 4336
    }

    /* Clean up the source domain. */
    qemudShutdownVMDaemon (dom->conn, driver, vm);
4337 4338 4339 4340

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
4341
    if (!vm->persistent) {
D
Daniel Veillard 已提交
4342
        virDomainRemoveInactive(&driver->domains, vm);
4343 4344
        vm = NULL;
    }
4345
    ret = 0;
D
Daniel Veillard 已提交
4346

4347 4348
cleanup:
    VIR_FREE(info);
4349 4350
    if (vm)
        virDomainObjUnlock(vm);
4351 4352
    if (event)
        qemuDomainEventQueue(driver, event);
4353
    qemuDriverUnlock(driver);
4354
    return ret;
D
Daniel Veillard 已提交
4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366
}

/* 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)
{
4367 4368 4369
    struct qemud_driver *driver = dconn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
4370
    virDomainEventPtr event = NULL;
D
Daniel Veillard 已提交
4371 4372
    char *info = NULL;

4373
    qemuDriverLock(driver);
4374
    vm = virDomainFindByName(&driver->domains, dname);
D
Daniel Veillard 已提交
4375 4376 4377
    if (!vm) {
        qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching name %s"), dname);
4378
        goto cleanup;
D
Daniel Veillard 已提交
4379 4380 4381 4382 4383 4384 4385 4386 4387
    }

    /* 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;
4388 4389 4390
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
D
Daniel Veillard 已提交
4391 4392
    } else {
        qemudShutdownVMDaemon (dconn, driver, vm);
4393 4394 4395
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
4396
        if (!vm->persistent) {
D
Daniel Veillard 已提交
4397
            virDomainRemoveInactive(&driver->domains, vm);
4398 4399
            vm = NULL;
        }
D
Daniel Veillard 已提交
4400
    }
4401 4402

cleanup:
4403 4404
    if (vm)
        virDomainObjUnlock(vm);
4405 4406
    if (event)
        qemuDomainEventQueue(driver, event);
4407
    qemuDriverUnlock(driver);
4408
    return dom;
D
Daniel Veillard 已提交
4409 4410
}

4411 4412 4413 4414 4415
static virDriver qemuDriver = {
    VIR_DRV_QEMU,
    "QEMU",
    qemudOpen, /* open */
    qemudClose, /* close */
D
Daniel Veillard 已提交
4416
    qemudSupportsFeature, /* supports_feature */
4417 4418
    qemudGetType, /* type */
    qemudGetVersion, /* version */
4419
    qemudGetHostname, /* hostname */
4420
    NULL, /* URI  */
4421 4422 4423 4424 4425
    qemudGetMaxVCPUs, /* getMaxVcpus */
    qemudGetNodeInfo, /* nodeGetInfo */
    qemudGetCapabilities, /* getCapabilities */
    qemudListDomains, /* listDomains */
    qemudNumDomains, /* numOfDomains */
4426
    qemudDomainCreate, /* domainCreateXML */
4427 4428 4429 4430 4431
    qemudDomainLookupByID, /* domainLookupByID */
    qemudDomainLookupByUUID, /* domainLookupByUUID */
    qemudDomainLookupByName, /* domainLookupByName */
    qemudDomainSuspend, /* domainSuspend */
    qemudDomainResume, /* domainResume */
4432
    qemudDomainShutdown, /* domainShutdown */
4433 4434 4435
    NULL, /* domainReboot */
    qemudDomainDestroy, /* domainDestroy */
    qemudDomainGetOSType, /* domainGetOSType */
4436 4437 4438
    qemudDomainGetMaxMemory, /* domainGetMaxMemory */
    qemudDomainSetMaxMemory, /* domainSetMaxMemory */
    qemudDomainSetMemory, /* domainSetMemory */
4439 4440 4441 4442
    qemudDomainGetInfo, /* domainGetInfo */
    qemudDomainSave, /* domainSave */
    qemudDomainRestore, /* domainRestore */
    NULL, /* domainCoreDump */
4443
    qemudDomainSetVcpus, /* domainSetVcpus */
4444 4445 4446 4447
#if HAVE_SCHED_GETAFFINITY
    qemudDomainPinVcpu, /* domainPinVcpu */
    qemudDomainGetVcpus, /* domainGetVcpus */
#else
4448 4449
    NULL, /* domainPinVcpu */
    NULL, /* domainGetVcpus */
4450
#endif
4451
    qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
4452 4453 4454 4455 4456 4457
    qemudDomainDumpXML, /* domainDumpXML */
    qemudListDefinedDomains, /* listDomains */
    qemudNumDefinedDomains, /* numOfDomains */
    qemudDomainStart, /* domainCreate */
    qemudDomainDefine, /* domainDefineXML */
    qemudDomainUndefine, /* domainUndefine */
4458
    qemudDomainAttachDevice, /* domainAttachDevice */
4459
    qemudDomainDetachDevice, /* domainDetachDevice */
4460 4461 4462 4463 4464
    qemudDomainGetAutostart, /* domainGetAutostart */
    qemudDomainSetAutostart, /* domainSetAutostart */
    NULL, /* domainGetSchedulerType */
    NULL, /* domainGetSchedulerParameters */
    NULL, /* domainSetSchedulerParameters */
D
Daniel Veillard 已提交
4465 4466
    NULL, /* domainMigratePrepare (v1) */
    qemudDomainMigratePerform, /* domainMigratePerform */
4467
    NULL, /* domainMigrateFinish */
4468
    qemudDomainBlockStats, /* domainBlockStats */
4469
    qemudDomainInterfaceStats, /* domainInterfaceStats */
4470
    qemudDomainBlockPeek, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
4471
    qemudDomainMemoryPeek, /* domainMemoryPeek */
4472 4473 4474 4475
#if HAVE_NUMACTL
    qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    qemudNodeGetFreeMemory,  /* getFreeMemory */
#else
4476
    NULL, /* nodeGetCellsFreeMemory */
4477
    NULL, /* getFreeMemory */
4478
#endif
4479 4480
    qemudDomainEventRegister, /* domainEventRegister */
    qemudDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
4481 4482
    qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
    qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
4483 4484 4485
};


4486
static virStateDriver qemuStateDriver = {
4487 4488 4489 4490
    .initialize = qemudStartup,
    .cleanup = qemudShutdown,
    .reload = qemudReload,
    .active = qemudActive,
4491
};
4492

4493
int qemuRegister(void) {
4494 4495 4496 4497
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}