qemu_driver.c 289.7 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, 2010 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
#include <sys/types.h>
#include <sys/poll.h>
28
#include <sys/time.h>
D
Daniel P. Berrange 已提交
29 30 31
#include <dirent.h>
#include <limits.h>
#include <string.h>
32
#include <stdbool.h>
D
Daniel P. Berrange 已提交
33 34 35 36 37 38
#include <stdio.h>
#include <strings.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
39
#include <sys/utsname.h>
40 41 42 43
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
44 45
#include <pwd.h>
#include <stdio.h>
46
#include <sys/wait.h>
47
#include <sys/ioctl.h>
48
#include <sys/un.h>
D
Daniel P. Berrange 已提交
49

50
#ifdef __linux__
51 52 53 54
# include <sys/vfs.h>
# ifndef NFS_SUPER_MAGIC
#  define NFS_SUPER_MAGIC 0x6969
# endif /* NFS_SUPER_MAGIC */
55
#endif /* __linux__ */
56

57
#include "virterror_internal.h"
58
#include "logging.h"
59
#include "datatypes.h"
60 61
#include "qemu_driver.h"
#include "qemu_conf.h"
62
#include "qemu_monitor.h"
63
#include "qemu_monitor_text.h"
64
#include "qemu_bridge_filter.h"
J
Jim Meyering 已提交
65
#include "c-ctype.h"
66
#include "event.h"
67
#include "buf.h"
68
#include "util.h"
69
#include "nodeinfo.h"
70
#include "stats_linux.h"
71
#include "capabilities.h"
72
#include "memory.h"
73
#include "uuid.h"
74
#include "domain_conf.h"
75 76
#include "node_device_conf.h"
#include "pci.h"
77
#include "hostusb.h"
78
#include "processinfo.h"
79 80
#include "qemu_security_stacked.h"
#include "qemu_security_dac.h"
81
#include "cgroup.h"
C
Chris Lalancette 已提交
82
#include "libvirt_internal.h"
83
#include "xml.h"
84
#include "cpu/cpu.h"
85
#include "macvtap.h"
86

87

88 89
#define VIR_FROM_THIS VIR_FROM_QEMU

90 91 92 93 94 95 96 97 98 99 100 101 102 103
/* Only 1 job is allowed at any time
 * A job includes *all* monitor commands, even those just querying
 * information, not merely actions */
enum qemuDomainJob {
    QEMU_JOB_NONE = 0,  /* Always set to 0 for easy if (jobActive) conditions */
    QEMU_JOB_UNSPECIFIED,
    QEMU_JOB_MIGRATION,
};

enum qemuDomainJobSignals {
    QEMU_JOB_SIGNAL_CANCEL  = 1 << 0, /* Request job cancellation */
    QEMU_JOB_SIGNAL_SUSPEND = 1 << 1, /* Request VM suspend to finish live migration offline */
};

104 105 106
typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
struct _qemuDomainObjPrivate {
107
    virCond jobCond; /* Use in conjunction with main virDomainObjPtr lock */
108 109
    enum qemuDomainJob jobActive;   /* Currently running job */
    unsigned int jobSignals;        /* Signals for running job */
110 111
    virDomainJobInfo jobInfo;
    unsigned long long jobStart;
112

113
    qemuMonitorPtr mon;
114
    virDomainChrDefPtr monConfig;
D
Daniel P. Berrange 已提交
115
    int monJSON;
116 117 118

    int nvcpupids;
    int *vcpupids;
119 120

    qemuDomainPCIAddressSetPtr pciaddrs;
121
    int persistentAddrs;
122 123
};

124 125
static int qemudShutdown(void);

126 127
static void qemuDriverLock(struct qemud_driver *driver)
{
128
    virMutexLock(&driver->lock);
129 130 131
}
static void qemuDriverUnlock(struct qemud_driver *driver)
{
132
    virMutexUnlock(&driver->lock);
133 134
}

135 136 137
static void qemuDomainEventFlush(int timer, void *opaque);
static void qemuDomainEventQueue(struct qemud_driver *driver,
                                 virDomainEventPtr event);
138

139 140
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
141
                              virDomainObjPtr vm,
142 143
                              const char *migrateFrom,
                              int stdin_fd);
144

145
static void qemudShutdownVMDaemon(struct qemud_driver *driver,
146
                                  virDomainObjPtr vm);
147

148
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
149

150
static int qemuDetectVcpuPIDs(struct qemud_driver *driver,
151
                              virDomainObjPtr vm);
152

153 154 155
static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
                                       virDomainDefPtr def);

J
Jim Meyering 已提交
156
static struct qemud_driver *qemu_driver = NULL;
157

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

static void *qemuDomainObjPrivateAlloc(void)
{
    qemuDomainObjPrivatePtr priv;

    if (VIR_ALLOC(priv) < 0)
        return NULL;

    return priv;
}

static void qemuDomainObjPrivateFree(void *data)
{
    qemuDomainObjPrivatePtr priv = data;

173
    qemuDomainPCIAddressSetFree(priv->pciaddrs);
174 175 176
    virDomainChrDefFree(priv->monConfig);
    VIR_FREE(priv->vcpupids);

177 178 179 180 181 182 183 184 185
    /* This should never be non-NULL if we get here, but just in case... */
    if (priv->mon) {
        VIR_ERROR0("Unexpected QEMU monitor still active during domain deletion");
        qemuMonitorClose(priv->mon);
    }
    VIR_FREE(priv);
}


186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
{
    qemuDomainObjPrivatePtr priv = data;
    const char *monitorpath;

    /* priv->monitor_chr is set only for qemu */
    if (priv->monConfig) {
        switch (priv->monConfig->type) {
        case VIR_DOMAIN_CHR_TYPE_UNIX:
            monitorpath = priv->monConfig->data.nix.path;
            break;
        default:
        case VIR_DOMAIN_CHR_TYPE_PTY:
            monitorpath = priv->monConfig->data.file.path;
            break;
        }

        virBufferEscapeString(buf, "  <monitor path='%s'", monitorpath);
D
Daniel P. Berrange 已提交
204 205
        if (priv->monJSON)
            virBufferAddLit(buf, " json='1'");
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
        virBufferVSprintf(buf, " type='%s'/>\n",
                          virDomainChrTypeToString(priv->monConfig->type));
    }


    if (priv->nvcpupids) {
        int i;
        virBufferAddLit(buf, "  <vcpus>\n");
        for (i = 0 ; i < priv->nvcpupids ; i++) {
            virBufferVSprintf(buf, "    <vcpu pid='%d'/>\n", priv->vcpupids[i]);
        }
        virBufferAddLit(buf, "  </vcpus>\n");
    }

    return 0;
}

static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
{
    qemuDomainObjPrivatePtr priv = data;
    char *monitorpath;
    char *tmp;
    int n, i;
    xmlNodePtr *nodes = NULL;

    if (VIR_ALLOC(priv->monConfig) < 0) {
232
        virReportOOMError();
233 234 235
        goto error;
    }

236
    if (!(priv->monConfig->info.alias = strdup("monitor"))) {
237
        virReportOOMError();
238 239 240
        goto error;
    }

241
    if (!(monitorpath =
242
          virXPathString("string(./monitor[1]/@path)", ctxt))) {
243 244
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no monitor path"));
245 246 247
        goto error;
    }

248
    tmp = virXPathString("string(./monitor[1]/@type)", ctxt);
249 250 251 252 253 254
    if (tmp)
        priv->monConfig->type = virDomainChrTypeFromString(tmp);
    else
        priv->monConfig->type = VIR_DOMAIN_CHR_TYPE_PTY;
    VIR_FREE(tmp);

255
    if (virXPathBoolean("count(./monitor[@json = '1']) > 0", ctxt)) {
D
Daniel P. Berrange 已提交
256
        priv->monJSON = 1;
257 258 259
    } else {
        priv->monJSON = 0;
    }
D
Daniel P. Berrange 已提交
260

261 262 263 264 265 266 267 268 269
    switch (priv->monConfig->type) {
    case VIR_DOMAIN_CHR_TYPE_PTY:
        priv->monConfig->data.file.path = monitorpath;
        break;
    case VIR_DOMAIN_CHR_TYPE_UNIX:
        priv->monConfig->data.nix.path = monitorpath;
        break;
    default:
        VIR_FREE(monitorpath);
270 271 272
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unsupported monitor type '%s'"),
                        virDomainChrTypeToString(priv->monConfig->type));
273 274 275
        goto error;
    }

276
    n = virXPathNodeSet("./vcpus/vcpu", ctxt, &nodes);
277 278 279 280 281
    if (n < 0)
        goto error;
    if (n) {
        priv->nvcpupids = n;
        if (VIR_REALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) {
282
            virReportOOMError();
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
            goto error;
        }

        for (i = 0 ; i < n ; i++) {
            char *pidstr = virXMLPropString(nodes[i], "pid");
            if (!pidstr)
                goto error;

            if (virStrToLong_i(pidstr, NULL, 10, &(priv->vcpupids[i])) < 0) {
                VIR_FREE(pidstr);
                goto error;
            }
            VIR_FREE(pidstr);
        }
        VIR_FREE(nodes);
    }

    return 0;

error:
303 304
    virDomainChrDefFree(priv->monConfig);
    priv->monConfig = NULL;
305 306 307 308 309 310
    VIR_FREE(nodes);
    return -1;
}



311 312 313 314 315 316 317 318 319
/*
 * obj must be locked before calling, qemud_driver must NOT be locked
 *
 * This must be called by anything that will change the VM state
 * in any way, or anything that will use the QEMU monitor.
 *
 * Upon successful return, the object will have its ref count increased,
 * successful calls must be followed by EndJob eventually
 */
320 321 322 323

/* Give up waiting for mutex after 30 seconds */
#define QEMU_JOB_WAIT_TIME (1000ull * 30)

324 325 326 327
static int qemuDomainObjBeginJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
static int qemuDomainObjBeginJob(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
328 329 330 331
    struct timeval now;
    unsigned long long then;

    if (gettimeofday(&now, NULL) < 0) {
332
        virReportSystemError(errno, "%s",
333 334 335 336 337
                             _("cannot get time of day"));
        return -1;
    }
    then = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
    then += QEMU_JOB_WAIT_TIME;
338 339 340 341

    virDomainObjRef(obj);

    while (priv->jobActive) {
342
        if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
343
            virDomainObjUnref(obj);
344
            if (errno == ETIMEDOUT)
345 346
                qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
                                "%s", _("cannot acquire state change lock"));
347
            else
348
                virReportSystemError(errno,
349
                                     "%s", _("cannot acquire job mutex"));
350 351 352
            return -1;
        }
    }
353 354
    priv->jobActive = QEMU_JOB_UNSPECIFIED;
    priv->jobSignals = 0;
355 356
    priv->jobStart = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
    memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372

    return 0;
}

/*
 * obj must be locked before calling, qemud_driver must be locked
 *
 * This must be called by anything that will change the VM state
 * in any way, or anything that will use the QEMU monitor.
 */
static int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
                                           virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
static int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
                                           virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
373 374 375 376
    struct timeval now;
    unsigned long long then;

    if (gettimeofday(&now, NULL) < 0) {
377
        virReportSystemError(errno, "%s",
378 379 380 381 382
                             _("cannot get time of day"));
        return -1;
    }
    then = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
    then += QEMU_JOB_WAIT_TIME;
383 384 385 386 387

    virDomainObjRef(obj);
    qemuDriverUnlock(driver);

    while (priv->jobActive) {
388
        if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
389
            virDomainObjUnref(obj);
390
            if (errno == ETIMEDOUT)
391 392
                qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
                                "%s", _("cannot acquire state change lock"));
393
            else
394
                virReportSystemError(errno,
395
                                     "%s", _("cannot acquire job mutex"));
M
Matthias Bolte 已提交
396
            qemuDriverLock(driver);
397 398 399
            return -1;
        }
    }
400 401
    priv->jobActive = QEMU_JOB_UNSPECIFIED;
    priv->jobSignals = 0;
402 403
    priv->jobStart = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
    memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
404 405 406 407 408 409 410 411 412 413 414 415 416

    virDomainObjUnlock(obj);
    qemuDriverLock(driver);
    virDomainObjLock(obj);

    return 0;
}

/*
 * obj must be locked before calling, qemud_driver does not matter
 *
 * To be called after completing the work associated with the
 * earlier  qemuDomainBeginJob() call
417 418 419
 *
 * Returns remaining refcount on 'obj', maybe 0 to indicated it
 * was deleted
420
 */
421
static int ATTRIBUTE_RETURN_CHECK qemuDomainObjEndJob(virDomainObjPtr obj)
422 423 424
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

425 426
    priv->jobActive = QEMU_JOB_NONE;
    priv->jobSignals = 0;
427 428
    priv->jobStart = 0;
    memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
429 430
    virCondSignal(&priv->jobCond);

431
    return virDomainObjUnref(obj);
432 433 434 435 436 437 438 439 440 441 442
}


/*
 * obj must be locked before calling, qemud_driver must be unlocked
 *
 * To be called immediately before any QEMU monitor API call
 * Must have alrady called qemuDomainObjBeginJob().
 *
 * To be followed with qemuDomainObjExitMonitor() once complete
 */
443 444 445 446 447
static void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    qemuMonitorLock(priv->mon);
448
    qemuMonitorRef(priv->mon);
449
    virDomainObjUnlock(obj);
450 451 452
}


453 454 455 456
/* obj must NOT be locked before calling, qemud_driver must be unlocked
 *
 * Should be paired with an earlier  qemuDomainObjEnterMonitor() call
 */
457 458 459
static void qemuDomainObjExitMonitor(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
460 461 462 463 464 465
    int refs;

    refs = qemuMonitorUnref(priv->mon);

    if (refs > 0)
        qemuMonitorUnlock(priv->mon);
466

467
    virDomainObjLock(obj);
468 469 470 471 472

    if (refs == 0) {
        virDomainObjUnref(obj);
        priv->mon = NULL;
    }
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
}


/*
 * obj must be locked before calling, qemud_driver must be locked
 *
 * To be called immediately before any QEMU monitor API call
 * Must have alrady called qemuDomainObjBeginJob().
 *
 * To be followed with qemuDomainObjExitMonitorWithDriver() once complete
 */
static void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    qemuMonitorLock(priv->mon);
489
    qemuMonitorRef(priv->mon);
490 491 492 493 494 495 496 497 498 499 500 501 502
    virDomainObjUnlock(obj);
    qemuDriverUnlock(driver);
}


/* obj must NOT be locked before calling, qemud_driver must be unlocked,
 * and will be locked after returning
 *
 * Should be paired with an earlier  qemuDomainObjEnterMonitor() call
 */
static void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
503 504 505 506 507 508
    int refs;

    refs = qemuMonitorUnref(priv->mon);

    if (refs > 0)
        qemuMonitorUnlock(priv->mon);
509 510 511

    qemuDriverLock(driver);
    virDomainObjLock(obj);
512 513 514 515 516

    if (refs == 0) {
        virDomainObjUnref(obj);
        priv->mon = NULL;
    }
517 518 519
}


520 521 522 523 524 525 526 527 528
static int qemuCgroupControllerActive(struct qemud_driver *driver,
                                      int controller)
{
    if (driver->cgroup == NULL)
        return 0;
    if (driver->cgroupControllers & (1 << controller))
        return 1;
    return 0;
}
529

530
static int
531
qemudLogFD(struct qemud_driver *driver, const char* name)
532 533 534
{
    char logfile[PATH_MAX];
    mode_t logmode;
G
Guido Günther 已提交
535
    int ret, fd = -1;
536

537 538
    if ((ret = snprintf(logfile, sizeof(logfile), "%s/%s.log",
                        driver->logDir, name))
G
Guido Günther 已提交
539
        < 0 || ret >= sizeof(logfile)) {
540
        virReportOOMError();
541 542 543 544
        return -1;
    }

    logmode = O_CREAT | O_WRONLY;
545 546
    /* Only logrotate files in /var/log, so only append if running privileged */
    if (driver->privileged)
547
        logmode |= O_APPEND;
548 549 550
    else
        logmode |= O_TRUNC;

551
    if ((fd = open(logfile, logmode, S_IRUSR | S_IWUSR)) < 0) {
552
        virReportSystemError(errno,
553 554
                             _("failed to create logfile %s"),
                             logfile);
555 556
        return -1;
    }
557
    if (virSetCloseExec(fd) < 0) {
558
        virReportSystemError(errno, "%s",
559
                             _("Unable to set VM logfile close-on-exec flag"));
560 561 562 563 564 565 566
        close(fd);
        return -1;
    }
    return fd;
}


567
static int
568
qemudLogReadFD(const char* logDir, const char* name, off_t pos)
569 570 571 572 573 574 575
{
    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)) {
576 577 578
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("failed to build logfile name %s/%s.log"),
                        logDir, name);
579 580 581 582 583
        return -1;
    }


    if ((fd = open(logfile, logmode)) < 0) {
584
        virReportSystemError(errno,
585 586
                             _("failed to create logfile %s"),
                             logfile);
587 588
        return -1;
    }
589
    if (virSetCloseExec(fd) < 0) {
590
        virReportSystemError(errno, "%s",
591
                             _("Unable to set VM logfile close-on-exec flag"));
592 593 594
        close(fd);
        return -1;
    }
595
    if (pos < 0 || lseek(fd, pos, SEEK_SET) < 0) {
596
      virReportSystemError(pos < 0 ? 0 : errno,
597 598
                             _("Unable to seek to %lld in %s"),
                             (long long) pos, logfile);
599 600 601 602 603 604
        close(fd);
    }
    return fd;
}


605 606 607 608 609 610 611 612 613 614 615 616
struct qemuAutostartData {
    struct qemud_driver *driver;
    virConnectPtr conn;
};
static void
qemuAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
{
    virDomainObjPtr vm = payload;
    struct qemuAutostartData *data = opaque;

    virDomainObjLock(vm);
    if (vm->autostart &&
D
Daniel P. Berrange 已提交
617
        !virDomainObjIsActive(vm)) {
618 619 620 621 622 623
        int ret;

        virResetLastError();
        ret = qemudStartVMDaemon(data->conn, data->driver, vm, NULL, -1);
        if (ret < 0) {
            virErrorPtr err = virGetLastError();
624
            VIR_ERROR(_("Failed to autostart VM '%s': %s"),
625 626 627 628 629 630 631 632 633 634 635 636 637 638
                      vm->def->name,
                      err ? err->message : "");
        } else {
            virDomainEventPtr event =
                virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
            if (event)
                qemuDomainEventQueue(data->driver, event);
        }
    }
    virDomainObjUnlock(vm);
}

639 640
static void
qemudAutostartConfigs(struct qemud_driver *driver) {
641 642 643 644 645
    /* 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
     */
646 647 648
    virConnectPtr conn = virConnectOpen(driver->privileged ?
                                        "qemu:///system" :
                                        "qemu:///session");
649
    /* Ignoring NULL conn which is mostly harmless here */
650
    struct qemuAutostartData data = { driver, conn };
651

652
    qemuDriverLock(driver);
653
    virHashForEach(driver->domains.objs, qemuAutostartDomain, &data);
654
    qemuDriverUnlock(driver);
655

656 657
    if (conn)
        virConnectClose(conn);
658 659
}

660 661 662 663 664 665 666 667 668

/**
 * qemudRemoveDomainStatus
 *
 * remove all state files of a domain from statedir
 *
 * Returns 0 on success
 */
static int
669
qemudRemoveDomainStatus(struct qemud_driver *driver,
670 671
                        virDomainObjPtr vm)
{
672
    char ebuf[1024];
673 674 675
    char *file = NULL;

    if (virAsprintf(&file, "%s/%s.xml", driver->stateDir, vm->def->name) < 0) {
676
        virReportOOMError();
D
Daniel Veillard 已提交
677
        return(-1);
678 679
    }

680 681
    if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR)
        VIR_WARN(_("Failed to remove domain XML for %s: %s"),
D
Daniel Veillard 已提交
682 683 684
                 vm->def->name, virStrerror(errno, ebuf, sizeof(ebuf)));
    VIR_FREE(file);

685 686 687
    if (virFileDeletePid(driver->stateDir, vm->def->name) != 0)
        VIR_WARN(_("Failed to remove PID file for %s: %s"),
                 vm->def->name, virStrerror(errno, ebuf, sizeof(ebuf)));
688

D
Daniel Veillard 已提交
689

690
    return 0;
691 692
}

693 694 695 696 697 698 699 700 701 702 703 704 705 706

/*
 * This is a callback registered with a qemuMonitorPtr  instance,
 * and to be invoked when the monitor console hits an end of file
 * condition, or error, thus indicating VM shutdown should be
 * performed
 */
static void
qemuHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                     virDomainObjPtr vm,
                     int hasError) {
    struct qemud_driver *driver = qemu_driver;
    virDomainEventPtr event = NULL;

707
    VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name);
708 709 710 711 712 713 714 715
    virDomainObjLock(vm);

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     hasError ?
                                     VIR_DOMAIN_EVENT_STOPPED_FAILED :
                                     VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);

716
    qemudShutdownVMDaemon(driver, vm);
717 718 719 720 721 722 723 724 725 726 727 728 729
    if (!vm->persistent)
        virDomainRemoveInactive(&driver->domains, vm);
    else
        virDomainObjUnlock(vm);

    if (event) {
        qemuDriverLock(driver);
        qemuDomainEventQueue(driver, event);
        qemuDriverUnlock(driver);
    }
}


730 731 732
static virDomainDiskDefPtr
findDomainDiskByPath(virDomainObjPtr vm,
                     const char *path)
733 734 735 736 737 738 739
{
    int i;

    for (i = 0; i < vm->def->ndisks; i++) {
        virDomainDiskDefPtr disk;

        disk = vm->def->disks[i];
740 741
        if (disk->src != NULL && STREQ(disk->src, path))
            return disk;
742
    }
743 744 745 746

    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    _("no disk found with path %s"),
                    path);
747 748 749 750
    return NULL;
}

static int
751 752 753 754
getVolumeQcowPassphrase(virConnectPtr conn,
                        virDomainDiskDefPtr disk,
                        char **secretRet,
                        size_t *secretLen)
755 756 757 758 759
{
    virSecretPtr secret;
    char *passphrase;
    unsigned char *data;
    size_t size;
760
    int ret = -1;
761
    virStorageEncryptionPtr enc;
762

763 764 765 766 767 768 769
    if (!disk->encryption) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("disk %s does not have any encryption information"),
                        disk->src);
        return -1;
    }
    enc = disk->encryption;
770 771

    if (!conn) {
772 773
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("cannot find secrets without a connection"));
774
        goto cleanup;
775 776 777 778 779
    }

    if (conn->secretDriver == NULL ||
        conn->secretDriver->lookupByUUID == NULL ||
        conn->secretDriver->getValue == NULL) {
780 781
        qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
                        _("secret storage not supported"));
782
        goto cleanup;
783 784 785 786 787 788
    }

    if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
        enc->nsecrets != 1 ||
        enc->secrets[0]->type !=
        VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) {
789
        qemuReportError(VIR_ERR_INVALID_DOMAIN,
790
                        _("invalid <encryption> for volume %s"), disk->src);
791
        goto cleanup;
792 793 794 795 796
    }

    secret = conn->secretDriver->lookupByUUID(conn,
                                              enc->secrets[0]->uuid);
    if (secret == NULL)
797
        goto cleanup;
798 799 800 801
    data = conn->secretDriver->getValue(secret, &size,
                                        VIR_SECRET_GET_VALUE_INTERNAL_CALL);
    virUnrefSecret(secret);
    if (data == NULL)
802
        goto cleanup;
803 804 805 806

    if (memchr(data, '\0', size) != NULL) {
        memset(data, 0, size);
        VIR_FREE(data);
807 808
        qemuReportError(VIR_ERR_INVALID_SECRET,
                        _("format='qcow' passphrase for %s must not contain a "
809
                          "'\\0'"), disk->src);
810
        goto cleanup;
811 812 813 814 815
    }

    if (VIR_ALLOC_N(passphrase, size + 1) < 0) {
        memset(data, 0, size);
        VIR_FREE(data);
816
        virReportOOMError();
817
        goto cleanup;
818 819 820 821 822 823 824 825 826 827
    }
    memcpy(passphrase, data, size);
    passphrase[size] = '\0';

    memset(data, 0, size);
    VIR_FREE(data);

    *secretRet = passphrase;
    *secretLen = size;

828 829 830
    ret = 0;

cleanup:
831 832
    return ret;
}
833

834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
static int
findVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                         virConnectPtr conn,
                         virDomainObjPtr vm,
                         const char *path,
                         char **secretRet,
                         size_t *secretLen)
{
    virDomainDiskDefPtr disk;
    int ret = -1;

    virDomainObjLock(vm);
    disk = findDomainDiskByPath(vm, path);

    if (!disk)
        goto cleanup;

    ret = getVolumeQcowPassphrase(conn, disk, secretRet, secretLen);

cleanup:
    virDomainObjUnlock(vm);
855
    return ret;
856 857
}

858 859 860 861 862
static qemuMonitorCallbacks monitorCallbacks = {
    .eofNotify = qemuHandleMonitorEOF,
    .diskSecretLookup = findVolumeQcowPassphrase,
};

863
static int
864
qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm)
865
{
866
    qemuDomainObjPrivatePtr priv = vm->privateData;
867
    int ret;
868

869 870 871 872
    /* Hold an extra reference because we can't allow 'vm' to be
     * deleted while the monitor is active */
    virDomainObjRef(vm);

873 874
    if ((priv->mon = qemuMonitorOpen(vm,
                                     priv->monConfig,
D
Daniel P. Berrange 已提交
875
                                     priv->monJSON,
876
                                     &monitorCallbacks)) == NULL) {
877
        VIR_ERROR(_("Failed to connect monitor for %s"), vm->def->name);
878
        return -1;
879
    }
880

881 882 883 884 885 886 887 888 889 890
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
    ret = qemuMonitorSetCapabilities(priv->mon);
    qemuDomainObjExitMonitorWithDriver(driver, vm);

    if (ret < 0) {
        qemuMonitorClose(priv->mon);
        priv->mon = NULL;
    }

    return ret;
891
}
892 893 894 895

/*
 * Open an existing VM's monitor, re-detect VCPU threads
 * and re-reserve the security labels in use
896
 */
897 898
static void
qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
899
{
900 901
    virDomainObjPtr obj = payload;
    struct qemud_driver *driver = opaque;
902
    qemuDomainObjPrivatePtr priv;
903
    unsigned long long qemuCmdFlags;
904 905

    virDomainObjLock(obj);
906

907 908
    VIR_DEBUG("Reconnect monitor to %p '%s'", obj, obj->def->name);

909 910
    priv = obj->privateData;

911
    /* XXX check PID liveliness & EXE path */
912
    if (qemuConnectMonitor(driver, obj) < 0)
913
        goto error;
914

915 916 917 918
    if (qemuUpdateActivePciHostdevs(driver, obj->def) < 0) {
        goto error;
    }

919 920 921 922 923 924 925 926 927
    /* XXX we should be persisting the original flags in the XML
     * not re-detecting them, since the binary may have changed
     * since launch time */
    if (qemudExtractVersionInfo(obj->def->emulator,
                                NULL,
                                &qemuCmdFlags) >= 0 &&
        (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
        priv->persistentAddrs = 1;

928 929 930
    if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(obj->def)))
        goto error;

931
    if (driver->securityDriver &&
932
        driver->securityDriver->domainReserveSecurityLabel &&
933
        driver->securityDriver->domainReserveSecurityLabel(obj) < 0)
934
        goto error;
935

936 937
    if (obj->def->id >= driver->nextvmid)
        driver->nextvmid = obj->def->id + 1;
938

939 940
    virDomainObjUnlock(obj);
    return;
941

942
error:
943 944 945
    /* We can't get the monitor back, so must kill the VM
     * to remove danger of it ending up running twice if
     * user tries to start it again later */
946
    qemudShutdownVMDaemon(driver, obj);
947 948 949 950
    if (!obj->persistent)
        virDomainRemoveInactive(&driver->domains, obj);
    else
        virDomainObjUnlock(obj);
951
}
952

953
/**
954
 * qemudReconnectDomains
955 956 957 958 959 960 961
 *
 * Try to re-open the resources for live VMs that we care
 * about.
 */
static void
qemuReconnectDomains(struct qemud_driver *driver)
{
962
    virHashForEach(driver->domains.objs, qemuReconnectDomain, driver);
963 964
}

965

966 967 968 969 970 971
static int
qemudSecurityInit(struct qemud_driver *qemud_drv)
{
    int ret;
    virSecurityDriverPtr security_drv;

972 973 974
    qemuSecurityStackedSetDriver(qemud_drv);
    qemuSecurityDACSetDriver(qemud_drv);

975 976 977 978 979 980
    ret = virSecurityDriverStartup(&security_drv,
                                   qemud_drv->securityDriverName);
    if (ret == -1) {
        VIR_ERROR0(_("Failed to start security driver"));
        return -1;
    }
981 982 983

    /* No primary security driver wanted to be enabled: just setup
     * the DAC driver on its own */
984
    if (ret == -2) {
985
        qemud_drv->securityDriver = &qemuDACSecurityDriver;
986
        VIR_INFO0(_("No security driver available"));
987 988 989 990 991
    } else {
        qemud_drv->securityPrimaryDriver = security_drv;
        qemud_drv->securitySecondaryDriver = &qemuDACSecurityDriver;
        qemud_drv->securityDriver = &qemuStackedSecurityDriver;
        VIR_INFO("Initialized security driver %s", security_drv->name);
992 993
    }

994
    return 0;
995
}
996 997


998 999
static virCapsPtr
qemuCreateCapabilities(virCapsPtr oldcaps,
1000
                       struct qemud_driver *driver)
1001 1002 1003 1004 1005
{
    virCapsPtr caps;

    /* Basic host arch / guest machine capabilities */
    if (!(caps = qemudCapsInit(oldcaps))) {
1006
        virReportOOMError();
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
        return NULL;
    }

    /* Domain XML parser hooks */
    caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc;
    caps->privateDataFreeFunc = qemuDomainObjPrivateFree;
    caps->privateDataXMLFormat = qemuDomainObjPrivateXMLFormat;
    caps->privateDataXMLParse = qemuDomainObjPrivateXMLParse;


    /* Security driver data */
1018
    if (driver->securityPrimaryDriver) {
1019 1020
        const char *doi, *model;

1021 1022
        doi = virSecurityDriverGetDOI(driver->securityPrimaryDriver);
        model = virSecurityDriverGetModel(driver->securityPrimaryDriver);
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035

        if (!(caps->host.secModel.model = strdup(model)))
            goto no_memory;
        if (!(caps->host.secModel.doi = strdup(doi)))
            goto no_memory;

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

    return caps;

no_memory:
1036
    virReportOOMError();
1037 1038 1039
    virCapabilitiesFree(caps);
    return NULL;
}
1040

1041 1042 1043 1044 1045 1046
/**
 * qemudStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
1047
qemudStartup(int privileged) {
1048
    char *base = NULL;
D
Daniel P. Berrange 已提交
1049
    char driverConf[PATH_MAX];
1050
    int rc;
1051

1052
    if (VIR_ALLOC(qemu_driver) < 0)
1053 1054
        return -1;

1055
    if (virMutexInit(&qemu_driver->lock) < 0) {
1056
        VIR_ERROR("%s", _("cannot initialize mutex"));
1057 1058 1059
        VIR_FREE(qemu_driver);
        return -1;
    }
1060
    qemuDriverLock(qemu_driver);
1061
    qemu_driver->privileged = privileged;
1062

1063 1064 1065
    /* Don't have a dom0 so start from 1 */
    qemu_driver->nextvmid = 1;

1066 1067 1068
    if (virDomainObjListInit(&qemu_driver->domains) < 0)
        goto out_of_memory;

1069
    /* Init callback list */
1070
    if (VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
1071
        goto out_of_memory;
1072 1073 1074 1075 1076 1077
    if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew()))
        goto out_of_memory;

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

1079
    if (privileged) {
1080 1081
        if (virAsprintf(&qemu_driver->logDir,
                        "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
1082
            goto out_of_memory;
1083

D
Daniel P. Berrange 已提交
1084
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
1085
            goto out_of_memory;
1086 1087

        if (virAsprintf(&qemu_driver->stateDir,
1088
                      "%s/run/libvirt/qemu", LOCAL_STATE_DIR) == -1)
1089
            goto out_of_memory;
1090 1091 1092 1093 1094 1095 1096 1097

        if (virAsprintf(&qemu_driver->libDir,
                      "%s/lib/libvirt/qemu", LOCAL_STATE_DIR) == -1)
            goto out_of_memory;

        if (virAsprintf(&qemu_driver->cacheDir,
                      "%s/cache/libvirt/qemu", LOCAL_STATE_DIR) == -1)
            goto out_of_memory;
1098
    } else {
1099
        uid_t uid = geteuid();
1100
        char *userdir = virGetUserDirectory(uid);
1101
        if (!userdir)
1102
            goto error;
1103

1104
        if (virAsprintf(&qemu_driver->logDir,
1105 1106
                        "%s/.libvirt/qemu/log", userdir) == -1) {
            VIR_FREE(userdir);
1107
            goto out_of_memory;
1108
        }
1109

1110 1111
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
            VIR_FREE(userdir);
1112
            goto out_of_memory;
1113 1114
        }
        VIR_FREE(userdir);
1115 1116 1117

        if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", base) == -1)
            goto out_of_memory;
1118 1119 1120 1121
        if (virAsprintf(&qemu_driver->libDir, "%s/qemu/lib", base) == -1)
            goto out_of_memory;
        if (virAsprintf(&qemu_driver->cacheDir, "%s/qemu/cache", base) == -1)
            goto out_of_memory;
1122 1123
    }

L
Laine Stump 已提交
1124
    if (virFileMakePath(qemu_driver->stateDir) != 0) {
1125
        char ebuf[1024];
1126
        VIR_ERROR(_("Failed to create state dir '%s': %s"),
1127
                  qemu_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
1128
        goto error;
1129
    }
L
Laine Stump 已提交
1130
    if (virFileMakePath(qemu_driver->libDir) != 0) {
1131
        char ebuf[1024];
1132
        VIR_ERROR(_("Failed to create lib dir '%s': %s"),
1133 1134 1135
                  qemu_driver->libDir, virStrerror(errno, ebuf, sizeof ebuf));
        goto error;
    }
L
Laine Stump 已提交
1136
    if (virFileMakePath(qemu_driver->cacheDir) != 0) {
1137
        char ebuf[1024];
1138
        VIR_ERROR(_("Failed to create cache dir '%s': %s"),
1139 1140 1141
                  qemu_driver->cacheDir, virStrerror(errno, ebuf, sizeof ebuf));
        goto error;
    }
1142 1143 1144 1145

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

1150
    if (virAsprintf(&qemu_driver->configDir, "%s/qemu", base) == -1)
1151 1152
        goto out_of_memory;

1153
    if (virAsprintf(&qemu_driver->autostartDir, "%s/qemu/autostart", base) == -1)
1154 1155
        goto out_of_memory;

1156
    VIR_FREE(base);
1157

1158 1159 1160 1161 1162 1163 1164
    rc = virCgroupForDriver("qemu", &qemu_driver->cgroup, privileged, 1);
    if (rc < 0) {
        char buf[1024];
        VIR_WARN("Unable to create cgroup for driver: %s",
                 virStrerror(-rc, buf, sizeof(buf)));
    }

1165 1166 1167 1168
    if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
        goto error;
    }

1169 1170
    if (qemudSecurityInit(qemu_driver) < 0)
        goto error;
D
Daniel P. Berrange 已提交
1171

1172
    if ((qemu_driver->caps = qemuCreateCapabilities(NULL,
1173
                                                    qemu_driver)) == NULL)
1174
        goto error;
1175

1176
    if ((qemu_driver->activePciHostdevs = pciDeviceListNew()) == NULL)
1177 1178
        goto error;

1179 1180
    if (privileged) {
        if (chown(qemu_driver->libDir, qemu_driver->user, qemu_driver->group) < 0) {
1181
            virReportSystemError(errno,
1182 1183 1184 1185 1186
                                 _("unable to set ownership of '%s' to user %d:%d"),
                                 qemu_driver->libDir, qemu_driver->user, qemu_driver->group);
            goto error;
        }
        if (chown(qemu_driver->cacheDir, qemu_driver->user, qemu_driver->group) < 0) {
1187
            virReportSystemError(errno,
1188 1189 1190 1191 1192 1193
                                 _("unable to set ownership of '%s' to %d:%d"),
                                 qemu_driver->cacheDir, qemu_driver->user, qemu_driver->group);
            goto error;
        }
    }

1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
    /* If hugetlbfs is present, then we need to create a sub-directory within
     * it, since we can't assume the root mount point has permissions that
     * will let our spawned QEMU instances use it.
     *
     * NB the check for '/', since user may config "" to disable hugepages
     * even when mounted
     */
    if (qemu_driver->hugetlbfs_mount &&
        qemu_driver->hugetlbfs_mount[0] == '/') {
        char *mempath = NULL;
        if (virAsprintf(&mempath, "%s/libvirt/qemu", qemu_driver->hugetlbfs_mount) < 0)
            goto out_of_memory;

        if ((rc = virFileMakePath(mempath)) != 0) {
1208
            virReportSystemError(rc,
1209 1210 1211 1212 1213 1214
                                 _("unable to create hugepage path %s"), mempath);
            VIR_FREE(mempath);
            goto error;
        }
        if (qemu_driver->privileged &&
            chown(mempath, qemu_driver->user, qemu_driver->group) < 0) {
1215
            virReportSystemError(errno,
1216 1217 1218 1219 1220 1221 1222 1223 1224
                                 _("unable to set ownership on %s to %d:%d"),
                                 mempath, qemu_driver->user, qemu_driver->group);
            VIR_FREE(mempath);
            goto error;
        }

        qemu_driver->hugepage_path = mempath;
    }

1225
    /* Get all the running persistent or transient configs first */
1226
    if (virDomainLoadAllConfigs(qemu_driver->caps,
1227 1228 1229 1230 1231 1232 1233 1234 1235
                                &qemu_driver->domains,
                                qemu_driver->stateDir,
                                NULL,
                                1, NULL, NULL) < 0)
        goto error;

    qemuReconnectDomains(qemu_driver);

    /* Then inactive persistent configs */
1236
    if (virDomainLoadAllConfigs(qemu_driver->caps,
1237 1238
                                &qemu_driver->domains,
                                qemu_driver->configDir,
1239
                                qemu_driver->autostartDir,
1240
                                0, NULL, NULL) < 0)
1241
        goto error;
1242 1243
    qemuDriverUnlock(qemu_driver);

1244 1245
    qemudAutostartConfigs(qemu_driver);

1246

1247 1248
    return 0;

1249
out_of_memory:
1250
    virReportOOMError();
1251 1252 1253
error:
    if (qemu_driver)
        qemuDriverUnlock(qemu_driver);
1254
    VIR_FREE(base);
1255
    qemudShutdown();
1256 1257 1258
    return -1;
}

1259 1260 1261 1262
static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
{
    struct qemud_driver *driver = opaque;

1263 1264 1265 1266 1267 1268 1269 1270
    if (newVM) {
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }
1271 1272
}

1273 1274 1275 1276 1277 1278 1279 1280
/**
 * qemudReload:
 *
 * Function to restart the QEmu daemon, it will recheck the configuration
 * files and update its state and the networking
 */
static int
qemudReload(void) {
1281 1282 1283
    if (!qemu_driver)
        return 0;

1284
    qemuDriverLock(qemu_driver);
1285
    virDomainLoadAllConfigs(qemu_driver->caps,
1286 1287
                            &qemu_driver->domains,
                            qemu_driver->configDir,
1288
                            qemu_driver->autostartDir,
1289
                            0, qemudNotifyLoadDomain, qemu_driver);
1290
    qemuDriverUnlock(qemu_driver);
1291

1292
    qemudAutostartConfigs(qemu_driver);
1293 1294

    return 0;
1295 1296
}

1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
/**
 * 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) {
1307
    int active = 0;
1308

1309 1310 1311
    if (!qemu_driver)
        return 0;

1312
    /* XXX having to iterate here is not great because it requires many locks */
1313
    qemuDriverLock(qemu_driver);
1314
    active = virDomainObjListNumOfDomains(&qemu_driver->domains, 1);
1315 1316
    qemuDriverUnlock(qemu_driver);
    return active;
1317 1318
}

1319 1320 1321 1322 1323 1324 1325
/**
 * qemudShutdown:
 *
 * Shutdown the QEmu daemon, it will stop all active domains and networks
 */
static int
qemudShutdown(void) {
1326
    int i;
1327

1328
    if (!qemu_driver)
1329
        return -1;
1330

1331
    qemuDriverLock(qemu_driver);
1332
    pciDeviceListFree(qemu_driver->activePciHostdevs);
1333 1334
    virCapabilitiesFree(qemu_driver->caps);

1335
    virDomainObjListDeinit(&qemu_driver->domains);
1336

1337
    VIR_FREE(qemu_driver->securityDriverName);
1338
    VIR_FREE(qemu_driver->logDir);
1339 1340
    VIR_FREE(qemu_driver->configDir);
    VIR_FREE(qemu_driver->autostartDir);
1341
    VIR_FREE(qemu_driver->stateDir);
1342 1343
    VIR_FREE(qemu_driver->libDir);
    VIR_FREE(qemu_driver->cacheDir);
1344
    VIR_FREE(qemu_driver->vncTLSx509certdir);
J
Jim Meyering 已提交
1345
    VIR_FREE(qemu_driver->vncListen);
1346
    VIR_FREE(qemu_driver->vncPassword);
1347
    VIR_FREE(qemu_driver->vncSASLdir);
1348
    VIR_FREE(qemu_driver->saveImageFormat);
1349 1350
    VIR_FREE(qemu_driver->hugetlbfs_mount);
    VIR_FREE(qemu_driver->hugepage_path);
D
Daniel P. Berrange 已提交
1351

1352 1353 1354 1355 1356 1357
    if (qemu_driver->cgroupDeviceACL) {
        for (i = 0 ; qemu_driver->cgroupDeviceACL[i] != NULL ; i++)
            VIR_FREE(qemu_driver->cgroupDeviceACL[i]);
        VIR_FREE(qemu_driver->cgroupDeviceACL);
    }

1358 1359
    /* Free domain callback list */
    virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
1360 1361 1362 1363
    virDomainEventQueueFree(qemu_driver->domainEventQueue);

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

1365 1366 1367
    if (qemu_driver->brctl)
        brShutdown(qemu_driver->brctl);

1368 1369
    virCgroupFree(&qemu_driver->cgroup);

1370
    qemuDriverUnlock(qemu_driver);
1371
    virMutexDestroy(&qemu_driver->lock);
1372
    VIR_FREE(qemu_driver);
1373 1374

    return 0;
1375 1376
}

1377
typedef int qemuLogHandleOutput(virDomainObjPtr vm,
1378 1379
                                const char *output,
                                int fd);
1380 1381 1382 1383 1384

/*
 * Returns -1 for error, 0 on success
 */
static int
1385
qemudReadLogOutput(virDomainObjPtr vm,
1386 1387
                   int fd,
                   char *buf,
G
Guido Günther 已提交
1388
                   size_t buflen,
1389
                   qemuLogHandleOutput func,
1390 1391 1392
                   const char *what,
                   int timeout)
{
1393
    int retries = (timeout*10);
1394
    int got = 0;
1395 1396 1397
    buf[0] = '\0';

    while (retries) {
1398
        ssize_t func_ret, ret;
1399
        int isdead = 0;
G
Guido Günther 已提交
1400

1401
        func_ret = func(vm, buf, fd);
1402

1403 1404
        if (kill(vm->pid, 0) == -1 && errno == ESRCH)
            isdead = 1;
1405

1406 1407
        /* Any failures should be detected before we read the log, so we
         * always have something useful to report on failure. */
1408 1409
        ret = saferead(fd, buf+got, buflen-got-1);
        if (ret < 0) {
1410
            virReportSystemError(errno,
1411 1412 1413 1414 1415
                                 _("Failure while reading %s log output"),
                                 what);
            return -1;
        }

1416 1417 1418
        got += ret;
        buf[got] = '\0';
        if (got == buflen-1) {
1419
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
1420 1421
                            _("Out of space while reading %s log output: %s"),
                            what, buf);
1422 1423 1424 1425
            return -1;
        }

        if (isdead) {
1426
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
1427 1428
                            _("Process exited while reading %s log output: %s"),
                            what, buf);
1429 1430 1431
            return -1;
        }

1432 1433
        if (func_ret <= 0)
            return func_ret;
1434 1435 1436 1437

        usleep(100*1000);
        retries--;
    }
1438

1439
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
1440 1441
                    _("Timed out while reading %s log output: %s"),
                    what, buf);
1442 1443 1444
    return -1;
}

1445

1446 1447 1448 1449 1450 1451 1452 1453
/*
 * Look at a chunk of data from the QEMU stdout logs and try to
 * find a TTY device, as indicated by a line like
 *
 * char device redirected to /dev/pts/3
 *
 * Returns -1 for error, 0 success, 1 continue reading
 */
1454
static int
1455
qemudExtractTTYPath(const char *haystack,
1456 1457
                    size_t *offset,
                    char **path)
1458
{
1459
    static const char needle[] = "char device redirected to";
1460
    char *tmp, *dev;
1461

1462
    VIR_FREE(*path);
1463
    /* First look for our magic string */
1464 1465 1466 1467 1468
    if (!(tmp = strstr(haystack + *offset, needle))) {
        return 1;
    }
    tmp += sizeof(needle);
    dev = tmp;
1469

1470 1471 1472 1473 1474
    /*
     * And look for first whitespace character and nul terminate
     * to mark end of the pty path
     */
    while (*tmp) {
1475
        if (c_isspace(*tmp)) {
1476 1477
            *path = strndup(dev, tmp-dev);
            if (*path == NULL) {
1478
                virReportOOMError();
1479 1480
                return -1;
            }
1481

1482
            /* ... now further update offset till we get EOL */
1483
            *offset = tmp - haystack;
1484 1485
            return 0;
        }
1486
        tmp++;
1487 1488 1489 1490 1491
    }

    /*
     * We found a path, but didn't find any whitespace,
     * so it must be still incomplete - we should at
1492 1493
     * least see a \n - indicate that we want to carry
     * on trying again
1494
     */
1495
    return 1;
1496 1497
}

1498
static int
1499
qemudFindCharDevicePTYsMonitor(virDomainObjPtr vm,
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514
                               virHashTablePtr paths)
{
    int i;

#define LOOKUP_PTYS(array, arraylen, idprefix)                            \
    for (i = 0 ; i < (arraylen) ; i++) {                                  \
        virDomainChrDefPtr chr = (array)[i];                              \
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {                       \
            char id[16];                                                  \
                                                                          \
            if (snprintf(id, sizeof(id), idprefix "%i", i) >= sizeof(id)) \
                return -1;                                                \
                                                                          \
            const char *path = (const char *) virHashLookup(paths, id);   \
            if (path == NULL) {                                           \
1515 1516 1517
                if (chr->data.file.path == NULL) {                        \
                    /* neither the log output nor 'info chardev' had a */ \
                    /* pty path for this chardev, report an error */      \
1518 1519 1520
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,               \
                                    _("no assigned pty for device %s"), id); \
                    return -1;                                            \
1521 1522 1523 1524 1525
                } else {                                                  \
                    /* 'info chardev' had no pty path for this chardev, */\
                    /* but the log output had, so we're fine */           \
                    continue;                                             \
                }                                                         \
1526 1527
            }                                                             \
                                                                          \
1528
            VIR_FREE(chr->data.file.path);                                \
1529
            chr->data.file.path = strdup(path);                           \
1530 1531
                                                                          \
            if (chr->data.file.path == NULL) {                            \
1532
                virReportOOMError();                                      \
1533 1534
                return -1;                                                \
            }                                                             \
1535 1536 1537 1538 1539 1540
        }                                                                 \
    }

    LOOKUP_PTYS(vm->def->serials,   vm->def->nserials,   "serial");
    LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel");
    LOOKUP_PTYS(vm->def->channels,  vm->def->nchannels,  "channel");
1541
#undef LOOKUP_PTYS
1542 1543 1544 1545

    return 0;
}

1546
static int
1547
qemudFindCharDevicePTYs(virDomainObjPtr vm,
1548 1549
                        const char *output,
                        int fd ATTRIBUTE_UNUSED)
1550
{
1551
    size_t offset = 0;
1552
    int ret, i;
1553 1554

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

1558
    /* first comes the serial devices */
1559 1560
    for (i = 0 ; i < vm->def->nserials ; i++) {
        virDomainChrDefPtr chr = vm->def->serials[i];
1561
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
1562
            if ((ret = qemudExtractTTYPath(output, &offset,
1563
                                           &chr->data.file.path)) != 0)
1564
                return ret;
1565 1566 1567
        }
    }

1568
    /* then the parallel devices */
1569 1570
    for (i = 0 ; i < vm->def->nparallels ; i++) {
        virDomainChrDefPtr chr = vm->def->parallels[i];
1571
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
1572
            if ((ret = qemudExtractTTYPath(output, &offset,
1573
                                           &chr->data.file.path)) != 0)
1574
                return ret;
1575 1576 1577
        }
    }

1578 1579 1580 1581
    /* then the channel devices */
    for (i = 0 ; i < vm->def->nchannels ; i++) {
        virDomainChrDefPtr chr = vm->def->channels[i];
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
1582
            if ((ret = qemudExtractTTYPath(output, &offset,
1583 1584 1585 1586 1587
                                           &chr->data.file.path)) != 0)
                return ret;
        }
    }

1588
    return 0;
1589 1590
}

1591 1592 1593 1594 1595
static void qemudFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED)
{
    VIR_FREE(payload);
}

1596
static int
1597
qemudWaitForMonitor(struct qemud_driver* driver,
1598
                    virDomainObjPtr vm, off_t pos)
1599
{
1600
    char buf[4096]; /* Plenty of space to get startup greeting */
1601
    int logfd;
1602
    int ret = -1;
1603

1604
    if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos))
1605
        < 0)
1606
        return -1;
1607

1608
    ret = qemudReadLogOutput(vm, logfd, buf, sizeof(buf),
1609
                             qemudFindCharDevicePTYs,
1610
                             "console", 30);
1611
    if (close(logfd) < 0) {
1612
        char ebuf[4096];
1613
        VIR_WARN(_("Unable to close logfile: %s"),
1614 1615
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1616

1617
    if (ret < 0)
1618
        return -1;
1619

1620
    VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
1621
    if (qemuConnectMonitor(driver, vm) < 0)
1622 1623
        return -1;

1624 1625 1626 1627 1628 1629
    /* Try to get the pty path mappings again via the monitor. This is much more
     * reliable if it's available.
     * Note that the monitor itself can be on a pty, so we still need to try the
     * log output method. */
    virHashTablePtr paths = virHashCreate(0);
    if (paths == NULL) {
1630
        virReportOOMError();
1631 1632 1633
        goto cleanup;
    }

1634
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
1635 1636
    qemuDomainObjPrivatePtr priv = vm->privateData;
    ret = qemuMonitorGetPtyPaths(priv->mon, paths);
1637
    qemuDomainObjExitMonitorWithDriver(driver, vm);
1638 1639 1640

    VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret);
    if (ret == 0) {
1641
        ret = qemudFindCharDevicePTYsMonitor(vm, paths);
1642 1643 1644 1645 1646 1647 1648 1649
    }

cleanup:
    if (paths) {
        virHashFree(paths, qemudFreePtyPath);
    }

    return ret;
1650 1651
}

1652
static int
1653
qemuDetectVcpuPIDs(struct qemud_driver *driver,
1654 1655 1656
                   virDomainObjPtr vm) {
    pid_t *cpupids = NULL;
    int ncpupids;
1657
    qemuDomainObjPrivatePtr priv = vm->privateData;
1658

1659
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
1660 1661
        priv->nvcpupids = 1;
        if (VIR_ALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) {
1662
            virReportOOMError();
1663 1664
            return -1;
        }
1665
        priv->vcpupids[0] = vm->pid;
1666 1667 1668
        return 0;
    }

1669
    /* What follows is now all KVM specific */
1670

1671
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
1672
    if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) < 0) {
1673
        qemuDomainObjExitMonitorWithDriver(driver, vm);
1674
        return -1;
1675
    }
1676
    qemuDomainObjExitMonitorWithDriver(driver, vm);
1677

1678 1679 1680
    /* Treat failure to get VCPU<->PID mapping as non-fatal */
    if (ncpupids == 0)
        return 0;
1681

1682
    if (ncpupids != vm->def->vcpus) {
1683 1684 1685
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("got wrong number of vCPU pids from QEMU monitor. got %d, wanted %d"),
                        ncpupids, (int)vm->def->vcpus);
1686 1687 1688
        VIR_FREE(cpupids);
        return -1;
    }
1689

1690 1691
    priv->nvcpupids = ncpupids;
    priv->vcpupids = cpupids;
1692 1693 1694
    return 0;
}

1695
static int
1696 1697
qemudInitCpuAffinity(virDomainObjPtr vm)
{
1698
    int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN;
1699
    virNodeInfo nodeinfo;
1700 1701
    unsigned char *cpumap;
    int cpumaplen;
1702
    qemuDomainObjPrivatePtr priv = vm->privateData;
1703

1704
    if (nodeGetInfo(NULL, &nodeinfo) < 0)
1705 1706 1707 1708
        return -1;

    /* setaffinity fails if you set bits for CPUs which
     * aren't present, so we have to limit ourselves */
1709 1710 1711
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
1712

1713 1714
    cpumaplen = VIR_CPU_MAPLEN(maxcpu);
    if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
1715
        virReportOOMError();
1716 1717 1718
        return -1;
    }

D
Daniel P. Berrange 已提交
1719
    if (vm->def->cpumask) {
1720 1721 1722
        /* XXX why don't we keep 'cpumask' in the libvirt cpumap
         * format to start with ?!?! */
        for (i = 0 ; i < maxcpu && i < vm->def->cpumasklen ; i++)
D
Daniel P. Berrange 已提交
1723
            if (vm->def->cpumask[i])
1724
                VIR_USE_CPU(cpumap, i);
D
Daniel P. Berrange 已提交
1725
    } else {
1726 1727 1728 1729
        /* You may think this is redundant, but we can't assume libvirtd
         * itself is running on all pCPUs, so we need to explicitly set
         * the spawned QEMU instance to all pCPUs if no map is given in
         * its config file */
D
Daniel P. Berrange 已提交
1730
        for (i = 0 ; i < maxcpu ; i++)
1731
            VIR_USE_CPU(cpumap, i);
D
Daniel P. Berrange 已提交
1732
    }
1733

1734 1735
    /* The XML config only gives a per-VM affinity, so we apply
     * the same mapping to all vCPUs */
1736 1737
    for (i = 0 ; i < priv->nvcpupids ; i++) {
        if (virProcessInfoSetAffinity(priv->vcpupids[i],
1738 1739
                                      cpumap, cpumaplen, maxcpu) < 0) {
            VIR_FREE(cpumap);
1740 1741 1742
            return -1;
        }
    }
1743
    VIR_FREE(cpumap);
1744 1745 1746 1747 1748

    return 0;
}


1749
static int
1750 1751 1752 1753
qemuInitPasswords(virConnectPtr conn,
                  struct qemud_driver *driver,
                  virDomainObjPtr vm,
                  unsigned long long qemuCmdFlags) {
1754
    int ret = 0;
1755
    qemuDomainObjPrivatePtr priv = vm->privateData;
1756

1757 1758 1759
    if ((vm->def->ngraphics == 1) &&
        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        (vm->def->graphics[0]->data.vnc.passwd || driver->vncPassword)) {
1760

1761
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
1762
        ret = qemuMonitorSetVNCPassword(priv->mon,
1763 1764 1765
                                        vm->def->graphics[0]->data.vnc.passwd ?
                                        vm->def->graphics[0]->data.vnc.passwd :
                                        driver->vncPassword);
1766
        qemuDomainObjExitMonitorWithDriver(driver, vm);
1767 1768
    }

1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791
    if (ret < 0)
        goto cleanup;

    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        int i;

        for (i = 0 ; i < vm->def->ndisks ; i++) {
            char *secret;
            size_t secretLen;

            if (!vm->def->disks[i]->encryption ||
                !vm->def->disks[i]->src)
                continue;

            if (getVolumeQcowPassphrase(conn,
                                        vm->def->disks[i],
                                        &secret, &secretLen) < 0)
                goto cleanup;

            qemuDomainObjEnterMonitorWithDriver(driver, vm);
            ret = qemuMonitorSetDrivePassphrase(priv->mon,
                                                vm->def->disks[i]->info.alias,
                                                secret);
1792
            VIR_FREE(secret);
1793 1794 1795 1796 1797 1798 1799
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            if (ret < 0)
                goto cleanup;
        }
    }

cleanup:
1800
    return ret;
1801 1802 1803
}


1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032
#define QEMU_PCI_VENDOR_INTEL     0x8086
#define QEMU_PCI_VENDOR_LSI_LOGIC 0x1000
#define QEMU_PCI_VENDOR_REDHAT    0x1af4
#define QEMU_PCI_VENDOR_CIRRUS    0x1013
#define QEMU_PCI_VENDOR_REALTEK   0x10ec
#define QEMU_PCI_VENDOR_AMD       0x1022
#define QEMU_PCI_VENDOR_ENSONIQ   0x1274
#define QEMU_PCI_VENDOR_VMWARE    0x15ad
#define QEMU_PCI_VENDOR_QEMU      0x1234

#define QEMU_PCI_PRODUCT_DISK_VIRTIO 0x1001

#define QEMU_PCI_PRODUCT_NIC_NE2K     0x8029
#define QEMU_PCI_PRODUCT_NIC_PCNET    0x2000
#define QEMU_PCI_PRODUCT_NIC_RTL8139  0x8139
#define QEMU_PCI_PRODUCT_NIC_E1000    0x100E
#define QEMU_PCI_PRODUCT_NIC_VIRTIO   0x1000

#define QEMU_PCI_PRODUCT_VGA_CIRRUS 0x00b8
#define QEMU_PCI_PRODUCT_VGA_VMWARE 0x0405
#define QEMU_PCI_PRODUCT_VGA_STDVGA 0x1111

#define QEMU_PCI_PRODUCT_AUDIO_AC97    0x2415
#define QEMU_PCI_PRODUCT_AUDIO_ES1370  0x5000

#define QEMU_PCI_PRODUCT_CONTROLLER_PIIX 0x7010
#define QEMU_PCI_PRODUCT_CONTROLLER_LSI  0x0012

#define QEMU_PCI_PRODUCT_WATCHDOG_I63000ESB 0x25ab

static int
qemuAssignNextPCIAddress(virDomainDeviceInfo *info,
                         int vendor,
                         int product,
                         qemuMonitorPCIAddress *addrs,
                         int naddrs)
{
    int found = 0;
    int i;

    VIR_DEBUG("Look for %x:%x out of %d", vendor, product, naddrs);

    for (i = 0 ; (i < naddrs) && !found; i++) {
        VIR_DEBUG("Maybe %x:%x", addrs[i].vendor, addrs[i].product);
        if (addrs[i].vendor == vendor &&
            addrs[i].product == product) {
            VIR_DEBUG("Match %d", i);
            found = 1;
            break;
        }
    }
    if (!found) {
        return -1;
    }

    /* Blank it out so this device isn't matched again */
    addrs[i].vendor = 0;
    addrs[i].product = 0;

    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
        info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;

    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
        info->addr.pci.domain = addrs[i].addr.domain;
        info->addr.pci.bus = addrs[i].addr.bus;
        info->addr.pci.slot = addrs[i].addr.slot;
        info->addr.pci.function = addrs[i].addr.function;
    }

    return 0;
}

static int
qemuGetPCIDiskVendorProduct(virDomainDiskDefPtr def,
                            unsigned *vendor,
                            unsigned *product)
{
    switch (def->bus) {
    case VIR_DOMAIN_DISK_BUS_VIRTIO:
        *vendor = QEMU_PCI_VENDOR_REDHAT;
        *product = QEMU_PCI_PRODUCT_DISK_VIRTIO;
        break;

    default:
        return -1;
    }

    return 0;
}

static int
qemuGetPCINetVendorProduct(virDomainNetDefPtr def,
                            unsigned *vendor,
                            unsigned *product)
{
    if (!def->model)
        return -1;

    if (STREQ(def->model, "ne2k_pci")) {
        *vendor = QEMU_PCI_VENDOR_REALTEK;
        *product = QEMU_PCI_PRODUCT_NIC_NE2K;
    } else if (STREQ(def->model, "pcnet")) {
        *vendor = QEMU_PCI_VENDOR_AMD;
        *product = QEMU_PCI_PRODUCT_NIC_PCNET;
    } else if (STREQ(def->model, "rtl8139")) {
        *vendor = QEMU_PCI_VENDOR_REALTEK;
        *product = QEMU_PCI_PRODUCT_NIC_RTL8139;
    } else if (STREQ(def->model, "e1000")) {
        *vendor = QEMU_PCI_VENDOR_INTEL;
        *product = QEMU_PCI_PRODUCT_NIC_E1000;
    } else if (STREQ(def->model, "virtio")) {
        *vendor = QEMU_PCI_VENDOR_REDHAT;
        *product = QEMU_PCI_PRODUCT_NIC_VIRTIO;
    } else {
        VIR_INFO("Unexpected NIC model %s, cannot get PCI address",
                 def->model);
        return -1;
    }
    return 0;
}

static int
qemuGetPCIControllerVendorProduct(virDomainControllerDefPtr def,
                                  unsigned *vendor,
                                  unsigned *product)
{
    switch (def->type) {
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
        *vendor = QEMU_PCI_VENDOR_LSI_LOGIC;
        *product = QEMU_PCI_PRODUCT_CONTROLLER_LSI;
        break;

    case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
        /* XXX we could put in the ISA bridge address, but
           that's not technically the FDC's address */
        return -1;

    case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
        *vendor = QEMU_PCI_VENDOR_INTEL;
        *product = QEMU_PCI_PRODUCT_CONTROLLER_PIIX;
        break;

    default:
        VIR_INFO("Unexpected controller type %s, cannot get PCI address",
                 virDomainControllerTypeToString(def->type));
        return -1;
    }

    return 0;
}

static int
qemuGetPCIVideoVendorProduct(virDomainVideoDefPtr def,
                             unsigned *vendor,
                             unsigned *product)
{
    switch (def->type) {
    case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
        *vendor = QEMU_PCI_VENDOR_CIRRUS;
        *product = QEMU_PCI_PRODUCT_VGA_CIRRUS;
        break;

    case VIR_DOMAIN_VIDEO_TYPE_VGA:
        *vendor = QEMU_PCI_VENDOR_QEMU;
        *product = QEMU_PCI_PRODUCT_VGA_STDVGA;
        break;

    case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
        *vendor = QEMU_PCI_VENDOR_VMWARE;
        *product = QEMU_PCI_PRODUCT_VGA_VMWARE;
        break;

    default:
        return -1;
    }
    return 0;
}

static int
qemuGetPCISoundVendorProduct(virDomainSoundDefPtr def,
                             unsigned *vendor,
                             unsigned *product)
{
    switch (def->model) {
    case VIR_DOMAIN_SOUND_MODEL_ES1370:
        *vendor = QEMU_PCI_VENDOR_ENSONIQ;
        *product = QEMU_PCI_PRODUCT_AUDIO_ES1370;
        break;

    case VIR_DOMAIN_SOUND_MODEL_AC97:
        *vendor = QEMU_PCI_VENDOR_INTEL;
        *product = QEMU_PCI_PRODUCT_AUDIO_AC97;
        break;

    default:
        return -1;
    }

    return 0;
}

static int
qemuGetPCIWatchdogVendorProduct(virDomainWatchdogDefPtr def,
                                unsigned *vendor,
                                unsigned *product)
{
    switch (def->model) {
    case VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB:
        *vendor = QEMU_PCI_VENDOR_INTEL;
        *product = QEMU_PCI_PRODUCT_WATCHDOG_I63000ESB;
        break;

    default:
        return -1;
    }

    return 0;
}


/*
 * This entire method assumes that PCI devices in 'info pci'
 * match ordering of devices specified on the command line
 * wrt to devices of matching vendor+product
 *
 * XXXX this might not be a valid assumption if we assign
 * some static addrs on CLI. Have to check that...
 */
static int
2033
qemuDetectPCIAddresses(virDomainObjPtr vm,
2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
                       qemuMonitorPCIAddress *addrs,
                       int naddrs)
{
    unsigned int vendor = 0, product = 0;
    int i;

    /* XXX should all these vendor/product IDs be kept in the
     * actual device data structure instead ?
     */

    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (qemuGetPCIDiskVendorProduct(vm->def->disks[i], &vendor, &product) < 0)
            continue;

        if (qemuAssignNextPCIAddress(&(vm->def->disks[i]->info),
                                     vendor, product,
                                     addrs, naddrs) < 0) {
2051 2052 2053
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for VirtIO disk %s"),
                            vm->def->disks[i]->dst);
2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
            return -1;
        }
    }

    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (qemuGetPCINetVendorProduct(vm->def->nets[i], &vendor, &product) < 0)
            continue;

        if (qemuAssignNextPCIAddress(&(vm->def->nets[i]->info),
                                     vendor, product,
                                     addrs,  naddrs) < 0) {
2065 2066 2067
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for %s NIC"),
                            vm->def->nets[i]->model);
2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078
            return -1;
        }
    }

    for (i = 0 ; i < vm->def->ncontrollers ; i++) {
        if (qemuGetPCIControllerVendorProduct(vm->def->controllers[i], &vendor, &product) < 0)
            continue;

        if (qemuAssignNextPCIAddress(&(vm->def->controllers[i]->info),
                                     vendor, product,
                                     addrs,  naddrs) < 0) {
2079 2080 2081
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for controller %s"),
                            virDomainControllerTypeToString(vm->def->controllers[i]->type));
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092
            return -1;
        }
    }

    for (i = 0 ; i < vm->def->nvideos ; i++) {
        if (qemuGetPCIVideoVendorProduct(vm->def->videos[i], &vendor, &product) < 0)
            continue;

        if (qemuAssignNextPCIAddress(&(vm->def->videos[i]->info),
                                     vendor, product,
                                     addrs,  naddrs) < 0) {
2093 2094 2095
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for video adapter %s"),
                            virDomainVideoTypeToString(vm->def->videos[i]->type));
2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
            return -1;
        }
    }

    for (i = 0 ; i < vm->def->nsounds ; i++) {
        if (qemuGetPCISoundVendorProduct(vm->def->sounds[i], &vendor, &product) < 0)
            continue;

        if (qemuAssignNextPCIAddress(&(vm->def->sounds[i]->info),
                                     vendor, product,
                                     addrs,  naddrs) < 0) {
2107 2108 2109
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for sound adapter %s"),
                            virDomainSoundModelTypeToString(vm->def->sounds[i]->model));
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119
            return -1;
        }
    }


    if (vm->def->watchdog &&
        qemuGetPCIWatchdogVendorProduct(vm->def->watchdog, &vendor, &product) == 0) {
        if (qemuAssignNextPCIAddress(&(vm->def->watchdog->info),
                                     vendor, product,
                                     addrs,  naddrs) < 0) {
2120 2121 2122
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for watchdog %s"),
                            virDomainWatchdogModelTypeToString(vm->def->watchdog->model));
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
            return -1;
        }
    }

    /* XXX console (virtio) */


    /* ... and now things we don't have in our xml */

    /* XXX USB controller ? */

    /* XXXX virtio balloon ? */

    /* XXX what about other PCI devices (ie bridges) */

    return 0;
}

static int
qemuInitPCIAddresses(struct qemud_driver *driver,
                     virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int naddrs;
    int ret;
    qemuMonitorPCIAddress *addrs = NULL;

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
    naddrs = qemuMonitorGetAllPCIAddresses(priv->mon,
                                           &addrs);
    qemuDomainObjExitMonitorWithDriver(driver, vm);

2155
    ret = qemuDetectPCIAddresses(vm, addrs, naddrs);
2156 2157 2158 2159 2160 2161

    VIR_FREE(addrs);

    return ret;
}

2162
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197
    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;
}

2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235

static int
qemuAssignPCIAddresses(virDomainDefPtr def)
{
    int ret = -1;
    unsigned long long qemuCmdFlags = 0;
    qemuDomainPCIAddressSetPtr addrs = NULL;
    struct stat sb;

    if (stat(def->emulator, &sb) < 0) {
        virReportSystemError(errno,
                             _("Cannot find QEMU binary %s"),
                             def->emulator);
        goto cleanup;
    }

    if (qemudExtractVersionInfo(def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0)
        goto cleanup;

    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (!(addrs = qemuDomainPCIAddressSetCreate(def)))
            goto cleanup;

        if (qemuAssignDevicePCISlots(def, addrs) < 0)
            goto cleanup;
    }

    ret = 0;

cleanup:
    qemuDomainPCIAddressSetFree(addrs);

    return ret;
}


2236
static pciDeviceList *
2237
qemuGetPciHostDeviceList(virDomainDefPtr def)
2238 2239
{
    pciDeviceList *list;
2240 2241
    int i;

2242
    if (!(list = pciDeviceListNew()))
2243
        return NULL;
2244 2245 2246 2247 2248 2249 2250 2251 2252 2253

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

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

2254
        dev = pciGetDevice(hostdev->source.subsys.u.pci.domain,
2255 2256 2257
                           hostdev->source.subsys.u.pci.bus,
                           hostdev->source.subsys.u.pci.slot,
                           hostdev->source.subsys.u.pci.function);
2258
        if (!dev) {
2259
            pciDeviceListFree(list);
2260 2261
            return NULL;
        }
2262

2263 2264 2265
        if (pciDeviceListAdd(list, dev) < 0) {
            pciFreeDevice(dev);
            pciDeviceListFree(list);
2266
            return NULL;
2267 2268
        }

2269
        pciDeviceSetManaged(dev, hostdev->managed);
2270 2271
    }

2272 2273 2274 2275
    return list;
}

static int
2276 2277 2278 2279
qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
                            virDomainDefPtr def)
{
    pciDeviceList *pcidevs;
2280
    int i;
2281
    int ret = -1;
2282 2283 2284 2285

    if (!def->nhostdevs)
        return 0;

2286
    if (!(pcidevs = qemuGetPciHostDeviceList(def)))
2287 2288
        return -1;

2289 2290
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2291 2292 2293
        pciDeviceListSteal(pcidevs, dev);
        if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
            pciFreeDevice(dev);
2294
            goto cleanup;
2295 2296 2297
        }
    }

2298 2299 2300
    ret = 0;

cleanup:
2301
    pciDeviceListFree(pcidevs);
2302 2303 2304
    return ret;
}

2305

2306
static int
2307 2308
qemuPrepareHostPCIDevices(struct qemud_driver *driver,
                          virDomainDefPtr def)
2309 2310 2311
{
    pciDeviceList *pcidevs;
    int i;
2312
    int ret = -1;
2313

2314
    if (!(pcidevs = qemuGetPciHostDeviceList(def)))
2315 2316
        return -1;

2317
    /* We have to use 3 loops here. *All* devices must
2318 2319
     * be detached before we reset any of them, because
     * in some cases you have to reset the whole PCI,
2320 2321
     * which impacts all devices on it. Also, all devices
     * must be reset before being marked as active.
2322 2323 2324 2325 2326 2327 2328
     */

    /* XXX validate that non-managed device isn't in use, eg
     * by checking that device is either un-bound, or bound
     * to pci-stub.ko
     */

2329 2330
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2331
        if (!pciDeviceIsAssignable(dev, !driver->relaxedACS))
2332 2333
            goto cleanup;

2334
        if (pciDeviceGetManaged(dev) &&
2335
            pciDettachDevice(dev) < 0)
2336 2337
            goto cleanup;
    }
2338 2339 2340

    /* Now that all the PCI hostdevs have be dettached, we can safely
     * reset them */
2341 2342
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2343
        if (pciResetDevice(dev, driver->activePciHostdevs) < 0)
2344 2345
            goto cleanup;
    }
2346

2347
    /* Now mark all the devices as active */
2348 2349
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2350 2351 2352
        pciDeviceListSteal(pcidevs, dev);
        if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
            pciFreeDevice(dev);
2353 2354
            goto cleanup;
        }
2355 2356
    }

2357
    ret = 0;
2358

2359
cleanup:
2360
    pciDeviceListFree(pcidevs);
2361
    return ret;
2362 2363
}

2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374

static int
qemuPrepareHostUSBDevices(struct qemud_driver *driver ATTRIBUTE_UNUSED,
                          virDomainDefPtr def)
{
    int i;
    for (i = 0 ; i < def->nhostdevs ; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
2375
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413
            continue;

        /* Resolve a vendor/product to bus/device */
        if (hostdev->source.subsys.u.usb.vendor) {
            usbDevice *usb
                = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
                                hostdev->source.subsys.u.usb.product);

            if (!usb)
                return -1;

            hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
            hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);

            usbFreeDevice(usb);
        }
    }

    return 0;
}

static int
qemuPrepareHostDevices(struct qemud_driver *driver,
                       virDomainDefPtr def)
{
    if (!def->nhostdevs)
        return 0;

    if (qemuPrepareHostPCIDevices(driver, def) < 0)
        return -1;

    if (qemuPrepareHostUSBDevices(driver, def) < 0)
        return -1;

    return 0;
}


2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424
static void
qemudReattachManagedDevice(pciDevice *dev)
{
    int retries = 100;

    if (pciDeviceGetManaged(dev)) {
        while (pciWaitForDeviceCleanup(dev, "kvm_assigned_device")
               && retries) {
            usleep(100*1000);
            retries--;
        }
2425
        if (pciReAttachDevice(dev) < 0) {
2426 2427 2428 2429 2430 2431 2432 2433
            virErrorPtr err = virGetLastError();
            VIR_ERROR(_("Failed to re-attach PCI device: %s"),
                      err ? err->message : "");
            virResetError(err);
        }
    }
}

2434
static void
2435
qemuDomainReAttachHostDevices(struct qemud_driver *driver,
2436
                              virDomainDefPtr def)
2437
{
2438
    pciDeviceList *pcidevs;
2439 2440
    int i;

2441 2442
    if (!def->nhostdevs)
        return;
2443

2444
    if (!(pcidevs = qemuGetPciHostDeviceList(def))) {
2445
        virErrorPtr err = virGetLastError();
2446
        VIR_ERROR(_("Failed to allocate pciDeviceList: %s"),
2447 2448 2449
                  err ? err->message : "");
        virResetError(err);
        return;
2450 2451
    }

2452 2453
    /* Again 3 loops; mark all devices as inactive before reset
     * them and reset all the devices before re-attach */
2454

2455 2456
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2457
        pciDeviceListDel(driver->activePciHostdevs, dev);
2458
    }
2459

2460 2461
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2462
        if (pciResetDevice(dev, driver->activePciHostdevs) < 0) {
2463
            virErrorPtr err = virGetLastError();
2464
            VIR_ERROR(_("Failed to reset PCI device: %s"),
2465 2466 2467
                      err ? err->message : "");
            virResetError(err);
        }
2468
    }
2469

2470 2471
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2472
        qemudReattachManagedDevice(dev);
2473
    }
2474

2475
    pciDeviceListFree(pcidevs);
2476 2477
}

2478 2479 2480 2481 2482 2483 2484 2485 2486 2487
static const char *const defaultDeviceACL[] = {
    "/dev/null", "/dev/full", "/dev/zero",
    "/dev/random", "/dev/urandom",
    "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
    "/dev/rtc", "/dev/hpet", "/dev/net/tun",
    NULL,
};
#define DEVICE_PTY_MAJOR 136
#define DEVICE_SND_MAJOR 116

2488
static int qemuSetupCgroup(struct qemud_driver *driver,
2489 2490 2491 2492
                           virDomainObjPtr vm)
{
    virCgroupPtr cgroup = NULL;
    int rc;
2493
    unsigned int i;
2494 2495 2496 2497
    const char *const *deviceACL =
        driver->cgroupDeviceACL ?
        (const char *const *)driver->cgroupDeviceACL :
        defaultDeviceACL;
2498 2499 2500 2501 2502 2503

    if (driver->cgroup == NULL)
        return 0; /* Not supported, so claim success */

    rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 1);
    if (rc != 0) {
2504
        virReportSystemError(-rc,
2505 2506 2507 2508 2509
                             _("Unable to create cgroup for %s"),
                             vm->def->name);
        goto cleanup;
    }

2510 2511
    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
        rc = virCgroupDenyAllDevices(cgroup);
2512
        if (rc != 0) {
2513 2514 2515 2516 2517
            if (rc == -EPERM) {
                VIR_WARN0("Group devices ACL is not accessible, disabling whitelisting");
                goto done;
            }

2518
            virReportSystemError(-rc,
2519
                                 _("Unable to deny all devices for %s"), vm->def->name);
2520 2521 2522
            goto cleanup;
        }

2523 2524 2525 2526 2527 2528 2529 2530
        for (i = 0; i < vm->def->ndisks ; i++) {
            if (vm->def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK ||
                vm->def->disks[i]->src == NULL)
                continue;

            rc = virCgroupAllowDevicePath(cgroup,
                                          vm->def->disks[i]->src);
            if (rc != 0) {
2531
                virReportSystemError(-rc,
2532 2533 2534 2535 2536
                                     _("Unable to allow device %s for %s"),
                                     vm->def->disks[i]->src, vm->def->name);
                goto cleanup;
            }
        }
2537

2538
        rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR);
2539
        if (rc != 0) {
2540
            virReportSystemError(-rc, "%s",
2541
                                 _("unable to allow /dev/pts/ devices"));
2542 2543 2544
            goto cleanup;
        }

2545 2546 2547
        if (vm->def->nsounds) {
            rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_SND_MAJOR);
            if (rc != 0) {
2548
                virReportSystemError(-rc, "%s",
2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
                                     _("unable to allow /dev/snd/ devices"));
                goto cleanup;
            }
        }

        for (i = 0; deviceACL[i] != NULL ; i++) {
            rc = virCgroupAllowDevicePath(cgroup,
                                          deviceACL[i]);
            if (rc < 0 &&
                rc != -ENOENT) {
2559
                virReportSystemError(-rc,
2560 2561 2562 2563
                                     _("unable to allow device %s"),
                                     deviceACL[i]);
                goto cleanup;
            }
2564 2565 2566 2567
        }
    }

done:
2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579
    virCgroupFree(&cgroup);
    return 0;

cleanup:
    if (cgroup) {
        virCgroupRemove(cgroup);
        virCgroupFree(&cgroup);
    }
    return -1;
}


2580
static int qemuRemoveCgroup(struct qemud_driver *driver,
2581 2582
                            virDomainObjPtr vm,
                            int quiet)
2583 2584 2585 2586 2587 2588 2589 2590 2591
{
    virCgroupPtr cgroup;
    int rc;

    if (driver->cgroup == NULL)
        return 0; /* Not supported, so claim success */

    rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0);
    if (rc != 0) {
2592
        if (!quiet)
2593 2594 2595
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Unable to find cgroup for %s\n"),
                            vm->def->name);
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615
        return rc;
    }

    rc = virCgroupRemove(cgroup);
    virCgroupFree(&cgroup);
    return rc;
}

static int qemuAddToCgroup(struct qemud_driver *driver,
                           virDomainDefPtr def)
{
    virCgroupPtr cgroup = NULL;
    int ret = -1;
    int rc;

    if (driver->cgroup == NULL)
        return 0; /* Not supported, so claim success */

    rc = virCgroupForDomain(driver->cgroup, def->name, &cgroup, 0);
    if (rc != 0) {
2616
        virReportSystemError(-rc,
2617 2618 2619 2620 2621 2622 2623
                             _("unable to find cgroup for domain %s"),
                             def->name);
        goto cleanup;
    }

    rc = virCgroupAddTask(cgroup, getpid());
    if (rc != 0) {
2624
        virReportSystemError(-rc,
2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641
                             _("unable to add domain %s task %d to cgroup"),
                             def->name, getpid());
        goto cleanup;
    }

    ret = 0;

cleanup:
    virCgroupFree(&cgroup);
    return ret;
}


struct qemudHookData {
    virConnectPtr conn;
    virDomainObjPtr vm;
    struct qemud_driver *driver;
2642 2643 2644
};

static int qemudSecurityHook(void *data) {
2645 2646 2647 2648
    struct qemudHookData *h = data;

    if (qemuAddToCgroup(h->driver, h->vm->def) < 0)
        return -1;
2649

2650 2651
    if (h->driver->securityDriver &&
        h->driver->securityDriver->domainSetSecurityProcessLabel &&
2652
        h->driver->securityDriver->domainSetSecurityProcessLabel(h->driver->securityDriver, h->vm) < 0)
2653 2654 2655
        return -1;

    return 0;
2656 2657
}

2658
static int
2659
qemuPrepareMonitorChr(struct qemud_driver *driver,
2660
                      virDomainChrDefPtr monConfig,
2661 2662
                      const char *vm)
{
2663
    monConfig->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_MONITOR;
2664

2665 2666
    monConfig->type = VIR_DOMAIN_CHR_TYPE_UNIX;
    monConfig->data.nix.listen = 1;
2667

D
Daniel P. Berrange 已提交
2668
    if (!(monConfig->info.alias = strdup("monitor"))) {
2669
        virReportOOMError();
D
Daniel P. Berrange 已提交
2670 2671 2672
        return -1;
    }

2673
    if (virAsprintf(&monConfig->data.nix.path, "%s/%s.monitor",
2674
                    driver->libDir, vm) < 0) {
2675
        virReportOOMError();
2676 2677 2678 2679 2680 2681
        return -1;
    }

    return 0;
}

2682 2683
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
2684
                              virDomainObjPtr vm,
2685 2686
                              const char *migrateFrom,
                              int stdin_fd) {
2687
    const char **argv = NULL, **tmp;
2688
    const char **progenv = NULL;
2689
    int i, ret;
2690
    struct stat sb;
2691 2692
    int *tapfds = NULL;
    int ntapfds = 0;
2693
    unsigned long long qemuCmdFlags;
2694
    fd_set keepfd;
2695
    const char *emulator;
G
Guido Günther 已提交
2696
    pid_t child;
2697
    int pos = -1;
2698
    char ebuf[1024];
2699
    char *pidfile = NULL;
2700
    int logfile;
2701
    qemuDomainObjPrivatePtr priv = vm->privateData;
2702

2703
    struct qemudHookData hookData;
2704 2705 2706 2707
    hookData.conn = conn;
    hookData.vm = vm;
    hookData.driver = driver;

2708
    FD_ZERO(&keepfd);
2709

2710 2711
    DEBUG0("Beginning VM startup process");

D
Daniel P. Berrange 已提交
2712
    if (virDomainObjIsActive(vm)) {
2713 2714
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("VM is already active"));
2715 2716 2717
        return -1;
    }

2718 2719 2720 2721 2722
    /* Must be run before security labelling */
    DEBUG0("Preparing host devices");
    if (qemuPrepareHostDevices(driver, vm->def) < 0)
        goto cleanup;

2723 2724
    /* If you are using a SecurityDriver with dynamic labelling,
       then generate a security label for isolation */
2725
    DEBUG0("Generating domain security label (if required)");
2726
    if (driver->securityDriver &&
2727
        driver->securityDriver->domainGenSecurityLabel &&
2728
        driver->securityDriver->domainGenSecurityLabel(vm) < 0)
2729 2730
        return -1;

2731
    DEBUG0("Generating setting domain security labels (if required)");
2732 2733
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityAllLabel &&
2734
        driver->securityDriver->domainSetSecurityAllLabel(vm) < 0)
2735 2736
        goto cleanup;

2737 2738 2739
    /* Ensure no historical cgroup for this VM is lying around bogus
     * settings */
    DEBUG0("Ensuring no historical cgroup is lying around");
2740
    qemuRemoveCgroup(driver, vm, 1);
2741

2742 2743 2744
    if ((vm->def->ngraphics == 1) &&
        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics[0]->data.vnc.autoport) {
2745
        DEBUG0("Determining VNC port");
2746
        int port = qemudNextFreeVNCPort(driver);
2747
        if (port < 0) {
2748 2749
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("Unable to find an unused VNC port"));
2750
            goto cleanup;
2751
        }
2752
        vm->def->graphics[0]->data.vnc.port = port;
2753
    }
2754

L
Laine Stump 已提交
2755
    if (virFileMakePath(driver->logDir) != 0) {
2756
        virReportSystemError(errno,
2757 2758
                             _("cannot create log directory %s"),
                             driver->logDir);
2759
        goto cleanup;
2760 2761
    }

2762
    DEBUG0("Creating domain log file");
2763
    if ((logfile = qemudLogFD(driver, vm->def->name)) < 0)
2764
        goto cleanup;
2765

2766 2767
    emulator = vm->def->emulator;

2768 2769 2770 2771
    /* 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
     */
2772
    if (stat(emulator, &sb) < 0) {
2773
        virReportSystemError(errno,
2774 2775
                             _("Cannot find QEMU binary %s"),
                             emulator);
2776
        goto cleanup;
2777 2778
    }

2779
    DEBUG0("Determing emulator version");
2780
    if (qemudExtractVersionInfo(emulator,
2781
                                NULL,
2782
                                &qemuCmdFlags) < 0)
2783
        goto cleanup;
2784

2785
    DEBUG0("Setting up domain cgroup (if required)");
2786
    if (qemuSetupCgroup(driver, vm) < 0)
2787 2788
        goto cleanup;

2789
    if (VIR_ALLOC(priv->monConfig) < 0) {
2790
        virReportOOMError();
2791 2792 2793
        goto cleanup;
    }

2794
    DEBUG0("Preparing monitor state");
2795
    if (qemuPrepareMonitorChr(driver, priv->monConfig, vm->def->name) < 0)
2796
        goto cleanup;
2797

D
Daniel P. Berrange 已提交
2798 2799 2800
#if HAVE_YAJL
    if (qemuCmdFlags & QEMUD_CMD_FLAG_MONITOR_JSON)
        priv->monJSON = 1;
2801
    else
D
Daniel P. Berrange 已提交
2802
#endif
2803
        priv->monJSON = 0;
D
Daniel P. Berrange 已提交
2804

D
Daniel P. Berrange 已提交
2805
    if ((ret = virFileDeletePid(driver->stateDir, vm->def->name)) != 0) {
2806
        virReportSystemError(ret,
D
Daniel P. Berrange 已提交
2807 2808 2809 2810 2811
                             _("Cannot remove stale PID file for %s"),
                             vm->def->name);
        goto cleanup;
    }

2812
    if (!(pidfile = virFilePid(driver->stateDir, vm->def->name))) {
2813
        virReportSystemError(errno,
2814 2815 2816
                             "%s", _("Failed to build pidfile path."));
        goto cleanup;
    }
D
Daniel P. Berrange 已提交
2817

2818
    /*
M
Matthew Booth 已提交
2819
     * Normally PCI addresses are assigned in the virDomainCreate
2820 2821 2822 2823 2824
     * or virDomainDefine methods. We might still need to assign
     * some here to cope with the question of upgrades. Regardless
     * we also need to populate the PCi address set cache for later
     * use in hotplug
     */
2825
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
2826
        DEBUG0("Assigning domain PCI addresses");
2827
        /* Populate cache with current addresses */
2828 2829 2830 2831 2832 2833 2834
        if (priv->pciaddrs) {
            qemuDomainPCIAddressSetFree(priv->pciaddrs);
            priv->pciaddrs = NULL;
        }
        if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(vm->def)))
            goto cleanup;

2835 2836

        /* Assign any remaining addresses */
2837 2838
        if (qemuAssignDevicePCISlots(vm->def, priv->pciaddrs) < 0)
            goto cleanup;
2839 2840 2841 2842

        priv->persistentAddrs = 1;
    } else {
        priv->persistentAddrs = 0;
2843 2844
    }

2845
    DEBUG0("Building emulator command line");
2846
    vm->def->id = driver->nextvmid++;
2847
    if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
D
Daniel P. Berrange 已提交
2848
                              priv->monJSON, qemuCmdFlags, &argv, &progenv,
2849 2850
                              &tapfds, &ntapfds, migrateFrom) < 0)
        goto cleanup;
2851

2852 2853
    tmp = progenv;
    while (*tmp) {
2854
        if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
2855
            VIR_WARN(_("Unable to write envv to logfile: %s"),
2856
                     virStrerror(errno, ebuf, sizeof ebuf));
2857
        if (safewrite(logfile, " ", 1) < 0)
2858
            VIR_WARN(_("Unable to write envv to logfile: %s"),
2859
                     virStrerror(errno, ebuf, sizeof ebuf));
2860 2861
        tmp++;
    }
2862 2863
    tmp = argv;
    while (*tmp) {
2864
        if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
2865
            VIR_WARN(_("Unable to write argv to logfile: %s"),
2866
                     virStrerror(errno, ebuf, sizeof ebuf));
2867
        if (safewrite(logfile, " ", 1) < 0)
2868
            VIR_WARN(_("Unable to write argv to logfile: %s"),
2869
                     virStrerror(errno, ebuf, sizeof ebuf));
2870 2871
        tmp++;
    }
2872
    if (safewrite(logfile, "\n", 1) < 0)
2873
        VIR_WARN(_("Unable to write argv to logfile: %s"),
2874
                 virStrerror(errno, ebuf, sizeof ebuf));
2875

2876
    if ((pos = lseek(logfile, 0, SEEK_END)) < 0)
2877
        VIR_WARN(_("Unable to seek to end of logfile: %s"),
2878
                 virStrerror(errno, ebuf, sizeof ebuf));
2879

2880 2881 2882
    for (i = 0 ; i < ntapfds ; i++)
        FD_SET(tapfds[i], &keepfd);

2883
    ret = virExecDaemonize(argv, progenv, &keepfd, &child,
2884
                           stdin_fd, &logfile, &logfile,
2885
                           VIR_EXEC_NONBLOCK | VIR_EXEC_CLEAR_CAPS,
2886 2887 2888
                           qemudSecurityHook, &hookData,
                           pidfile);
    VIR_FREE(pidfile);
G
Guido Günther 已提交
2889 2890 2891

    /* wait for qemu process to to show up */
    if (ret == 0) {
2892
        if (virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) {
2893 2894
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Domain %s didn't show up\n"), vm->def->name);
2895
            ret = -1;
G
Guido Günther 已提交
2896
        }
2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907
    } else if (ret == -2) {
        /* The virExec process that launches the daemon failed. Pending on
         * when it failed (we can't determine for sure), there may be
         * extra info in the domain log (if the hook failed for example).
         *
         * Pretend like things succeeded, and let 'WaitForMonitor' report
         * the log contents for us.
         */
        vm->pid = child;
        ret = 0;
    }
2908 2909

    vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
2910

2911
    for (i = 0 ; argv[i] ; i++)
2912 2913
        VIR_FREE(argv[i]);
    VIR_FREE(argv);
2914

2915 2916 2917 2918
    for (i = 0 ; progenv[i] ; i++)
        VIR_FREE(progenv[i]);
    VIR_FREE(progenv);

2919 2920 2921
    if (tapfds) {
        for (i = 0 ; i < ntapfds ; i++) {
            close(tapfds[i]);
2922
        }
2923
        VIR_FREE(tapfds);
2924 2925
    }

2926
    if (ret == -1) /* The VM failed to start */
2927 2928
        goto cleanup;

2929
    DEBUG0("Waiting for monitor to show up");
2930
    if (qemudWaitForMonitor(driver, vm, pos) < 0)
2931 2932
        goto abort;

2933
    DEBUG0("Detecting VCPU PIDs");
2934
    if (qemuDetectVcpuPIDs(driver, vm) < 0)
2935 2936
        goto abort;

2937
    DEBUG0("Setting CPU affinity");
2938
    if (qemudInitCpuAffinity(vm) < 0)
2939 2940
        goto abort;

2941
    DEBUG0("Setting any required VM passwords");
2942
    if (qemuInitPasswords(conn, driver, vm, qemuCmdFlags) < 0)
2943 2944
        goto abort;

D
Daniel P. Berrange 已提交
2945 2946 2947
    /* If we have -device, then addresses are assigned explicitly.
     * If not, then we have to detect dynamic ones here */
    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
2948
        DEBUG0("Determining domain device PCI addresses");
D
Daniel P. Berrange 已提交
2949 2950 2951
        if (qemuInitPCIAddresses(driver, vm) < 0)
            goto abort;
    }
2952

2953
    DEBUG0("Setting initial memory amount");
2954
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
2955
    if (qemuMonitorSetBalloon(priv->mon, vm->def->memory) < 0) {
2956
        qemuDomainObjExitMonitorWithDriver(driver, vm);
2957
        goto abort;
2958
    }
2959 2960

    if (migrateFrom == NULL) {
2961
        DEBUG0("Starting domain CPUs");
2962 2963 2964
        /* Allow the CPUS to start executing */
        if (qemuMonitorStartCPUs(priv->mon, conn) < 0) {
            if (virGetLastError() == NULL)
2965 2966
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("resume operation failed"));
2967 2968 2969 2970
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            goto abort;
        }
    }
2971
    qemuDomainObjExitMonitorWithDriver(driver, vm);
2972

2973

2974
    DEBUG0("Writing domain status to disk");
2975
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
2976
        goto abort;
2977

2978 2979 2980
    if (logfile != -1)
        close(logfile);

2981
    return 0;
2982 2983

cleanup:
2984 2985 2986
    /* We jump here if we failed to start the VM for any reason
     * XXX investigate if we can kill this block and safely call
     * qemudShutdownVMDaemon even though no PID is running */
2987
    qemuDomainReAttachHostDevices(driver, vm->def);
2988

2989 2990
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityAllLabel)
2991
        driver->securityDriver->domainRestoreSecurityAllLabel(vm);
2992 2993
    if (driver->securityDriver &&
        driver->securityDriver->domainReleaseSecurityLabel)
2994
        driver->securityDriver->domainReleaseSecurityLabel(vm);
2995
    qemuRemoveCgroup(driver, vm, 1);
2996 2997 2998 2999
    if ((vm->def->ngraphics == 1) &&
        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics[0]->data.vnc.autoport)
        vm->def->graphics[0]->data.vnc.port = -1;
3000 3001
    if (logfile != -1)
        close(logfile);
3002 3003
    vm->def->id = -1;
    return -1;
3004 3005 3006 3007

abort:
    /* We jump here if we failed to initialize the now running VM
     * killing it off and pretend we never started it */
3008
    qemudShutdownVMDaemon(driver, vm);
3009 3010 3011 3012 3013

    if (logfile != -1)
        close(logfile);

    return -1;
3014 3015 3016
}


3017
static void qemudShutdownVMDaemon(struct qemud_driver *driver,
3018
                                  virDomainObjPtr vm) {
D
Daniel P. Berrange 已提交
3019
    int ret;
3020
    int retries = 0;
3021
    qemuDomainObjPrivatePtr priv = vm->privateData;
3022
    virErrorPtr orig_err;
3023 3024
    virDomainDefPtr def;
    int i;
D
Daniel P. Berrange 已提交
3025

D
Daniel P. Berrange 已提交
3026
    if (!virDomainObjIsActive(vm))
3027
        return;
3028

3029
    VIR_DEBUG("Shutting down VM '%s'", vm->def->name);
3030

3031 3032 3033 3034
    /* This method is routinely used in clean up paths. Disable error
     * reporting so we don't squash a legit error. */
    orig_err = virSaveLastError();

3035
    if (driver->macFilter) {
3036
        def = vm->def;
3037 3038 3039 3040
        for (i = 0 ; i < def->nnets ; i++) {
            virDomainNetDefPtr net = def->nets[i];
            if (net->ifname == NULL)
                continue;
3041
            if ((errno = networkDisallowMacOnPort(driver, net->ifname,
3042
                                                  net->mac))) {
3043
                virReportSystemError(errno,
3044 3045 3046 3047 3048 3049
             _("failed to remove ebtables rule to allow MAC address on  '%s'"),
                                     net->ifname);
            }
        }
    }

G
Guido Günther 已提交
3050 3051
    if (virKillProcess(vm->pid, 0) == 0 &&
        virKillProcess(vm->pid, SIGTERM) < 0)
3052
        virReportSystemError(errno,
3053 3054
                             _("Failed to send SIGTERM to %s (%d)"),
                             vm->def->name, vm->pid);
3055

3056 3057 3058
    if (priv->mon &&
        qemuMonitorClose(priv->mon) == 0) {
        virDomainObjUnref(vm);
3059
        priv->mon = NULL;
3060
    }
3061

3062 3063 3064 3065 3066
    if (priv->monConfig) {
        if (priv->monConfig->type == VIR_DOMAIN_CHR_TYPE_UNIX)
            unlink(priv->monConfig->data.nix.path);
        virDomainChrDefFree(priv->monConfig);
        priv->monConfig = NULL;
3067 3068
    }

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

3072
    /* Reset Security Labels */
3073
    if (driver->securityDriver &&
3074
        driver->securityDriver->domainRestoreSecurityAllLabel)
3075
        driver->securityDriver->domainRestoreSecurityAllLabel(vm);
3076 3077
    if (driver->securityDriver &&
        driver->securityDriver->domainReleaseSecurityLabel)
3078
        driver->securityDriver->domainReleaseSecurityLabel(vm);
3079

3080 3081 3082 3083 3084 3085 3086
    /* Clear out dynamically assigned labels */
    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
        VIR_FREE(vm->def->seclabel.model);
        VIR_FREE(vm->def->seclabel.label);
        VIR_FREE(vm->def->seclabel.imagelabel);
    }

D
Daniel P. Berrange 已提交
3087
    virDomainDefClearDeviceAliases(vm->def);
3088 3089 3090 3091 3092
    if (!priv->persistentAddrs) {
        virDomainDefClearPCIAddresses(vm->def);
        qemuDomainPCIAddressSetFree(priv->pciaddrs);
        priv->pciaddrs = NULL;
    }
3093

3094
    qemuDomainReAttachHostDevices(driver, vm->def);
3095

S
Stefan Berger 已提交
3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106
#if WITH_MACVTAP
    def = vm->def;
    for (i = 0; i < def->nnets; i++) {
        virDomainNetDefPtr net = def->nets[i];
        if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
            if (net->ifname)
                delMacvtap(net->ifname);
        }
    }
#endif

3107
retry:
3108
    if ((ret = qemuRemoveCgroup(driver, vm, 0)) < 0) {
3109 3110 3111 3112 3113 3114 3115 3116
        if (ret == -EBUSY && (retries++ < 5)) {
            usleep(200*1000);
            goto retry;
        }
        VIR_WARN("Failed to remove cgroup for %s",
                 vm->def->name);
    }

3117
    qemudRemoveDomainStatus(driver, vm);
D
Daniel P. Berrange 已提交
3118

3119
    vm->pid = -1;
3120
    vm->def->id = -1;
3121
    vm->state = VIR_DOMAIN_SHUTOFF;
3122 3123
    VIR_FREE(priv->vcpupids);
    priv->nvcpupids = 0;
3124 3125

    if (vm->newDef) {
3126
        virDomainDefFree(vm->def);
3127
        vm->def = vm->newDef;
3128
        vm->def->id = -1;
3129 3130
        vm->newDef = NULL;
    }
3131 3132 3133 3134 3135

    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
3136 3137 3138
}


3139
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
3140
                                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
3141
                                  int flags ATTRIBUTE_UNUSED) {
3142
    if (conn->uri == NULL) {
3143 3144 3145
        if (qemu_driver == NULL)
            return VIR_DRV_OPEN_DECLINED;

3146
        conn->uri = xmlParseURI(qemu_driver->privileged ?
3147 3148
                                "qemu:///system" :
                                "qemu:///session");
3149
        if (!conn->uri) {
3150
            virReportOOMError();
3151 3152
            return VIR_DRV_OPEN_ERROR;
        }
3153 3154 3155 3156 3157 3158 3159 3160 3161 3162
    } else {
        /* If URI isn't 'qemu' its definitely not for us */
        if (conn->uri->scheme == NULL ||
            STRNEQ(conn->uri->scheme, "qemu"))
            return VIR_DRV_OPEN_DECLINED;

        /* Allow remote driver to deal with URIs with hostname server */
        if (conn->uri->server != NULL)
            return VIR_DRV_OPEN_DECLINED;

3163
        if (qemu_driver == NULL) {
3164 3165
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("qemu state driver is not active"));
3166 3167 3168
            return VIR_DRV_OPEN_ERROR;
        }

3169
        if (conn->uri->path == NULL) {
3170 3171 3172 3173 3174
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("no QEMU URI path given, try %s"),
                            qemu_driver->privileged
                            ? "qemu:///system"
                            : "qemu:///session");
3175 3176 3177
                return VIR_DRV_OPEN_ERROR;
        }

3178
        if (qemu_driver->privileged) {
3179 3180
            if (STRNEQ (conn->uri->path, "/system") &&
                STRNEQ (conn->uri->path, "/session")) {
3181 3182 3183
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unexpected QEMU URI path '%s', try qemu:///system"),
                                conn->uri->path);
3184 3185 3186 3187
                return VIR_DRV_OPEN_ERROR;
            }
        } else {
            if (STRNEQ (conn->uri->path, "/session")) {
3188 3189 3190
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unexpected QEMU URI path '%s', try qemu:///session"),
                                conn->uri->path);
3191 3192 3193
                return VIR_DRV_OPEN_ERROR;
            }
        }
3194 3195 3196 3197 3198 3199 3200
    }
    conn->privateData = qemu_driver;

    return VIR_DRV_OPEN_SUCCESS;
}

static int qemudClose(virConnectPtr conn) {
3201
    struct qemud_driver *driver = conn->privateData;
3202 3203

    /* Get rid of callbacks registered for this conn */
3204
    qemuDriverLock(driver);
3205
    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
3206
    qemuDriverUnlock(driver);
3207 3208 3209 3210 3211 3212

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
3213 3214 3215 3216 3217
/* Which features are supported by this driver? */
static int
qemudSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
{
    switch (feature) {
3218 3219 3220 3221 3222
    case VIR_DRV_FEATURE_MIGRATION_V2:
    case VIR_DRV_FEATURE_MIGRATION_P2P:
        return 1;
    default:
        return 0;
D
Daniel Veillard 已提交
3223 3224 3225
    }
}

3226
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
3227
    return "QEMU";
3228 3229
}

3230

3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243
static int qemuIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* Trivially secure, since always inside the daemon */
    return 1;
}

static int qemuIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* Not encrypted, but remote driver takes care of that */
    return 0;
}


3244 3245 3246 3247
static int kvmGetMaxVCPUs(void) {
    int maxvcpus = 1;

    int r, fd;
3248

3249 3250
    fd = open(KVM_DEVICE, O_RDONLY);
    if (fd < 0) {
3251
        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
3252
        return -1;
3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263
    }

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

    close(fd);
    return maxvcpus;
}


3264
static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type) {
3265 3266 3267
    if (!type)
        return 16;

3268
    if (STRCASEEQ(type, "qemu"))
3269 3270
        return 16;

3271
    if (STRCASEEQ(type, "kvm"))
3272
        return kvmGetMaxVCPUs();
3273

3274
    if (STRCASEEQ(type, "kqemu"))
3275
        return 1;
3276

3277 3278
    qemuReportError(VIR_ERR_INVALID_ARG,
                    _("unknown type '%s'"), type);
3279 3280 3281
    return -1;
}

3282

3283
static char *qemudGetCapabilities(virConnectPtr conn) {
3284
    struct qemud_driver *driver = conn->privateData;
3285
    virCapsPtr caps = NULL;
3286
    char *xml = NULL;
3287

3288
    qemuDriverLock(driver);
3289

3290
    if ((caps = qemuCreateCapabilities(qemu_driver->caps,
3291
                                       qemu_driver)) == NULL) {
3292 3293 3294
        virCapabilitiesFree(caps);
        goto cleanup;
    }
3295

3296
    virCapabilitiesFree(qemu_driver->caps);
3297 3298 3299
    qemu_driver->caps = caps;

    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
3300
        virReportOOMError();
3301 3302

cleanup:
3303
    qemuDriverUnlock(driver);
3304

3305
    return xml;
3306 3307 3308
}


3309
static int qemudGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, int pid, int tid) {
D
Daniel P. Berrange 已提交
3310 3311
    char proc[PATH_MAX];
    FILE *pidinfo;
3312
    unsigned long long usertime, systime;
3313 3314
    int cpu;
    int ret;
D
Daniel P. Berrange 已提交
3315

3316 3317 3318 3319 3320 3321
    if (tid)
        ret = snprintf(proc, sizeof(proc), "/proc/%d/task/%d/stat", pid, tid);
    else
        ret = snprintf(proc, sizeof(proc), "/proc/%d/stat", pid);
    if (ret >= (int)sizeof(proc)) {
        errno = E2BIG;
D
Daniel P. Berrange 已提交
3322 3323 3324 3325
        return -1;
    }

    if (!(pidinfo = fopen(proc, "r"))) {
3326
        /*printf("cannot read pid info");*/
D
Daniel P. Berrange 已提交
3327
        /* VM probably shut down, so fake 0 */
3328 3329 3330 3331
        if (cpuTime)
            *cpuTime = 0;
        if (lastCpu)
            *lastCpu = 0;
D
Daniel P. Berrange 已提交
3332 3333 3334
        return 0;
    }

3335 3336 3337 3338 3339 3340 3341 3342 3343 3344
    /* See 'man proc' for information about what all these fields are. We're
     * only interested in a very few of them */
    if (fscanf(pidinfo,
               /* pid -> stime */
               "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu"
               /* cutime -> endcode */
               "%*d %*d %*d %*d %*d %*u %*u %*d %*u %*u %*u %*u"
               /* startstack -> processor */
               "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %d",
               &usertime, &systime, &cpu) != 3) {
3345
        fclose(pidinfo);
3346 3347
        VIR_WARN0("cannot parse process status data");
        errno = -EINVAL;
D
Daniel P. Berrange 已提交
3348 3349 3350 3351 3352 3353 3354 3355
        return -1;
    }

    /* We got jiffies
     * We want nanoseconds
     * _SC_CLK_TCK is jiffies per second
     * So calulate thus....
     */
3356 3357 3358 3359 3360
    if (cpuTime)
        *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
    if (lastCpu)
        *lastCpu = cpu;

D
Daniel P. Berrange 已提交
3361

3362 3363
    VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d",
              pid, tid, usertime, systime, cpu);
D
Daniel P. Berrange 已提交
3364 3365 3366 3367 3368 3369 3370

    fclose(pidinfo);

    return 0;
}


3371
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
3372
                                          int id) {
3373 3374 3375 3376
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

3377
    qemuDriverLock(driver);
3378
    vm  = virDomainFindByID(&driver->domains, id);
3379
    qemuDriverUnlock(driver);
3380 3381

    if (!vm) {
3382 3383
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching id %d"), id);
3384
        goto cleanup;
3385 3386
    }

3387
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3388
    if (dom) dom->id = vm->def->id;
3389 3390

cleanup:
3391 3392
    if (vm)
        virDomainObjUnlock(vm);
3393 3394
    return dom;
}
3395

3396
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
3397
                                            const unsigned char *uuid) {
3398 3399 3400
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
3401

3402
    qemuDriverLock(driver);
3403
    vm = virDomainFindByUUID(&driver->domains, uuid);
3404 3405
    qemuDriverUnlock(driver);

3406
    if (!vm) {
3407 3408
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(uuid, uuidstr);
3409 3410
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3411
        goto cleanup;
3412 3413
    }

3414
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3415
    if (dom) dom->id = vm->def->id;
3416 3417

cleanup:
3418 3419
    if (vm)
        virDomainObjUnlock(vm);
3420 3421
    return dom;
}
3422

3423
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
3424
                                            const char *name) {
3425 3426 3427
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
3428

3429
    qemuDriverLock(driver);
3430
    vm = virDomainFindByName(&driver->domains, name);
3431 3432
    qemuDriverUnlock(driver);

3433
    if (!vm) {
3434 3435
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching name '%s'"), name);
3436
        goto cleanup;
3437 3438
    }

3439
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3440
    if (dom) dom->id = vm->def->id;
3441 3442

cleanup:
3443 3444
    if (vm)
        virDomainObjUnlock(vm);
3445 3446 3447
    return dom;
}

3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458

static int qemuDomainIsActive(virDomainPtr dom)
{
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    qemuDriverLock(driver);
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
    qemuDriverUnlock(driver);
    if (!obj) {
3459
        qemuReportError(VIR_ERR_NO_DOMAIN, NULL);
3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479
        goto cleanup;
    }
    ret = virDomainObjIsActive(obj);

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

static int qemuDomainIsPersistent(virDomainPtr dom)
{
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr obj;
    int ret = -1;

    qemuDriverLock(driver);
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
    qemuDriverUnlock(driver);
    if (!obj) {
3480
        qemuReportError(VIR_ERR_NO_DOMAIN, NULL);
3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491
        goto cleanup;
    }
    ret = obj->persistent;

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


3492
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
3493 3494 3495
    struct qemud_driver *driver = conn->privateData;
    int ret = -1;

3496
    qemuDriverLock(driver);
3497
    if (qemudExtractVersion(driver) < 0)
3498
        goto cleanup;
3499

3500
    *version = qemu_driver->qemuVersion;
3501 3502 3503
    ret = 0;

cleanup:
3504
    qemuDriverUnlock(driver);
3505
    return ret;
D
Daniel P. Berrange 已提交
3506 3507
}

3508
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
3509
    struct qemud_driver *driver = conn->privateData;
3510
    int n;
3511

3512
    qemuDriverLock(driver);
3513
    n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
3514
    qemuDriverUnlock(driver);
3515

3516
    return n;
D
Daniel P. Berrange 已提交
3517
}
3518

3519
static int qemudNumDomains(virConnectPtr conn) {
3520
    struct qemud_driver *driver = conn->privateData;
3521
    int n;
3522

3523
    qemuDriverLock(driver);
3524
    n = virDomainObjListNumOfDomains(&driver->domains, 1);
3525
    qemuDriverUnlock(driver);
3526

3527
    return n;
D
Daniel P. Berrange 已提交
3528
}
3529

3530
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
3531
                                      unsigned int flags ATTRIBUTE_UNUSED) {
3532
    struct qemud_driver *driver = conn->privateData;
3533
    virDomainDefPtr def;
3534
    virDomainObjPtr vm = NULL;
3535
    virDomainPtr dom = NULL;
3536
    virDomainEventPtr event = NULL;
D
Daniel P. Berrange 已提交
3537

3538
    qemuDriverLock(driver);
3539
    if (!(def = virDomainDefParseString(driver->caps, xml,
3540
                                        VIR_DOMAIN_XML_INACTIVE)))
3541
        goto cleanup;
3542

3543
    if (virSecurityDriverVerify(def) < 0)
3544 3545
        goto cleanup;

3546 3547
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
3548

3549 3550 3551 3552 3553 3554
    if (qemudCanonicalizeMachine(driver, def) < 0)
        goto cleanup;

    if (qemuAssignPCIAddresses(def) < 0)
        goto cleanup;

3555
    if (!(vm = virDomainAssignDef(driver->caps,
3556
                                  &driver->domains,
3557 3558 3559 3560
                                  def)))
        goto cleanup;

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

3562 3563 3564
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup; /* XXXX free the 'vm' we created ? */

3565
    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
3566 3567 3568
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains,
                                    vm);
3569
        vm = NULL;
3570
        goto endjob;
D
Daniel P. Berrange 已提交
3571
    }
3572 3573 3574 3575

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

3577
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3578
    if (dom) dom->id = vm->def->id;
3579

3580
endjob:
3581 3582 3583
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3584

3585 3586
cleanup:
    virDomainDefFree(def);
3587 3588
    if (vm)
        virDomainObjUnlock(vm);
3589 3590
    if (event)
        qemuDomainEventQueue(driver, event);
3591
    qemuDriverUnlock(driver);
3592
    return dom;
D
Daniel P. Berrange 已提交
3593 3594 3595
}


3596
static int qemudDomainSuspend(virDomainPtr dom) {
3597 3598 3599
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3600
    virDomainEventPtr event = NULL;
3601
    qemuDomainObjPrivatePtr priv;
3602

3603
    qemuDriverLock(driver);
3604
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3605

D
Daniel P. Berrange 已提交
3606
    if (!vm) {
3607 3608
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3609 3610
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3611
        goto cleanup;
D
Daniel P. Berrange 已提交
3612
    }
D
Daniel P. Berrange 已提交
3613
    if (!virDomainObjIsActive(vm)) {
3614 3615
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3616
        goto cleanup;
D
Daniel P. Berrange 已提交
3617
    }
3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635

    priv = vm->privateData;

    if (priv->jobActive == QEMU_JOB_MIGRATION) {
        if (vm->state != VIR_DOMAIN_PAUSED) {
            VIR_DEBUG("Requesting domain pause on %s",
                      vm->def->name);
            priv->jobSignals |= QEMU_JOB_SIGNAL_SUSPEND;
        }
        ret = 0;
        goto cleanup;
    } else {
        if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
            goto cleanup;

        if (!virDomainObjIsActive(vm)) {
            qemuReportError(VIR_ERR_OPERATION_INVALID,
                            "%s", _("domain is not running"));
3636
            goto endjob;
3637
        }
3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653
        if (vm->state != VIR_DOMAIN_PAUSED) {
            int rc;

            qemuDomainObjEnterMonitorWithDriver(driver, vm);
            rc = qemuMonitorStopCPUs(priv->mon);
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            if (rc < 0)
                goto endjob;
            vm->state = VIR_DOMAIN_PAUSED;
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_SUSPENDED,
                                             VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
        }
        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
            goto endjob;
        ret = 0;
D
Daniel P. Berrange 已提交
3654
    }
3655

3656
endjob:
3657 3658
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3659

3660
cleanup:
3661 3662
    if (vm)
        virDomainObjUnlock(vm);
3663

3664
    if (event)
3665
        qemuDomainEventQueue(driver, event);
3666
    qemuDriverUnlock(driver);
3667
    return ret;
D
Daniel P. Berrange 已提交
3668 3669 3670
}


3671
static int qemudDomainResume(virDomainPtr dom) {
3672 3673 3674
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3675
    virDomainEventPtr event = NULL;
3676

3677
    qemuDriverLock(driver);
3678
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3679

D
Daniel P. Berrange 已提交
3680
    if (!vm) {
3681 3682
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3683 3684
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3685
        goto cleanup;
D
Daniel P. Berrange 已提交
3686
    }
3687 3688 3689 3690

    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
3691
    if (!virDomainObjIsActive(vm)) {
3692 3693
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3694
        goto endjob;
D
Daniel P. Berrange 已提交
3695
    }
3696
    if (vm->state == VIR_DOMAIN_PAUSED) {
3697
        qemuDomainObjPrivatePtr priv = vm->privateData;
3698
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
3699
        if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) {
3700
            qemuDomainObjExitMonitorWithDriver(driver, vm);
3701
            if (virGetLastError() == NULL)
3702 3703
                qemuReportError(VIR_ERR_OPERATION_FAILED,
                                "%s", _("resume operation failed"));
3704
            goto endjob;
3705
        }
3706
        qemuDomainObjExitMonitorWithDriver(driver, vm);
3707
        vm->state = VIR_DOMAIN_RUNNING;
3708 3709 3710
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
D
Daniel P. Berrange 已提交
3711
    }
3712
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
3713
        goto endjob;
3714 3715
    ret = 0;

3716
endjob:
3717 3718
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3719

3720
cleanup:
3721 3722
    if (vm)
        virDomainObjUnlock(vm);
3723
    if (event)
3724
        qemuDomainEventQueue(driver, event);
3725
    qemuDriverUnlock(driver);
3726
    return ret;
D
Daniel P. Berrange 已提交
3727 3728 3729
}


3730
static int qemudDomainShutdown(virDomainPtr dom) {
3731 3732 3733
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3734

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

3739
    if (!vm) {
3740 3741
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3742 3743
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3744
        goto cleanup;
3745 3746
    }

3747 3748 3749
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
3750
    if (!virDomainObjIsActive(vm)) {
3751 3752
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3753
        goto endjob;
3754 3755
    }

3756
    qemuDomainObjPrivatePtr priv = vm->privateData;
3757 3758 3759
    qemuDomainObjEnterMonitor(vm);
    ret = qemuMonitorSystemPowerdown(priv->mon);
    qemuDomainObjExitMonitor(vm);
3760

3761
endjob:
3762 3763
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3764

3765
cleanup:
3766 3767
    if (vm)
        virDomainObjUnlock(vm);
3768
    return ret;
3769 3770 3771
}


3772
static int qemudDomainDestroy(virDomainPtr dom) {
3773 3774 3775
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3776
    virDomainEventPtr event = NULL;
3777

3778
    qemuDriverLock(driver);
3779
    vm  = virDomainFindByUUID(&driver->domains, dom->uuid);
D
Daniel P. Berrange 已提交
3780
    if (!vm) {
3781 3782
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3783 3784
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3785
        goto cleanup;
D
Daniel P. Berrange 已提交
3786
    }
3787 3788 3789 3790

    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
3791
    if (!virDomainObjIsActive(vm)) {
3792 3793
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3794
        goto endjob;
3795
    }
3796

3797
    qemudShutdownVMDaemon(driver, vm);
3798 3799 3800
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
3801
    if (!vm->persistent) {
3802 3803 3804
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains,
                                    vm);
3805 3806
        vm = NULL;
    }
3807 3808
    ret = 0;

3809
endjob:
3810 3811 3812
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3813

3814
cleanup:
3815 3816
    if (vm)
        virDomainObjUnlock(vm);
3817 3818
    if (event)
        qemuDomainEventQueue(driver, event);
3819
    qemuDriverUnlock(driver);
3820
    return ret;
D
Daniel P. Berrange 已提交
3821 3822 3823
}


3824
static char *qemudDomainGetOSType(virDomainPtr dom) {
3825 3826 3827
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *type = NULL;
3828

3829
    qemuDriverLock(driver);
3830
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3831
    qemuDriverUnlock(driver);
3832
    if (!vm) {
3833 3834
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3835 3836
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3837
        goto cleanup;
3838 3839
    }

3840
    if (!(type = strdup(vm->def->os.type)))
3841
        virReportOOMError();
3842 3843

cleanup:
3844 3845
    if (vm)
        virDomainObjUnlock(vm);
3846 3847 3848
    return type;
}

3849 3850
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
3851 3852 3853
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    unsigned long ret = 0;
3854

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

3859
    if (!vm) {
3860 3861
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3862 3863
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3864
        goto cleanup;
3865 3866
    }

3867 3868 3869
    ret = vm->def->maxmem;

cleanup:
3870 3871
    if (vm)
        virDomainObjUnlock(vm);
3872
    return ret;
3873 3874 3875
}

static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
3876
    struct qemud_driver *driver = dom->conn->privateData;
3877
    qemuDomainObjPrivatePtr priv;
3878
    virDomainObjPtr vm;
3879
    int ret = -1, r;
3880

3881
    qemuDriverLock(driver);
3882
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3883
    qemuDriverUnlock(driver);
3884
    if (!vm) {
3885 3886
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3887 3888
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3889
        goto cleanup;
3890 3891
    }

3892 3893 3894 3895 3896 3897
    if (!virDomainObjIsActive(vm)) {
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
        goto cleanup;
    }

3898
    if (newmem > vm->def->maxmem) {
3899 3900
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("cannot set memory higher than max memory"));
3901
        goto cleanup;
3902 3903
    }

3904 3905 3906
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

3907 3908 3909 3910 3911 3912
    priv = vm->privateData;
    qemuDomainObjEnterMonitor(vm);
    r = qemuMonitorSetBalloon(priv->mon, newmem);
    qemuDomainObjExitMonitor(vm);
    if (r < 0)
        goto endjob;
3913

3914 3915 3916 3917 3918
    /* Lack of balloon support is a fatal error */
    if (r == 0) {
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("cannot set memory of an active domain"));
        goto endjob;
3919
    }
3920

3921
    ret = 0;
3922
endjob:
3923 3924
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3925

3926
cleanup:
3927 3928
    if (vm)
        virDomainObjUnlock(vm);
3929
    return ret;
3930 3931
}

3932
static int qemudDomainGetInfo(virDomainPtr dom,
3933
                              virDomainInfoPtr info) {
3934 3935 3936
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3937 3938
    int err;
    unsigned long balloon;
3939

3940
    qemuDriverLock(driver);
3941
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3942
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
3943
    if (!vm) {
3944 3945
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3946 3947
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3948
        goto cleanup;
D
Daniel P. Berrange 已提交
3949 3950
    }

3951
    info->state = vm->state;
D
Daniel P. Berrange 已提交
3952

D
Daniel P. Berrange 已提交
3953
    if (!virDomainObjIsActive(vm)) {
3954
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
3955
    } else {
3956
        if (qemudGetProcessInfo(&(info->cpuTime), NULL, vm->pid, 0) < 0) {
3957
            qemuReportError(VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
3958
            goto cleanup;
D
Daniel P. Berrange 已提交
3959 3960 3961
        }
    }

3962
    info->maxMem = vm->def->maxmem;
3963

D
Daniel P. Berrange 已提交
3964
    if (virDomainObjIsActive(vm)) {
3965
        qemuDomainObjPrivatePtr priv = vm->privateData;
3966 3967 3968
        if (!priv->jobActive) {
            if (qemuDomainObjBeginJob(vm) < 0)
                goto cleanup;
3969

3970 3971 3972 3973
            qemuDomainObjEnterMonitor(vm);
            err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
            qemuDomainObjExitMonitor(vm);
            if (err < 0) {
3974 3975
                if (qemuDomainObjEndJob(vm) == 0)
                    vm = NULL;
3976 3977 3978 3979 3980 3981 3982 3983 3984
                goto cleanup;
            }

            if (err == 0)
                /* Balloon not supported, so maxmem is always the allocation */
                info->memory = vm->def->maxmem;
            else
                info->memory = balloon;

3985 3986 3987 3988
            if (qemuDomainObjEndJob(vm) == 0) {
                vm = NULL;
                goto cleanup;
            }
3989 3990 3991
        } else {
            info->memory = vm->def->memory;
        }
3992 3993 3994 3995
    } else {
        info->memory = vm->def->memory;
    }

3996
    info->nrVirtCpu = vm->def->vcpus;
3997 3998 3999
    ret = 0;

cleanup:
4000 4001
    if (vm)
        virDomainObjUnlock(vm);
4002
    return ret;
D
Daniel P. Berrange 已提交
4003 4004 4005
}


4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034
/** qemuDomainMigrateOffline:
 * Pause domain for non-live migration.
 */
static int
qemuDomainMigrateOffline(struct qemud_driver *driver,
                         virDomainObjPtr vm)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int ret;

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
    ret = qemuMonitorStopCPUs(priv->mon);
    qemuDomainObjExitMonitorWithDriver(driver, vm);

    if (ret == 0) {
        virDomainEventPtr event;

        vm->state = VIR_DOMAIN_PAUSED;
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }

    return ret;
}


4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052
static int
qemuDomainWaitForMigrationComplete(struct qemud_driver *driver, virDomainObjPtr vm)
{
    int ret = -1;
    int status;
    unsigned long long memProcessed;
    unsigned long long memRemaining;
    unsigned long long memTotal;
    qemuDomainObjPrivatePtr priv = vm->privateData;

    priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;

    while (priv->jobInfo.type == VIR_DOMAIN_JOB_UNBOUNDED) {
        /* Poll every 50ms for progress & to allow cancellation */
        struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000ull };
        struct timeval now;
        int rc;

4053 4054
        if (priv->jobSignals & QEMU_JOB_SIGNAL_CANCEL) {
            priv->jobSignals ^= QEMU_JOB_SIGNAL_CANCEL;
4055 4056 4057 4058 4059 4060 4061
            VIR_DEBUG0("Cancelling migration at client request");
            qemuDomainObjEnterMonitorWithDriver(driver, vm);
            rc = qemuMonitorMigrateCancel(priv->mon);
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            if (rc < 0) {
                VIR_WARN0("Unable to cancel migration");
            }
4062 4063 4064 4065 4066
        } else if (priv->jobSignals & QEMU_JOB_SIGNAL_SUSPEND) {
            priv->jobSignals ^= QEMU_JOB_SIGNAL_SUSPEND;
            VIR_DEBUG0("Pausing domain for non-live migration");
            if (qemuDomainMigrateOffline(driver, vm) < 0)
                VIR_WARN0("Unable to pause domain");
4067 4068
        }

4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
        rc = qemuMonitorGetMigrationStatus(priv->mon,
                                           &status,
                                           &memProcessed,
                                           &memRemaining,
                                           &memTotal);
        qemuDomainObjExitMonitorWithDriver(driver, vm);

        if (rc < 0) {
            priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED;
            goto cleanup;
        }

        if (gettimeofday(&now, NULL) < 0) {
            priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED;
            virReportSystemError(errno, "%s",
                                 _("cannot get time of day"));
            goto cleanup;
        }
        priv->jobInfo.timeElapsed =
            ((now.tv_sec * 1000ull) + (now.tv_usec / 1000)) -
            priv->jobStart;

        switch (status) {
        case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
            priv->jobInfo.type = VIR_DOMAIN_JOB_NONE;
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Migration is not active"));
            break;

        case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
            priv->jobInfo.dataTotal = memTotal;
            priv->jobInfo.dataRemaining = memRemaining;
            priv->jobInfo.dataProcessed = memProcessed;

            priv->jobInfo.memTotal = memTotal;
            priv->jobInfo.memRemaining = memRemaining;
            priv->jobInfo.memProcessed = memProcessed;
            break;

        case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
            priv->jobInfo.type = VIR_DOMAIN_JOB_COMPLETED;
            ret = 0;
            break;

        case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
            priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED;
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Migration unexpectedly failed"));
            break;

        case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
            priv->jobInfo.type = VIR_DOMAIN_JOB_CANCELLED;
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Migration was cancelled by client"));
            break;
        }

        virDomainObjUnlock(vm);
        qemuDriverUnlock(driver);

        nanosleep(&ts, NULL);

        qemuDriverLock(driver);
        virDomainObjLock(vm);
    }

cleanup:
    return ret;
}


4141
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave"
4142 4143 4144
#define QEMUD_SAVE_VERSION 2

enum qemud_save_formats {
4145 4146 4147
    QEMUD_SAVE_FORMAT_RAW = 0,
    QEMUD_SAVE_FORMAT_GZIP = 1,
    QEMUD_SAVE_FORMAT_BZIP2 = 2,
4148 4149
    /*
     * Deprecated by xz and never used as part of a release
4150
     * QEMUD_SAVE_FORMAT_LZMA
4151 4152
     */
    QEMUD_SAVE_FORMAT_XZ = 3,
4153
    QEMUD_SAVE_FORMAT_LZOP = 4,
4154 4155 4156
    /* Note: add new members only at the end.
       These values are used in the on-disk format.
       Do not change or re-use numbers. */
4157 4158

    QEMUD_SAVE_FORMAT_LAST
4159
};
4160

4161 4162 4163 4164 4165
VIR_ENUM_DECL(qemudSaveCompression)
VIR_ENUM_IMPL(qemudSaveCompression, QEMUD_SAVE_FORMAT_LAST,
              "raw",
              "gzip",
              "bzip2",
4166 4167
              "xz",
              "lzop")
4168

4169 4170 4171 4172 4173
struct qemud_save_header {
    char magic[sizeof(QEMUD_SAVE_MAGIC)-1];
    int version;
    int xml_len;
    int was_running;
4174 4175
    int compressed;
    int unused[15];
4176 4177
};

4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206
struct fileOpHookData {
    virDomainPtr dom;
    const char *path;
    char *xml;
    struct qemud_save_header *header;
};

static int qemudDomainSaveFileOpHook(int fd, void *data) {
    struct fileOpHookData *hdata = data;
    int ret = 0;

    if (safewrite(fd, hdata->header, sizeof(*hdata->header)) != sizeof(*hdata->header)) {
        ret = errno;
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                         _("failed to write save header to '%s'"), hdata->path);
        goto endjob;
    }

    if (safewrite(fd, hdata->xml, hdata->header->xml_len) != hdata->header->xml_len) {
        ret = errno;
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                         _("failed to write xml to '%s'"), hdata->path);
        goto endjob;
    }
endjob:
    return ret;
}


4207
static int qemudDomainSave(virDomainPtr dom,
4208 4209
                           const char *path)
{
4210
    struct qemud_driver *driver = dom->conn->privateData;
4211
    virDomainObjPtr vm = NULL;
4212
    char *xml = NULL;
4213
    struct qemud_save_header header;
4214 4215
    struct fileOpHookData hdata;
    int bypassSecurityDriver = 0;
4216
    int ret = -1;
4217
    int rc;
4218
    virDomainEventPtr event = NULL;
4219
    qemuDomainObjPrivatePtr priv;
4220 4221 4222 4223 4224

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

4225
    qemuDriverLock(driver);
4226 4227 4228
    if (driver->saveImageFormat == NULL)
        header.compressed = QEMUD_SAVE_FORMAT_RAW;
    else {
4229 4230 4231
        header.compressed =
            qemudSaveCompressionTypeFromString(driver->saveImageFormat);
        if (header.compressed < 0) {
4232 4233 4234
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Invalid save image format specified "
                                    "in configuration file"));
4235
            goto cleanup;
4236
        }
4237 4238
    }

4239
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4240

D
Daniel P. Berrange 已提交
4241
    if (!vm) {
4242 4243
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4244 4245
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4246
        goto cleanup;
D
Daniel P. Berrange 已提交
4247
    }
4248
    priv = vm->privateData;
4249

4250 4251 4252
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
4253
    if (!virDomainObjIsActive(vm)) {
4254 4255
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
4256
        goto endjob;
D
Daniel P. Berrange 已提交
4257
    }
4258

4259 4260 4261
    memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
    priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;

4262 4263 4264
    /* Pause */
    if (vm->state == VIR_DOMAIN_RUNNING) {
        header.was_running = 1;
4265
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
4266
        if (qemuMonitorStopCPUs(priv->mon) < 0) {
4267 4268
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            goto endjob;
4269
        }
4270
        qemuDomainObjExitMonitorWithDriver(driver, vm);
4271
        vm->state = VIR_DOMAIN_PAUSED;
4272 4273 4274
    }

    /* Get XML for the domain */
4275
    xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
4276
    if (!xml) {
4277 4278
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to get domain xml"));
4279
        goto endjob;
4280 4281 4282
    }
    header.xml_len = strlen(xml) + 1;

4283 4284 4285 4286 4287 4288
    /* Setup hook data needed by virFileOperation hook function */
    hdata.dom = dom;
    hdata.path = path;
    hdata.xml = xml;
    hdata.header = &header;

4289 4290
    /* Write header to file, followed by XML */

4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310
    /* First try creating the file as root */
    if ((rc = virFileOperation(path, O_CREAT|O_TRUNC|O_WRONLY,
                               S_IRUSR|S_IWUSR,
                               getuid(), getgid(),
                               qemudDomainSaveFileOpHook, &hdata,
                               0)) != 0) {

        /* If we failed as root, and the error was permission-denied
           (EACCES), assume it's on a network-connected share where
           root access is restricted (eg, root-squashed NFS). If the
           qemu user (driver->user) is non-root, just set a flag to
           bypass security driver shenanigans, and retry the operation
           after doing setuid to qemu user */

        if ((rc != EACCES) ||
            driver->user == getuid()) {
            virReportSystemError(rc, _("Failed to create domain save file '%s'"),
                                 path);
            goto endjob;
        }
4311

4312 4313 4314 4315 4316
#ifdef __linux__
        /* On Linux we can also verify the FS-type of the directory. */
        char *dirpath, *p;
        struct statfs st;
        int statfs_ret;
4317

4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384
        if ((dirpath = strdup(path)) == NULL) {
            virReportOOMError();
            goto endjob;
        }

        do {
            // Try less and less of the path until we get to a
            // directory we can stat. Even if we don't have 'x'
            // permission on any directory in the path on the NFS
            // server (assuming it's NFS), we will be able to stat the
            // mount point, and that will properly tell us if the
            // fstype is NFS.

            if ((p = strrchr(dirpath, '/')) == NULL) {
                qemuReportError(VIR_ERR_INVALID_ARG,
                                _("Invalid relative path '%s' for domain save file"),
                                path);
                VIR_FREE(dirpath);
                goto endjob;
            }

            if (p == dirpath)
                *(p+1) = '\0';
            else
                *p = '\0';

            statfs_ret = statfs(dirpath, &st);

        } while ((statfs_ret == -1) && (p != dirpath));

        if (statfs_ret == -1) {
            virReportSystemError(errno,
                                 _("Failed to create domain save file '%s'"
                                   " statfs of all elements of path failed."),
                                 path);
            VIR_FREE(dirpath);
            goto endjob;
        }

        if (st.f_type != NFS_SUPER_MAGIC) {
            virReportSystemError(rc,
                                 _("Failed to create domain save file '%s'"
                                   " (fstype of '%s' is 0x%X"),
                                 path, dirpath, (unsigned int) st.f_type);
            VIR_FREE(dirpath);
            goto endjob;
        }
        VIR_FREE(dirpath);
#endif

        /* Retry creating the file as driver->user */

        if ((rc = virFileOperation(path, O_CREAT|O_TRUNC|O_WRONLY,
                                   S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
                                   driver->user, driver->group,
                                   qemudDomainSaveFileOpHook, &hdata,
                                   VIR_FILE_OP_AS_UID)) != 0) {
            virReportSystemError(rc, _("Error from child process creating '%s'"),
                                 path);
            goto endjob;
        }

        /* Since we had to setuid to create the file, and the fstype
           is NFS, we assume it's a root-squashing NFS share, and that
           the security driver stuff would have failed anyway */

        bypassSecurityDriver = 1;
4385
    }
4386

4387 4388 4389

    if ((!bypassSecurityDriver) &&
        driver->securityDriver &&
4390
        driver->securityDriver->domainSetSavedStateLabel &&
4391
        driver->securityDriver->domainSetSavedStateLabel(vm, path) == -1)
4392 4393
        goto endjob;

4394 4395
    if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
        const char *args[] = { "cat", NULL };
M
Matthias Bolte 已提交
4396
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
4397
        rc = qemuMonitorMigrateToCommand(priv->mon, 1, args, path);
M
Matthias Bolte 已提交
4398
        qemuDomainObjExitMonitorWithDriver(driver, vm);
4399
    } else {
4400
        const char *prog = qemudSaveCompressionTypeToString(header.compressed);
4401 4402 4403 4404 4405
        const char *args[] = {
            prog,
            "-c",
            NULL
        };
M
Matthias Bolte 已提交
4406
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
4407
        rc = qemuMonitorMigrateToCommand(priv->mon, 1, args, path);
M
Matthias Bolte 已提交
4408
        qemuDomainObjExitMonitorWithDriver(driver, vm);
4409 4410
    }

4411 4412 4413 4414 4415
    if (rc < 0)
        goto endjob;

    rc = qemuDomainWaitForMigrationComplete(driver, vm);

4416
    if (rc < 0)
4417
        goto endjob;
4418

4419 4420
    if ((!bypassSecurityDriver) &&
        driver->securityDriver &&
4421
        driver->securityDriver->domainRestoreSavedStateLabel &&
4422
        driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
4423 4424 4425 4426
        goto endjob;

    ret = 0;

4427
    /* Shut it down */
4428
    qemudShutdownVMDaemon(driver, vm);
4429 4430 4431
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
4432
    if (!vm->persistent) {
4433 4434 4435
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains,
                                    vm);
4436 4437
        vm = NULL;
    }
4438

4439
endjob:
4440 4441 4442 4443 4444 4445 4446 4447 4448 4449
    if (ret != 0 && header.was_running) {
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
        rc = qemuMonitorStartCPUs(priv->mon, dom->conn);
        qemuDomainObjExitMonitorWithDriver(driver, vm);
        if (rc < 0)
            VIR_WARN0("Unable to resume guest CPUs after save failure");
        else
            vm->state = VIR_DOMAIN_RUNNING;
    }

4450 4451
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
4452
            vm = NULL;
4453

4454 4455 4456 4457
cleanup:
    VIR_FREE(xml);
    if (ret != 0)
        unlink(path);
4458 4459
    if (vm)
        virDomainObjUnlock(vm);
4460 4461
    if (event)
        qemuDomainEventQueue(driver, event);
4462
    qemuDriverUnlock(driver);
4463
    return ret;
D
Daniel P. Berrange 已提交
4464 4465 4466
}


P
Paolo Bonzini 已提交
4467 4468 4469 4470 4471 4472
static int qemudDomainCoreDump(virDomainPtr dom,
                               const char *path,
                               int flags ATTRIBUTE_UNUSED) {
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int resume = 0, paused = 0;
4473
    int ret = -1, fd = -1;
4474
    virDomainEventPtr event = NULL;
4475 4476 4477 4478
    const char *args[] = {
        "cat",
        NULL,
    };
4479
    qemuDomainObjPrivatePtr priv;
P
Paolo Bonzini 已提交
4480 4481 4482 4483 4484 4485 4486

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

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4487 4488
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
P
Paolo Bonzini 已提交
4489 4490
        goto cleanup;
    }
4491
    priv = vm->privateData;
P
Paolo Bonzini 已提交
4492

4493
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
4494 4495
        goto cleanup;

D
Daniel P. Berrange 已提交
4496
    if (!virDomainObjIsActive(vm)) {
4497 4498
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
4499
        goto endjob;
P
Paolo Bonzini 已提交
4500 4501
    }

4502 4503
    /* Create an empty file with appropriate ownership.  */
    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
4504 4505
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("failed to create '%s'"), path);
4506 4507 4508 4509
        goto endjob;
    }

    if (close(fd) < 0) {
4510
        virReportSystemError(errno,
4511 4512 4513 4514 4515 4516 4517
                             _("unable to save file %s"),
                             path);
        goto endjob;
    }

    if (driver->securityDriver &&
        driver->securityDriver->domainSetSavedStateLabel &&
4518
        driver->securityDriver->domainSetSavedStateLabel(vm, path) == -1)
4519 4520
        goto endjob;

P
Paolo Bonzini 已提交
4521 4522
    /* Migrate will always stop the VM, so the resume condition is
       independent of whether the stop command is issued.  */
P
Paolo Bonzini 已提交
4523 4524 4525
    resume = (vm->state == VIR_DOMAIN_RUNNING);

    /* Pause domain for non-live dump */
P
Paolo Bonzini 已提交
4526
    if (!(flags & VIR_DUMP_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
4527 4528 4529
        qemuDomainObjEnterMonitor(vm);
        if (qemuMonitorStopCPUs(priv->mon) < 0) {
            qemuDomainObjExitMonitor(vm);
4530
            goto endjob;
4531 4532
        }
        qemuDomainObjExitMonitor(vm);
P
Paolo Bonzini 已提交
4533 4534 4535
        paused = 1;
    }

4536
    qemuDomainObjEnterMonitor(vm);
4537
    ret = qemuMonitorMigrateToCommand(priv->mon, 1, args, path);
4538
    qemuDomainObjExitMonitor(vm);
4539 4540 4541 4542 4543 4544 4545 4546 4547 4548

    if (ret < 0)
        goto endjob;

    ret = qemuDomainWaitForMigrationComplete(driver, vm);

    if (ret < 0)
        goto endjob;

    paused = 1;
4549 4550 4551

    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSavedStateLabel &&
4552
        driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
4553 4554 4555
        goto endjob;

endjob:
4556
    if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
4557
        qemudShutdownVMDaemon(driver, vm);
4558 4559 4560 4561 4562
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
    }

P
Paolo Bonzini 已提交
4563 4564 4565
    /* Since the monitor is always attached to a pty for libvirt, it
       will support synchronous operations so we always get here after
       the migration is complete.  */
4566
    else if (resume && paused) {
4567
        qemuDomainObjEnterMonitor(vm);
4568
        if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) {
4569
            if (virGetLastError() == NULL)
4570 4571
                qemuReportError(VIR_ERR_OPERATION_FAILED,
                                "%s", _("resuming after dump failed"));
P
Paolo Bonzini 已提交
4572
        }
4573
        qemuDomainObjExitMonitor(vm);
P
Paolo Bonzini 已提交
4574
    }
4575

4576 4577
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
4578
    else if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) {
4579 4580 4581 4582
        virDomainRemoveInactive(&driver->domains,
                                vm);
        vm = NULL;
    }
4583 4584

cleanup:
4585 4586
    if (ret != 0)
        unlink(path);
P
Paolo Bonzini 已提交
4587 4588
    if (vm)
        virDomainObjUnlock(vm);
4589 4590
    if (event)
        qemuDomainEventQueue(driver, event);
4591
    qemuDriverUnlock(driver);
P
Paolo Bonzini 已提交
4592 4593 4594 4595
    return ret;
}


4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607
static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int i, rc;
    int ret = -1;

    /* We need different branches here, because we want to offline
     * in reverse order to onlining, so any partial fail leaves us in a
     * reasonably sensible state */
    if (nvcpus > vm->def->vcpus) {
        for (i = vm->def->vcpus ; i < nvcpus ; i++) {
            /* Online new CPU */
4608
            qemuDomainObjEnterMonitor(vm);
4609
            rc = qemuMonitorSetCPU(priv->mon, i, 1);
4610
            qemuDomainObjExitMonitor(vm);
4611 4612 4613 4614 4615 4616 4617 4618 4619 4620
            if (rc == 0)
                goto unsupported;
            if (rc < 0)
                goto cleanup;

            vm->def->vcpus++;
        }
    } else {
        for (i = vm->def->vcpus - 1 ; i >= nvcpus ; i--) {
            /* Offline old CPU */
4621
            qemuDomainObjEnterMonitor(vm);
4622
            rc = qemuMonitorSetCPU(priv->mon, i, 0);
4623
            qemuDomainObjExitMonitor(vm);
4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645
            if (rc == 0)
                goto unsupported;
            if (rc < 0)
                goto cleanup;

            vm->def->vcpus--;
        }
    }

    ret = 0;

cleanup:
    return ret;

unsupported:
    qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("cannot change vcpu count of this domain"));
    goto cleanup;
}


static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
4646 4647
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4648 4649
    const char * type;
    int max;
4650
    int ret = -1;
4651

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

4656 4657 4658
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

4659
    if (!vm) {
4660 4661
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4662 4663
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4664
        goto endjob;
4665 4666
    }

4667 4668 4669
    if (!virDomainObjIsActive(vm)) {
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                         "%s", _("domain is not running"));
4670
        goto endjob;
4671 4672
    }

4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown virt type in domain definition '%d'"),
                        vm->def->virtType);
        goto endjob;
    }

    if ((max = qemudGetMaxVCPUs(NULL, type)) < 0) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("could not determine max vcpus for the domain"));
        goto endjob;
    }

    if (nvcpus > max) {
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("requested vcpus is greater than max allowable"
                          " vcpus for the domain: %d > %d"), nvcpus, max);
        goto endjob;
    }

    ret = qemudDomainHotplugVcpus(vm, nvcpus);

endjob:
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
4698

4699
cleanup:
4700 4701
    if (vm)
        virDomainObjUnlock(vm);
4702
    return ret;
4703 4704
}

4705 4706 4707 4708 4709 4710

static int
qemudDomainPinVcpu(virDomainPtr dom,
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
4711 4712
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4713
    int maxcpu, hostcpus;
4714
    virNodeInfo nodeinfo;
4715
    int ret = -1;
4716
    qemuDomainObjPrivatePtr priv;
4717

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

4722 4723 4724
    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4725 4726
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4727 4728 4729
        goto cleanup;
    }

D
Daniel P. Berrange 已提交
4730
    if (!virDomainObjIsActive(vm)) {
4731 4732
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s",_("cannot pin vcpus on an inactive domain"));
4733
        goto cleanup;
4734 4735
    }

4736 4737 4738
    priv = vm->privateData;

    if (vcpu > (priv->nvcpupids-1)) {
4739 4740 4741
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("vcpu number out of range %d > %d"),
                        vcpu, priv->nvcpupids);
4742
        goto cleanup;
4743 4744
    }

4745
    if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
4746
        goto cleanup;
4747

4748
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
4749
    maxcpu = maplen * 8;
4750 4751
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
4752

4753 4754
    if (priv->vcpupids != NULL) {
        if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
4755
                                      cpumap, maplen, maxcpu) < 0)
4756
            goto cleanup;
4757
    } else {
4758 4759
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("cpu affinity is not supported"));
4760
        goto cleanup;
4761
    }
4762
    ret = 0;
4763

4764
cleanup:
4765 4766
    if (vm)
        virDomainObjUnlock(vm);
4767
    return ret;
4768 4769 4770 4771 4772 4773 4774 4775
}

static int
qemudDomainGetVcpus(virDomainPtr dom,
                    virVcpuInfoPtr info,
                    int maxinfo,
                    unsigned char *cpumaps,
                    int maplen) {
4776 4777
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4778
    virNodeInfo nodeinfo;
4779
    int i, v, maxcpu, hostcpus;
4780
    int ret = -1;
4781
    qemuDomainObjPrivatePtr priv;
4782

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

4787 4788 4789
    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4790 4791
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4792 4793 4794
        goto cleanup;
    }

D
Daniel P. Berrange 已提交
4795
    if (!virDomainObjIsActive(vm)) {
4796 4797 4798
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s",
                        _("cannot list vcpu pinning for an inactive domain"));
4799
        goto cleanup;
4800 4801
    }

4802 4803
    priv = vm->privateData;

4804
    if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
4805
        goto cleanup;
4806

4807
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
4808
    maxcpu = maplen * 8;
4809 4810
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
4811 4812

    /* Clamp to actual number of vcpus */
4813 4814
    if (maxinfo > priv->nvcpupids)
        maxinfo = priv->nvcpupids;
4815

4816 4817 4818 4819 4820 4821
    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;
4822

4823
                if (priv->vcpupids != NULL &&
4824 4825 4826
                    qemudGetProcessInfo(&(info[i].cpuTime),
                                        &(info[i].cpu),
                                        vm->pid,
4827
                                        priv->vcpupids[i]) < 0) {
4828
                    virReportSystemError(errno, "%s",
4829 4830 4831
                                         _("cannot get vCPU placement & pCPU time"));
                    goto cleanup;
                }
4832
            }
4833 4834
        }

4835 4836
        if (cpumaps != NULL) {
            memset(cpumaps, 0, maplen * maxinfo);
4837
            if (priv->vcpupids != NULL) {
4838 4839 4840
                for (v = 0 ; v < maxinfo ; v++) {
                    unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);

4841
                    if (virProcessInfoGetAffinity(priv->vcpupids[v],
4842
                                                  cpumap, maplen, maxcpu) < 0)
4843
                        goto cleanup;
4844
                }
4845
            } else {
4846 4847
                qemuReportError(VIR_ERR_NO_SUPPORT,
                                "%s", _("cpu affinity is not available"));
4848
                goto cleanup;
4849 4850 4851
            }
        }
    }
4852
    ret = maxinfo;
4853

4854
cleanup:
4855 4856
    if (vm)
        virDomainObjUnlock(vm);
4857
    return ret;
4858 4859 4860
}


4861
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
4862 4863
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4864
    const char *type;
4865
    int ret = -1;
4866

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

4871
    if (!vm) {
4872 4873
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4874 4875
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4876
        goto cleanup;
4877 4878
    }

4879
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
4880 4881 4882
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown virt type in domain definition '%d'"),
                        vm->def->virtType);
4883
        goto cleanup;
4884 4885
    }

4886
    ret = qemudGetMaxVCPUs(NULL, type);
4887

4888
cleanup:
4889 4890
    if (vm)
        virDomainObjUnlock(vm);
4891 4892 4893
    return ret;
}

4894 4895 4896 4897 4898 4899 4900 4901 4902 4903
static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
{
    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
    virDomainObjPtr vm;
    const char *type;
    int ret = -1;

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

4904 4905
    memset(seclabel, 0, sizeof(*seclabel));

4906 4907 4908
    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4909 4910
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4911 4912 4913 4914
        goto cleanup;
    }

    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
4915 4916 4917
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown virt type in domain definition '%d'"),
                        vm->def->virtType);
4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934
        goto cleanup;
    }

    /*
     * Theoretically, the pid can be replaced during this operation and
     * return the label of a different process.  If atomicity is needed,
     * further validation will be required.
     *
     * Comment from Dan Berrange:
     *
     *   Well the PID as stored in the virDomainObjPtr can't be changed
     *   because you've got a locked object.  The OS level PID could have
     *   exited, though and in extreme circumstances have cycled through all
     *   PIDs back to ours. We could sanity check that our PID still exists
     *   after reading the label, by checking that our FD connecting to the
     *   QEMU monitor hasn't seen SIGHUP/ERR on poll().
     */
D
Daniel P. Berrange 已提交
4935
    if (virDomainObjIsActive(vm)) {
4936
        if (driver->securityDriver && driver->securityDriver->domainGetSecurityProcessLabel) {
4937
            if (driver->securityDriver->domainGetSecurityProcessLabel(vm, seclabel) == -1) {
4938 4939
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("Failed to get security label"));
4940 4941 4942 4943 4944 4945 4946 4947 4948 4949
                goto cleanup;
            }
        }
    }

    ret = 0;

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
4950
    qemuDriverUnlock(driver);
4951 4952 4953
    return ret;
}

4954 4955
static int qemudNodeGetSecurityModel(virConnectPtr conn,
                                     virSecurityModelPtr secmodel)
4956 4957 4958
{
    struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
    char *p;
4959
    int ret = 0;
4960

4961 4962
    qemuDriverLock(driver);
    if (!driver->securityDriver) {
4963
        memset(secmodel, 0, sizeof (*secmodel));
4964 4965
        goto cleanup;
    }
4966

4967 4968
    p = driver->caps->host.secModel.model;
    if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
4969 4970 4971
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("security model string exceeds max %d bytes"),
                        VIR_SECURITY_MODEL_BUFLEN-1);
4972 4973
        ret = -1;
        goto cleanup;
4974 4975 4976 4977 4978
    }
    strcpy(secmodel->model, p);

    p = driver->caps->host.secModel.doi;
    if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
4979 4980 4981
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("security DOI string exceeds max %d bytes"),
                        VIR_SECURITY_DOI_BUFLEN-1);
4982 4983
        ret = -1;
        goto cleanup;
4984 4985
    }
    strcpy(secmodel->doi, p);
4986 4987 4988 4989

cleanup:
    qemuDriverUnlock(driver);
    return ret;
4990 4991
}

4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123
/* qemudOpenAsUID() - pipe/fork/setuid/open a file, and return the
   pipe fd to caller, so that it can read from the file. Also return
   the pid of the child process, so the caller can wait for it to exit
   after it's finished reading (to avoid a zombie, if nothing
   else). */

static int qemudOpenAsUID(const char *path, uid_t uid, pid_t *child_pid) {
    int pipefd[2];
    int fd = -1;

    *child_pid = -1;

    if (pipe(pipefd) < 0) {
        virReportSystemError(errno,
                             _("failed to create pipe to read '%s'"),
                             path);
        pipefd[0] = pipefd[1] = -1;
        goto parent_cleanup;
    }

    int forkRet = virFork(child_pid);

    if (*child_pid < 0) {
        virReportSystemError(errno,
                             _("failed to fork child to read '%s'"),
                             path);
        goto parent_cleanup;
    }

    if (*child_pid > 0) {

        /* parent */

        /* parent doesn't need the write side of the pipe */
        close(pipefd[1]);
        pipefd[1] = -1;

        if (forkRet < 0) {
            virReportSystemError(errno,
                                 _("failed in parent after forking child to read '%s'"),
                                 path);
            goto parent_cleanup;
        }
        /* caller gets the read side of the pipe */
        fd = pipefd[0];
        pipefd[0] = -1;
parent_cleanup:
        if (pipefd[0] != -1)
            close(pipefd[0]);
        if (pipefd[1] != -1)
            close(pipefd[1]);
        if ((fd < 0) && (*child_pid > 0)) {
            /* a child process was started and subsequently an error
               occurred in the parent, so we need to wait for it to
               exit, but its status is inconsequential. */
            while ((waitpid(*child_pid, NULL, 0) == -1)
                   && (errno == EINTR)) {
                /* empty */
            }
            *child_pid = -1;
        }
        return fd;
    }

    /* child */

    /* setuid to the qemu user, then open the file, read it,
       and stuff it into the pipe for the parent process to
       read */
    int exit_code;
    char *buf = NULL;
    size_t bufsize = 1024 * 1024;
    int bytesread;

    /* child doesn't need the read side of the pipe */
    close(pipefd[0]);

    if (forkRet < 0) {
        exit_code = errno;
        virReportSystemError(errno,
                             _("failed in child after forking to read '%s'"),
                             path);
        goto child_cleanup;
    }

    if (setuid(uid) != 0) {
        exit_code = errno;
        virReportSystemError(errno,
                             _("cannot setuid(%d) to read '%s'"),
                             uid, path);
        goto child_cleanup;
    }
    if ((fd = open(path, O_RDONLY)) < 0) {
        exit_code = errno;
        virReportSystemError(errno,
                             _("cannot open '%s' as uid %d"),
                             path, uid);
        goto child_cleanup;
    }
    if (VIR_ALLOC_N(buf, bufsize) < 0) {
        exit_code = ENOMEM;
        virReportOOMError();
        goto child_cleanup;
    }

    /* read from fd and write to pipefd[1] until EOF */
    do {
        if ((bytesread = saferead(fd, buf, bufsize)) < 0) {
            exit_code = errno;
            virReportSystemError(errno,
                                 _("child failed reading from '%s'"),
                                 path);
            goto child_cleanup;
        }
        if (safewrite(pipefd[1], buf, bytesread) != bytesread) {
            exit_code = errno;
            virReportSystemError(errno, "%s",
                                 _("child failed writing to pipe"));
            goto child_cleanup;
        }
    } while (bytesread > 0);
    exit_code = 0;

child_cleanup:
    VIR_FREE(buf);
    if (fd != -1)
        close(fd);
    if (pipefd[1] != -1)
        close(pipefd[1]);
    _exit(exit_code);
}

5124
/* TODO: check seclabel restore */
5125
static int qemudDomainRestore(virConnectPtr conn,
5126 5127 5128
                              const char *path) {
    struct qemud_driver *driver = conn->privateData;
    virDomainDefPtr def = NULL;
5129
    virDomainObjPtr vm = NULL;
5130
    int fd = -1;
5131
    pid_t read_pid = -1;
5132 5133
    int ret = -1;
    char *xml = NULL;
5134
    struct qemud_save_header header;
5135
    virDomainEventPtr event = NULL;
5136 5137 5138
    int intermediatefd = -1;
    pid_t intermediate_pid = -1;
    int childstat;
5139

5140
    qemuDriverLock(driver);
5141 5142
    /* Verify the header and read the XML */
    if ((fd = open(path, O_RDONLY)) < 0) {
5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156
        if ((driver->user == 0) || (getuid() != 0)) {
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("cannot read domain image"));
            goto cleanup;
        }

        /* Opening as root failed, but qemu runs as a different user
           that might have better luck. Create a pipe, then fork a
           child process to run as the qemu user, which will hopefully
           have the necessary authority to read the file. */
        if ((fd = qemudOpenAsUID(path, driver->user, &read_pid)) < 0) {
            /* error already reported */
            goto cleanup;
        }
5157 5158 5159
    }

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
5160 5161
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to read qemu header"));
5162
        goto cleanup;
5163 5164 5165
    }

    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
5166 5167
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("image magic is incorrect"));
5168
        goto cleanup;
5169 5170 5171
    }

    if (header.version > QEMUD_SAVE_VERSION) {
5172 5173 5174
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("image version is not supported (%d > %d)"),
                        header.version, QEMUD_SAVE_VERSION);
5175
        goto cleanup;
5176 5177
    }

5178 5179 5180
    if (header.xml_len <= 0) {
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("invalid XML length: %d"), header.xml_len);
5181
        goto cleanup;
5182 5183
    }

5184
    if (virFileReadLimFD(fd, header.xml_len, &xml) != header.xml_len) {
5185 5186
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to read XML"));
5187
        goto cleanup;
5188 5189 5190
    }

    /* Create a domain from this XML */
5191
    if (!(def = virDomainDefParseString(driver->caps, xml,
5192
                                        VIR_DOMAIN_XML_INACTIVE))) {
5193 5194
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to parse XML"));
5195
        goto cleanup;
5196 5197
    }

5198 5199
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
5200

5201
    if (!(vm = virDomainAssignDef(driver->caps,
5202 5203
                                  &driver->domains,
                                  def))) {
5204 5205
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to assign new VM"));
5206
        goto cleanup;
5207
    }
5208
    def = NULL;
5209

5210 5211 5212
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

5213 5214
    if (header.version == 2) {
        const char *intermediate_argv[3] = { NULL, "-dc", NULL };
5215 5216
        const char *prog = qemudSaveCompressionTypeToString(header.compressed);
        if (prog == NULL) {
5217 5218 5219
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("Invalid compressed save format %d"),
                            header.compressed);
5220
            goto endjob;
5221
        }
5222

5223
        if (header.compressed != QEMUD_SAVE_FORMAT_RAW) {
5224
            intermediate_argv[0] = prog;
5225 5226
            intermediatefd = fd;
            fd = -1;
5227
            if (virExec(intermediate_argv, NULL, NULL,
5228
                        &intermediate_pid, intermediatefd, &fd, NULL, 0) < 0) {
5229 5230 5231
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("Failed to start decompression binary %s"),
                                intermediate_argv[0]);
5232
                goto endjob;
5233 5234 5235
            }
        }
    }
5236
    /* Set the migration source and start it up. */
5237
    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
5238 5239 5240 5241 5242 5243 5244
    if (intermediate_pid != -1) {
        /* Wait for intermediate process to exit */
        while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
               errno == EINTR);
    }
    if (intermediatefd != -1)
        close(intermediatefd);
5245
    close(fd);
5246
    fd = -1;
5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275
    if (read_pid != -1) {
        int wait_ret;
        int status;
        /* reap the process that read the file */
        while (((wait_ret = waitpid(read_pid, &status, 0)) == -1)
               && (errno == EINTR)) {
            /* empty */
        }
        read_pid = -1;
        if (wait_ret == -1) {
            virReportSystemError(errno,
                                 _("failed to wait for process reading '%s'"),
                                 path);
            ret = -1;
        } else if (!WIFEXITED(status)) {
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("child process exited abnormally reading '%s'"),
                            path);
            ret = -1;
        } else {
            int exit_status = WEXITSTATUS(status);
            if (exit_status != 0) {
                virReportSystemError(exit_status,
                                     _("child process returned error reading '%s'"),
                                     path);
                ret = -1;
            }
        }
    }
5276
    if (ret < 0) {
5277
        if (!vm->persistent) {
5278 5279 5280
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains,
                                        vm);
5281 5282
            vm = NULL;
        }
5283
        goto endjob;
5284 5285
    }

5286 5287 5288
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
5289

5290 5291
    /* If it was running before, resume it now. */
    if (header.was_running) {
5292
        qemuDomainObjPrivatePtr priv = vm->privateData;
5293
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
5294
        if (qemuMonitorStartCPUs(priv->mon, conn) < 0) {
5295
            if (virGetLastError() == NULL)
5296 5297
                qemuReportError(VIR_ERR_OPERATION_FAILED,
                                "%s", _("failed to resume domain"));
5298 5299
            qemuDomainObjExitMonitorWithDriver(driver,vm);
            goto endjob;
5300
        }
5301
        qemuDomainObjExitMonitorWithDriver(driver, vm);
5302
        vm->state = VIR_DOMAIN_RUNNING;
5303
        virDomainSaveStatus(driver->caps, driver->stateDir, vm);
5304
    }
5305
    ret = 0;
5306

5307
endjob:
5308 5309 5310
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
5311

5312 5313 5314 5315 5316
cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
5317 5318 5319 5320 5321 5322 5323
    if (read_pid != 0) {
        /* reap the process that read the file */
        while ((waitpid(read_pid, NULL, 0) == -1)
               && (errno == EINTR)) {
            /* empty */
        }
    }
5324 5325
    if (vm)
        virDomainObjUnlock(vm);
5326 5327
    if (event)
        qemuDomainEventQueue(driver, event);
5328
    qemuDriverUnlock(driver);
5329
    return ret;
D
Daniel P. Berrange 已提交
5330 5331 5332
}


5333
static char *qemudDomainDumpXML(virDomainPtr dom,
5334
                                int flags) {
5335 5336 5337
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;
5338 5339
    unsigned long balloon;
    int err;
5340

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

D
Daniel P. Berrange 已提交
5345
    if (!vm) {
5346 5347
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
5348 5349
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
5350
        goto cleanup;
D
Daniel P. Berrange 已提交
5351 5352
    }

5353
    /* Refresh current memory based on balloon info */
D
Daniel P. Berrange 已提交
5354
    if (virDomainObjIsActive(vm)) {
5355
        qemuDomainObjPrivatePtr priv = vm->privateData;
5356 5357 5358 5359 5360 5361 5362 5363 5364
        /* Don't delay if someone's using the monitor, just use
         * existing most recent data instead */
        if (!priv->jobActive) {
            if (qemuDomainObjBeginJob(vm) < 0)
                goto cleanup;

            qemuDomainObjEnterMonitor(vm);
            err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
            qemuDomainObjExitMonitor(vm);
5365 5366 5367 5368
            if (qemuDomainObjEndJob(vm) == 0) {
                vm = NULL;
                goto cleanup;
            }
5369 5370 5371 5372 5373 5374
            if (err < 0)
                goto cleanup;
            if (err > 0)
                vm->def->memory = balloon;
            /* err == 0 indicates no balloon support, so ignore it */
        }
5375
    }
5376

5377
    ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
5378 5379 5380 5381
                             vm->newDef : vm->def,
                             flags);

cleanup:
5382 5383
    if (vm)
        virDomainObjUnlock(vm);
5384
    return ret;
D
Daniel P. Berrange 已提交
5385 5386 5387
}


5388 5389 5390 5391
static char *qemuDomainXMLFromNative(virConnectPtr conn,
                                     const char *format,
                                     const char *config,
                                     unsigned int flags ATTRIBUTE_UNUSED) {
5392
    struct qemud_driver *driver = conn->privateData;
5393 5394 5395 5396
    virDomainDefPtr def = NULL;
    char *xml = NULL;

    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
5397 5398
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("unsupported config type %s"), format);
5399 5400 5401
        goto cleanup;
    }

5402
    qemuDriverLock(driver);
5403
    def = qemuParseCommandLineString(driver->caps, config);
5404
    qemuDriverUnlock(driver);
5405 5406 5407
    if (!def)
        goto cleanup;

5408
    xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
5409 5410 5411 5412 5413 5414

cleanup:
    virDomainDefFree(def);
    return xml;
}

5415 5416 5417 5418 5419 5420
static char *qemuDomainXMLToNative(virConnectPtr conn,
                                   const char *format,
                                   const char *xmlData,
                                   unsigned int flags ATTRIBUTE_UNUSED) {
    struct qemud_driver *driver = conn->privateData;
    virDomainDefPtr def = NULL;
5421
    virDomainChrDef monConfig;
5422
    const char *emulator;
5423
    unsigned long long qemuCmdFlags;
5424 5425 5426 5427 5428 5429 5430 5431
    struct stat sb;
    const char **retargv = NULL;
    const char **retenv = NULL;
    const char **tmp;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *ret = NULL;
    int i;

5432 5433
    qemuDriverLock(driver);

5434
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
5435 5436
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("unsupported config type %s"), format);
5437 5438 5439
        goto cleanup;
    }

5440
    def = virDomainDefParseString(driver->caps, xmlData, 0);
5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484
    if (!def)
        goto cleanup;

    /* Since we're just exporting args, we can't do bridge/network
     * setups, since libvirt will normally create TAP devices
     * directly. We convert those configs into generic 'ethernet'
     * config and assume the user has suitable 'ifup-qemu' scripts
     */
    for (i = 0 ; i < def->nnets ; i++) {
        virDomainNetDefPtr net = def->nets[i];
        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
            VIR_FREE(net->data.network.name);

            memset(net, 0, sizeof *net);

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
            net->data.ethernet.dev = NULL;
            net->data.ethernet.script = NULL;
            net->data.ethernet.ipaddr = NULL;
        } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
            char *brname = net->data.bridge.brname;
            char *script = net->data.bridge.script;
            char *ipaddr = net->data.bridge.ipaddr;

            memset(net, 0, sizeof *net);

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
            net->data.ethernet.dev = brname;
            net->data.ethernet.script = script;
            net->data.ethernet.ipaddr = ipaddr;
        }
    }
    for (i = 0 ; i < def->ngraphics ; i++) {
        if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
            def->graphics[i]->data.vnc.autoport)
            def->graphics[i]->data.vnc.port = 5900;
    }
    emulator = def->emulator;

    /* 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
     */
    if (stat(emulator, &sb) < 0) {
5485
        virReportSystemError(errno,
5486 5487 5488 5489 5490 5491 5492 5493
                             _("Cannot find QEMU binary %s"),
                             emulator);
        goto cleanup;
    }

    if (qemudExtractVersionInfo(emulator,
                                NULL,
                                &qemuCmdFlags) < 0) {
5494 5495 5496
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot determine QEMU argv syntax %s"),
                        emulator);
5497 5498 5499
        goto cleanup;
    }

5500
    if (qemuPrepareMonitorChr(driver, &monConfig, def->name) < 0)
5501
        goto cleanup;
5502 5503

    if (qemudBuildCommandLine(conn, driver, def,
D
Daniel P. Berrange 已提交
5504
                              &monConfig, 0, qemuCmdFlags,
5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523
                              &retargv, &retenv,
                              NULL, NULL, /* Don't want it to create TAP devices */
                              NULL) < 0) {
        goto cleanup;
    }

    tmp = retenv;
    while (*tmp) {
        virBufferAdd(&buf, *tmp, strlen(*tmp));
        virBufferAddLit(&buf, " ");
        tmp++;
    }
    tmp = retargv;
    while (*tmp) {
        virBufferAdd(&buf, *tmp, strlen(*tmp));
        virBufferAddLit(&buf, " ");
        tmp++;
    }

5524 5525
    if (virBufferError(&buf)) {
        virBufferFreeAndReset(&buf);
5526
        virReportOOMError();
5527
        goto cleanup;
5528
    }
5529 5530 5531 5532

    ret = virBufferContentAndReset(&buf);

cleanup:
5533
    qemuDriverUnlock(driver);
5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546
    for (tmp = retargv ; tmp && *tmp ; tmp++)
        VIR_FREE(*tmp);
    VIR_FREE(retargv);

    for (tmp = retenv ; tmp && *tmp ; tmp++)
        VIR_FREE(*tmp);
    VIR_FREE(retenv);

    virDomainDefFree(def);
    return ret;
}


5547
static int qemudListDefinedDomains(virConnectPtr conn,
5548
                            char **const names, int nnames) {
5549
    struct qemud_driver *driver = conn->privateData;
5550
    int n;
5551

5552
    qemuDriverLock(driver);
5553
    n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
5554
    qemuDriverUnlock(driver);
5555
    return n;
D
Daniel P. Berrange 已提交
5556 5557
}

5558
static int qemudNumDefinedDomains(virConnectPtr conn) {
5559
    struct qemud_driver *driver = conn->privateData;
5560
    int n;
5561

5562
    qemuDriverLock(driver);
5563
    n = virDomainObjListNumOfDomains(&driver->domains, 0);
5564
    qemuDriverUnlock(driver);
5565

5566
    return n;
D
Daniel P. Berrange 已提交
5567 5568 5569
}


5570
static int qemudDomainStart(virDomainPtr dom) {
5571 5572 5573
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
5574
    virDomainEventPtr event = NULL;
5575

5576
    qemuDriverLock(driver);
5577
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
5578

5579
    if (!vm) {
5580 5581
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
5582 5583
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
5584
        goto cleanup;
5585 5586
    }

5587 5588 5589 5590
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

    if (virDomainObjIsActive(vm)) {
5591 5592
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is already running"));
5593 5594 5595
        goto endjob;
    }

5596
    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
5597
    if (ret != -1)
5598 5599 5600
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
5601

5602
endjob:
5603 5604
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
5605

5606
cleanup:
5607 5608
    if (vm)
        virDomainObjUnlock(vm);
5609
    if (event)
5610
        qemuDomainEventQueue(driver, event);
5611
    qemuDriverUnlock(driver);
5612
    return ret;
D
Daniel P. Berrange 已提交
5613 5614
}

5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629
static int
qemudCanonicalizeMachineFromInfo(virDomainDefPtr def,
                                 virCapsGuestDomainInfoPtr info,
                                 char **canonical)
{
    int i;

    *canonical = NULL;

    for (i = 0; i < info->nmachines; i++) {
        virCapsGuestMachinePtr machine = info->machines[i];

        if (!machine->canonical)
            continue;

5630
        if (STRNEQ(def->os.machine, machine->name))
5631 5632 5633
            continue;

        if (!(*canonical = strdup(machine->canonical))) {
5634
            virReportOOMError();
5635 5636 5637 5638 5639 5640 5641 5642 5643
            return -1;
        }

        break;
    }

    return 0;
}

5644 5645 5646 5647 5648 5649 5650
static int
qemudCanonicalizeMachineDirect(virDomainDefPtr def, char **canonical)
{
    virCapsGuestMachinePtr *machines = NULL;
    int i, nmachines = 0;

    if (qemudProbeMachineTypes(def->emulator, &machines, &nmachines) < 0) {
5651
        virReportOOMError();
5652 5653 5654 5655 5656 5657 5658
        return -1;
    }

    for (i = 0; i < nmachines; i++) {
        if (!machines[i]->canonical)
            continue;

5659
        if (STRNEQ(def->os.machine, machines[i]->name))
5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671
            continue;

        *canonical = machines[i]->canonical;
        machines[i]->canonical = NULL;
        break;
    }

    virCapabilitiesFreeMachines(machines, nmachines);

    return 0;
}

5672 5673
int
qemudCanonicalizeMachine(struct qemud_driver *driver, virDomainDefPtr def)
5674 5675 5676 5677 5678 5679
{
    char *canonical = NULL;
    int i;

    for (i = 0; i < driver->caps->nguests; i++) {
        virCapsGuestPtr guest = driver->caps->guests[i];
5680
        virCapsGuestDomainInfoPtr info;
5681 5682 5683
        int j;

        for (j = 0; j < guest->arch.ndomains; j++) {
5684
            info = &guest->arch.domains[j]->info;
5685

5686 5687 5688 5689 5690 5691 5692 5693 5694
            if (!info->emulator || !STREQ(info->emulator, def->emulator))
                continue;

            if (!info->nmachines)
                info = &guest->arch.defaultInfo;

            if (qemudCanonicalizeMachineFromInfo(def, info, &canonical) < 0)
                return -1;
            goto out;
5695 5696
        }

5697 5698 5699 5700
        info = &guest->arch.defaultInfo;

        if (info->emulator && STREQ(info->emulator, def->emulator)) {
            if (qemudCanonicalizeMachineFromInfo(def, info, &canonical) < 0)
5701 5702 5703 5704
                return -1;
            goto out;
        }
    }
5705 5706 5707 5708

    if (qemudCanonicalizeMachineDirect(def, &canonical) < 0)
        return -1;

5709 5710 5711 5712 5713 5714 5715
out:
    if (canonical) {
        VIR_FREE(def->os.machine);
        def->os.machine = canonical;
    }
    return 0;
}
D
Daniel P. Berrange 已提交
5716

5717
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
5718
    struct qemud_driver *driver = conn->privateData;
5719
    virDomainDefPtr def;
5720
    virDomainObjPtr vm = NULL;
5721
    virDomainPtr dom = NULL;
5722
    virDomainEventPtr event = NULL;
5723
    int dupVM;
5724

5725
    qemuDriverLock(driver);
5726
    if (!(def = virDomainDefParseString(driver->caps, xml,
5727
                                        VIR_DOMAIN_XML_INACTIVE)))
5728
        goto cleanup;
5729

5730
    if (virSecurityDriverVerify(def) < 0)
5731 5732
        goto cleanup;

5733 5734
    if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
        goto cleanup;
5735

5736
    if (qemudCanonicalizeMachine(driver, def) < 0)
5737 5738
        goto cleanup;

5739 5740 5741
    if (qemuAssignPCIAddresses(def) < 0)
        goto cleanup;

5742
    if (!(vm = virDomainAssignDef(driver->caps,
5743 5744
                                  &driver->domains,
                                  def))) {
5745
        goto cleanup;
5746
    }
5747
    def = NULL;
5748
    vm->persistent = 1;
5749

5750
    if (virDomainSaveConfig(driver->configDir,
5751
                            vm->newDef ? vm->newDef : vm->def) < 0) {
5752 5753
        virDomainRemoveInactive(&driver->domains,
                                vm);
5754
        vm = NULL;
5755
        goto cleanup;
5756 5757
    }

5758 5759
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
5760
                                     !dupVM ?
5761 5762
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
5763

5764
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
5765
    if (dom) dom->id = vm->def->id;
5766 5767

cleanup:
5768
    virDomainDefFree(def);
5769 5770
    if (vm)
        virDomainObjUnlock(vm);
5771 5772
    if (event)
        qemuDomainEventQueue(driver, event);
5773
    qemuDriverUnlock(driver);
5774
    return dom;
D
Daniel P. Berrange 已提交
5775 5776
}

5777
static int qemudDomainUndefine(virDomainPtr dom) {
5778 5779
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
5780
    virDomainEventPtr event = NULL;
5781
    int ret = -1;
D
Daniel P. Berrange 已提交
5782

5783
    qemuDriverLock(driver);
5784
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
5785

D
Daniel P. Berrange 已提交
5786
    if (!vm) {
5787 5788
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
5789 5790
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
5791
        goto cleanup;
D
Daniel P. Berrange 已提交
5792 5793
    }

D
Daniel P. Berrange 已提交
5794
    if (virDomainObjIsActive(vm)) {
5795 5796
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot delete active domain"));
5797
        goto cleanup;
D
Daniel P. Berrange 已提交
5798 5799
    }

5800
    if (!vm->persistent) {
5801 5802
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("cannot undefine transient domain"));
5803
        goto cleanup;
5804 5805
    }

5806
    if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0)
5807
        goto cleanup;
D
Daniel P. Berrange 已提交
5808

5809 5810 5811
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
5812

5813 5814
    virDomainRemoveInactive(&driver->domains,
                            vm);
5815
    vm = NULL;
5816
    ret = 0;
D
Daniel P. Berrange 已提交
5817

5818
cleanup:
5819 5820
    if (vm)
        virDomainObjUnlock(vm);
5821 5822
    if (event)
        qemuDomainEventQueue(driver, event);
5823
    qemuDriverUnlock(driver);
5824
    return ret;
D
Daniel P. Berrange 已提交
5825 5826
}

5827

5828
static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
5829
                                           virDomainObjPtr vm,
5830
                                           virDomainDiskDefPtr disk)
5831
{
5832
    virDomainDiskDefPtr origdisk = NULL;
5833
    int i;
5834
    int ret;
5835

5836
    origdisk = NULL;
5837
    for (i = 0 ; i < vm->def->ndisks ; i++) {
5838 5839
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
5840
            origdisk = vm->def->disks[i];
5841
            break;
5842
        }
5843 5844 5845
    }

    if (!origdisk) {
5846 5847 5848 5849
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("No device with bus '%s' and target '%s'"),
                        virDomainDiskBusTypeToString(disk->bus),
                        disk->dst);
5850 5851 5852
        return -1;
    }

5853
    if (!origdisk->info.alias) {
5854 5855
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("missing disk device alias name for %s"), origdisk->dst);
5856 5857
        return -1;
    }
5858

5859 5860
    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
        origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
5861 5862 5863
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Removable media not supported for %s device"),
                        virDomainDiskDeviceTypeToString(disk->device));
5864
        return -1;
5865
    }
5866

5867 5868
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
5869
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
5870 5871
        return -1;

5872
    qemuDomainObjPrivatePtr priv = vm->privateData;
5873
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5874
    if (disk->src) {
5875
        const char *format = NULL;
5876 5877 5878
        if (disk->type != VIR_DOMAIN_DISK_TYPE_DIR) {
            if (disk->driverType)
                format = disk->driverType;
5879 5880 5881
            else if (origdisk->driverType)
                format = origdisk->driverType;
        }
5882 5883
        ret = qemuMonitorChangeMedia(priv->mon,
                                     origdisk->info.alias,
5884
                                     disk->src, format);
5885
    } else {
5886
        ret = qemuMonitorEjectMedia(priv->mon, origdisk->info.alias);
5887
    }
5888
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5889

5890 5891 5892 5893 5894
    if (ret < 0)
        goto error;

    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5895
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, origdisk) < 0)
5896 5897 5898
        VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src);

    VIR_FREE(origdisk->src);
5899 5900 5901 5902 5903
    origdisk->src = disk->src;
    disk->src = NULL;
    origdisk->type = disk->type;

    virDomainDiskDefFree(disk);
5904

5905
    return ret;
5906 5907 5908 5909

error:
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5910
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
5911
        VIR_WARN("Unable to restore security label on new media %s", disk->src);
5912
    return -1;
5913 5914
}

5915

5916
static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver,
5917
                                          virDomainObjPtr vm,
5918 5919
                                          virDomainDiskDefPtr disk,
                                          int qemuCmdFlags)
5920
{
5921
    int i, ret;
5922
    const char* type = virDomainDiskBusTypeToString(disk->bus);
5923
    qemuDomainObjPrivatePtr priv = vm->privateData;
5924 5925
    char *devstr = NULL;
    char *drivestr = NULL;
5926 5927

    for (i = 0 ; i < vm->def->ndisks ; i++) {
5928
        if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
5929 5930
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s already exists"), disk->dst);
5931 5932 5933 5934
            return -1;
        }
    }

5935 5936
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
5937
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
5938 5939
        return -1;

5940
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
5941 5942
        if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0)
            goto error;
5943 5944
        if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0)
            goto error;
5945

5946 5947 5948
        if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
            goto error;

5949
        if (!(devstr = qemuBuildDriveDevStr(disk)))
5950 5951 5952
            goto error;
    }

5953
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
5954
        virReportOOMError();
5955
        goto error;
5956 5957
    }

5958
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        ret = qemuMonitorAddDrive(priv->mon, drivestr);
        if (ret == 0)
            qemuMonitorAddDevice(priv->mon, devstr);
            /* XXX remove the drive upon fail */
    } else {
        virDomainDevicePCIAddress guestAddr;
        ret = qemuMonitorAddPCIDisk(priv->mon,
                                    disk->src,
                                    type,
                                    &guestAddr);
        if (ret == 0) {
            disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
            memcpy(&disk->info.addr.pci, &guestAddr, sizeof(guestAddr));
        }
    }
5975
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5976

5977 5978
    if (ret < 0)
        goto error;
5979

5980
    virDomainDiskInsertPreAlloced(vm->def, disk);
5981

5982 5983 5984
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

5985 5986 5987
    return 0;

error:
5988 5989 5990
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

5991 5992 5993 5994 5995
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
        (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
        qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0)
        VIR_WARN("Unable to release PCI address on %s", disk->src);

5996 5997
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5998
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
5999
        VIR_WARN("Unable to restore security label on %s", disk->src);
6000 6001

    return -1;
6002
}
6003

6004

6005
static int qemudDomainAttachPciControllerDevice(struct qemud_driver *driver,
6006
                                                virDomainObjPtr vm,
6007 6008
                                                virDomainControllerDefPtr controller,
                                                int qemuCmdFlags)
6009
{
6010 6011
    int i;
    int ret = -1;
6012
    const char* type = virDomainControllerTypeToString(controller->type);
6013
    char *devstr = NULL;
6014 6015 6016
    qemuDomainObjPrivatePtr priv = vm->privateData;

    for (i = 0 ; i < vm->def->ncontrollers ; i++) {
6017 6018
        if ((vm->def->controllers[i]->type == controller->type) &&
            (vm->def->controllers[i]->idx == controller->idx)) {
6019 6020 6021
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s:%d already exists"),
                            type, controller->idx);
6022 6023 6024 6025
            return -1;
        }
    }

6026 6027 6028 6029 6030 6031
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0)
            goto cleanup;
        if (qemuAssignDeviceControllerAlias(controller) < 0)
            goto cleanup;
    }
6032

6033
    if (!(devstr = qemuBuildControllerDevStr(controller))) {
6034
        virReportOOMError();
6035 6036 6037
        goto cleanup;
    }

6038
    if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers+1) < 0) {
6039
        virReportOOMError();
6040
        goto cleanup;
6041 6042 6043
    }

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6044 6045 6046 6047 6048 6049 6050
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        ret = qemuMonitorAddDevice(priv->mon, devstr);
    } else {
        ret = qemuMonitorAttachPCIDiskController(priv->mon,
                                                 type,
                                                 &controller->info.addr.pci);
    }
6051 6052 6053
    qemuDomainObjExitMonitorWithDriver(driver, vm);

    if (ret == 0) {
6054 6055
        controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
        virDomainControllerInsertPreAlloced(vm->def, controller);
6056 6057
    }

6058
cleanup:
6059 6060 6061 6062 6063 6064
    if ((ret != 0) &&
        (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
        (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
        qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &controller->info) < 0)
        VIR_WARN0("Unable to release PCI address on controller");

6065
    VIR_FREE(devstr);
6066 6067 6068
    return ret;
}

6069

6070
static virDomainControllerDefPtr
6071
qemuDomainFindOrCreateSCSIDiskController(struct qemud_driver *driver,
6072
                                         virDomainObjPtr vm,
6073 6074
                                         int controller,
                                         int qemuCmdFlags)
6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087
{
    int i;
    virDomainControllerDefPtr cont;
    for (i = 0 ; i < vm->def->ncontrollers ; i++) {
        cont = vm->def->controllers[i];

        if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
            continue;

        if (cont->idx == controller)
            return cont;
    }

W
Wolfgang Mauerer 已提交
6088
    /* No SCSI controller present, for backward compatibility we
6089 6090
     * now hotplug a controller */
    if (VIR_ALLOC(cont) < 0) {
6091
        virReportOOMError();
6092 6093 6094 6095 6096 6097
        return NULL;
    }
    cont->type = VIR_DOMAIN_CONTROLLER_TYPE_SCSI;
    cont->idx = 0;

    VIR_INFO0("No SCSI controller present, hotplugging one");
6098
    if (qemudDomainAttachPciControllerDevice(driver,
6099
                                             vm, cont, qemuCmdFlags) < 0) {
6100 6101 6102 6103 6104 6105
        VIR_FREE(cont);
        return NULL;
    }
    return cont;
}

6106

6107
static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver,
6108
                                     virDomainObjPtr vm,
6109
                                     virDomainDiskDefPtr disk,
6110 6111 6112 6113 6114 6115
                                     int qemuCmdFlags)
{
    int i;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virDomainControllerDefPtr cont;
    char *drivestr = NULL;
6116
    char *devstr = NULL;
6117 6118 6119
    int ret = -1;

    for (i = 0 ; i < vm->def->ndisks ; i++) {
6120
        if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
6121 6122
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s already exists"), disk->dst);
6123
            return -1;
6124 6125 6126
        }
    }

6127 6128 6129

    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
6130
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
6131 6132
        return -1;

6133
    /* We should have an address already, so make sure */
6134
    if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
6135 6136 6137
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected disk address type %s"),
                        virDomainDeviceAddressTypeToString(disk->info.type));
6138
        goto error;
6139 6140
    }

6141 6142 6143
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0)
            goto error;
6144
        if (!(devstr = qemuBuildDriveDevStr(disk)))
6145 6146 6147 6148 6149 6150
            goto error;
    }

    if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
        goto error;

6151
    for (i = 0 ; i <= disk->info.addr.drive.controller ; i++) {
6152
        cont = qemuDomainFindOrCreateSCSIDiskController(driver, vm, i, qemuCmdFlags);
6153
        if (!cont)
6154
            goto error;
6155 6156 6157
    }

    if (cont->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
6158 6159
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("SCSI controller %d was missing its PCI address"), cont->idx);
6160
        goto error;
6161 6162 6163
    }

    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
6164
        virReportOOMError();
6165
        goto error;
6166 6167 6168
    }

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        ret = qemuMonitorAddDrive(priv->mon,
                                  drivestr);
        if (ret == 0)
            ret = qemuMonitorAddDevice(priv->mon,
                                       devstr);
            /* XXX should call 'drive_del' on error but this does not exist yet */
    } else {
        virDomainDeviceDriveAddress driveAddr;
        ret = qemuMonitorAttachDrive(priv->mon,
                                     drivestr,
                                     &cont->info.addr.pci,
                                     &driveAddr);
        if (ret == 0) {
            /* XXX we should probably validate that the addr matches
             * our existing defined addr instead of overwriting */
            disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
            memcpy(&disk->info.addr.drive, &driveAddr, sizeof(driveAddr));
        }
    }
6189 6190
    qemuDomainObjExitMonitorWithDriver(driver, vm);

6191 6192
    if (ret < 0)
        goto error;
6193

6194
    virDomainDiskInsertPreAlloced(vm->def, disk);
6195 6196

    VIR_FREE(devstr);
6197
    VIR_FREE(drivestr);
6198 6199 6200 6201

    return 0;

error:
6202
    VIR_FREE(devstr);
6203
    VIR_FREE(drivestr);
6204

6205 6206
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
6207
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
6208
        VIR_WARN("Unable to restore security label on %s", disk->src);
6209 6210

    return -1;
6211 6212
}

6213

6214
static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
6215
                                                 virDomainObjPtr vm,
6216 6217
                                                 virDomainDiskDefPtr disk,
                                                 int qemuCmdFlags)
6218
{
6219
    qemuDomainObjPrivatePtr priv = vm->privateData;
6220
    int i, ret;
6221 6222
    char *drivestr = NULL;
    char *devstr = NULL;
6223

6224
    for (i = 0 ; i < vm->def->ndisks ; i++) {
6225
        if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
6226 6227
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s already exists"), disk->dst);
6228 6229 6230 6231
            return -1;
        }
    }

6232 6233
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
6234
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
6235 6236
        return -1;

6237
    if (!disk->src) {
6238 6239
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("disk source path is missing"));
6240
        goto error;
6241 6242
    }

6243
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
6244 6245
        if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0)
            goto error;
6246 6247
        if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
            goto error;
6248
        if (!(devstr = qemuBuildDriveDevStr(disk)))
6249 6250 6251
            goto error;
    }

6252
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
6253
        virReportOOMError();
6254
        goto error;
6255 6256
    }

6257
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6258 6259 6260 6261 6262 6263 6264 6265 6266 6267
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        ret = qemuMonitorAddDrive(priv->mon,
                                  drivestr);
        if (ret == 0)
            ret = qemuMonitorAddDevice(priv->mon,
                                       devstr);
            /* XXX should call 'drive_del' on error but this does not exist yet */
    } else {
        ret = qemuMonitorAddUSBDisk(priv->mon, disk->src);
    }
6268
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6269

6270 6271 6272
    if (ret < 0)
        goto error;

6273
    virDomainDiskInsertPreAlloced(vm->def, disk);
6274

6275 6276 6277
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

6278 6279 6280
    return 0;

error:
6281 6282 6283
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

6284 6285
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
6286
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
6287
        VIR_WARN("Unable to restore security label on %s", disk->src);
6288 6289

    return -1;
6290 6291
}

6292

6293
/* XXX conn required for network -> bridge resolution */
M
Mark McLoughlin 已提交
6294
static int qemudDomainAttachNetDevice(virConnectPtr conn,
6295
                                      struct qemud_driver *driver,
M
Mark McLoughlin 已提交
6296
                                      virDomainObjPtr vm,
6297
                                      virDomainNetDefPtr net,
6298
                                      unsigned long long qemuCmdFlags)
M
Mark McLoughlin 已提交
6299
{
6300
    qemuDomainObjPrivatePtr priv = vm->privateData;
6301
    char *tapfd_name = NULL;
6302
    int tapfd = -1;
6303
    char *nicstr = NULL;
6304
    char *netstr = NULL;
6305
    int ret = -1;
6306
    virDomainDevicePCIAddress guestAddr;
6307
    int vlan;
M
Mark McLoughlin 已提交
6308 6309

    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_HOST_NET_ADD)) {
6310 6311
        qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
                        _("installed qemu version does not support host_net_add"));
M
Mark McLoughlin 已提交
6312 6313 6314 6315 6316
        return -1;
    }

    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
        net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
6317
        if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
6318 6319 6320 6321
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("network device type '%s' cannot be attached: "
                              "qemu is not using a unix socket monitor"),
                            virDomainNetTypeToString(net->type));
6322 6323 6324 6325 6326
            return -1;
        }

        if ((tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags)) < 0)
            return -1;
6327 6328 6329 6330 6331 6332 6333 6334 6335
    } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
        if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("network device type '%s' cannot be attached: "
                            "qemu is not using a unix socket monitor"),
                            virDomainNetTypeToString(net->type));
            return -1;
        }

S
Stefan Berger 已提交
6336
        if ((tapfd = qemudPhysIfaceConnect(conn, driver, net,
6337
                                           net->data.direct.linkdev,
6338 6339
                                           net->data.direct.mode,
                                           qemuCmdFlags)) < 0)
6340
            return -1;
M
Mark McLoughlin 已提交
6341 6342
    }

6343 6344
    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0)
        goto no_memory;
M
Mark McLoughlin 已提交
6345

6346 6347 6348 6349 6350
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NET_NAME) ||
        (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
        if (qemuAssignDeviceNetAlias(vm->def, net, -1) < 0)
            goto cleanup;
    }
M
Mark McLoughlin 已提交
6351

6352 6353 6354 6355
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
        qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0)
        goto cleanup;

6356
    vlan = qemuDomainNetVLAN(net);
M
Mark McLoughlin 已提交
6357

6358
    if (vlan < 0) {
6359 6360
        qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
                        _("Unable to attach network devices without vlan"));
6361 6362 6363
        goto cleanup;
    }

6364
    if (tapfd != -1) {
6365
        if (virAsprintf(&tapfd_name, "fd-%s", net->info.alias) < 0)
6366 6367
            goto no_memory;

6368
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
6369
        if (qemuMonitorSendFileHandle(priv->mon, tapfd_name, tapfd) < 0) {
6370
            qemuDomainObjExitMonitorWithDriver(driver, vm);
6371
            goto cleanup;
6372
        }
6373
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6374 6375
    }

6376
    /* FIXME - need to support vhost-net here (5th arg) */
6377
    if (!(netstr = qemuBuildHostNetStr(net, ' ',
6378
                                       vlan, tapfd_name, 0)))
6379
        goto try_tapfd_close;
M
Mark McLoughlin 已提交
6380

6381
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6382
    if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) {
6383
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6384
        goto try_tapfd_close;
6385
    }
6386
    qemuDomainObjExitMonitorWithDriver(driver, vm);
M
Mark McLoughlin 已提交
6387

6388 6389 6390
    if (tapfd != -1)
        close(tapfd);
    tapfd = -1;
M
Mark McLoughlin 已提交
6391

6392
    if (!(nicstr = qemuBuildNicStr(net, NULL, vlan)))
6393
        goto try_remove;
M
Mark McLoughlin 已提交
6394

6395
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6396
    if (qemuMonitorAddPCINetwork(priv->mon, nicstr,
6397
                                 &guestAddr) < 0) {
6398
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6399
        goto try_remove;
6400
    }
6401
    net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
6402
    memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr));
6403
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6404

6405
    ret = 0;
M
Mark McLoughlin 已提交
6406 6407 6408

    vm->def->nets[vm->def->nnets++] = net;

6409
cleanup:
6410 6411 6412 6413 6414 6415
    if ((ret != 0) &&
        (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
        (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
        qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0)
        VIR_WARN0("Unable to release PCI address on NIC");

6416 6417 6418 6419 6420
    VIR_FREE(nicstr);
    VIR_FREE(netstr);
    VIR_FREE(tapfd_name);
    if (tapfd != -1)
        close(tapfd);
6421

6422
    return ret;
6423

6424
try_remove:
6425
    if (vlan < 0) {
6426
        VIR_WARN0(_("Unable to remove network backend"));
6427 6428 6429 6430
    } else {
        char *hostnet_name;
        if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0)
            goto no_memory;
6431
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
6432
        if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0)
6433
            VIR_WARN(_("Failed to remove network backend for vlan %d, net %s"),
6434
                     vlan, hostnet_name);
6435
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6436
        VIR_FREE(hostnet_name);
6437
    }
6438
    goto cleanup;
6439

6440
try_tapfd_close:
6441
    if (tapfd_name) {
6442
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
6443
        if (qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0)
6444
            VIR_WARN(_("Failed to close tapfd with '%s'"), tapfd_name);
6445
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6446
    }
6447

6448 6449
    goto cleanup;

6450
no_memory:
6451
    virReportOOMError();
6452
    goto cleanup;
M
Mark McLoughlin 已提交
6453 6454
}

6455

6456
static int qemudDomainAttachHostPciDevice(struct qemud_driver *driver,
6457
                                          virDomainObjPtr vm,
6458 6459
                                          virDomainHostdevDefPtr hostdev,
                                          int qemuCmdFlags)
6460
{
6461
    qemuDomainObjPrivatePtr priv = vm->privateData;
6462
    pciDevice *pci;
6463
    int ret;
6464
    virDomainDevicePCIAddress guestAddr;
6465
    char *devstr = NULL;
6466 6467

    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
6468
        virReportOOMError();
6469 6470 6471
        return -1;
    }

6472
    pci = pciGetDevice(hostdev->source.subsys.u.pci.domain,
6473 6474 6475
                       hostdev->source.subsys.u.pci.bus,
                       hostdev->source.subsys.u.pci.slot,
                       hostdev->source.subsys.u.pci.function);
6476
    if (!pci)
6477
        return -1;
6478

6479 6480 6481 6482
    if (!pciDeviceIsAssignable(pci, !driver->relaxedACS) ||
        (hostdev->managed && pciDettachDevice(pci) < 0) ||
        pciResetDevice(pci, driver->activePciHostdevs) < 0) {
        pciFreeDevice(pci);
6483 6484 6485
        return -1;
    }

6486 6487
    if (pciDeviceListAdd(driver->activePciHostdevs, pci) < 0) {
        pciFreeDevice(pci);
6488
        return -1;
6489 6490
    }

6491
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
6492 6493
        if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
            goto error;
6494 6495 6496 6497 6498 6499
        if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &hostdev->info) < 0)
            goto error;

        if (!(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
            goto error;
    }
6500

6501
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6502 6503 6504 6505 6506 6507
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
        ret = qemuMonitorAddDevice(priv->mon, devstr);
    else
        ret = qemuMonitorAddPCIHostDevice(priv->mon,
                                          &hostdev->source.subsys.u.pci,
                                          &guestAddr);
6508
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6509
    if (ret < 0)
6510
        goto error;
6511
    hostdev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
6512
    memcpy(&hostdev->info.addr.pci, &guestAddr, sizeof(guestAddr));
6513 6514 6515

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;

6516 6517
    VIR_FREE(devstr);

6518
    return 0;
6519 6520

error:
6521 6522 6523 6524 6525
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
        (hostdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
        qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &hostdev->info) < 0)
        VIR_WARN0("Unable to release PCI address on host device");

6526
    VIR_FREE(devstr);
6527
    pciDeviceListDel(driver->activePciHostdevs, pci);
6528 6529

    return -1;
6530 6531
}

6532

6533
static int qemudDomainAttachHostUsbDevice(struct qemud_driver *driver,
M
Mark McLoughlin 已提交
6534
                                          virDomainObjPtr vm,
6535 6536
                                          virDomainHostdevDefPtr hostdev,
                                          int qemuCmdFlags)
6537 6538
{
    int ret;
6539
    qemuDomainObjPrivatePtr priv = vm->privateData;
6540 6541
    char *devstr = NULL;

6542 6543 6544 6545 6546 6547
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
            goto error;
        if (!(devstr = qemuBuildUSBHostdevDevStr(hostdev)))
            goto error;
    }
6548

6549
    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
6550
        virReportOOMError();
6551
        goto error;
6552
    }
6553

6554
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6555 6556 6557
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
        ret = qemuMonitorAddDevice(priv->mon, devstr);
    else
6558
        ret = qemuMonitorAddUSBDeviceExact(priv->mon,
6559 6560
                                           hostdev->source.subsys.u.usb.bus,
                                           hostdev->source.subsys.u.usb.device);
6561
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6562 6563 6564 6565
    if (ret < 0)
        goto error;

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
6566

6567
    VIR_FREE(devstr);
6568

6569 6570 6571 6572 6573
    return 0;

error:
    VIR_FREE(devstr);
    return -1;
6574 6575
}

6576

6577
static int qemudDomainAttachHostDevice(struct qemud_driver *driver,
M
Mark McLoughlin 已提交
6578
                                       virDomainObjPtr vm,
6579 6580
                                       virDomainHostdevDefPtr hostdev,
                                       int qemuCmdFlags)
M
Mark McLoughlin 已提交
6581 6582
{
    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
6583 6584 6585
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev mode '%s' not supported"),
                        virDomainHostdevModeTypeToString(hostdev->mode));
M
Mark McLoughlin 已提交
6586 6587 6588
        return -1;
    }

6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605
    /* Resolve USB product/vendor to bus/device */
    if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
        hostdev->source.subsys.u.usb.vendor) {
        usbDevice *usb
            = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
                            hostdev->source.subsys.u.usb.product);

        if (!usb)
            return -1;

        hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
        hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);

        usbFreeDevice(usb);
    }


6606
    if (driver->securityDriver &&
6607
        driver->securityDriver->domainSetSecurityHostdevLabel &&
6608
        driver->securityDriver->domainSetSecurityHostdevLabel(vm, hostdev) < 0)
6609
        return -1;
M
Mark McLoughlin 已提交
6610 6611

    switch (hostdev->source.subsys.type) {
6612
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
6613
        if (qemudDomainAttachHostPciDevice(driver, vm,
6614
                                           hostdev, qemuCmdFlags) < 0)
6615 6616 6617
            goto error;
        break;

M
Mark McLoughlin 已提交
6618
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
6619
        if (qemudDomainAttachHostUsbDevice(driver, vm,
6620
                                           hostdev, qemuCmdFlags) < 0)
6621 6622 6623
            goto error;
        break;

M
Mark McLoughlin 已提交
6624
    default:
6625 6626 6627
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev subsys type '%s' not supported"),
                        virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
6628
        goto error;
M
Mark McLoughlin 已提交
6629
    }
6630 6631 6632 6633 6634 6635

    return 0;

error:
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityHostdevLabel &&
6636
        driver->securityDriver->domainRestoreSecurityHostdevLabel(vm, hostdev) < 0)
6637 6638 6639
        VIR_WARN0("Unable to restore host device labelling on hotplug fail");

    return -1;
M
Mark McLoughlin 已提交
6640 6641
}

6642

6643
static int qemudDomainAttachDevice(virDomainPtr dom,
6644 6645
                                   const char *xml)
{
6646 6647 6648
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
6649
    unsigned long long qemuCmdFlags;
6650
    virCgroupPtr cgroup = NULL;
6651
    int ret = -1;
6652

6653
    qemuDriverLock(driver);
6654
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6655
    if (!vm) {
6656 6657
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
6658 6659
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6660
        goto cleanup;
6661 6662
    }

6663 6664 6665
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
6666
    if (!virDomainObjIsActive(vm)) {
6667 6668
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot attach device on inactive domain"));
6669
        goto endjob;
6670 6671
    }

6672
    dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
6673
                                  VIR_DOMAIN_XML_INACTIVE);
6674
    if (dev == NULL)
6675
        goto endjob;
6676

6677 6678 6679
    if (qemudExtractVersionInfo(vm->def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0)
6680
        goto endjob;
6681

6682
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
6683
        if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
6684
            if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) {
6685 6686 6687
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("Unable to find cgroup for %s\n"),
                                vm->def->name);
6688
                goto endjob;
6689 6690 6691 6692 6693
            }
            if (dev->data.disk->src != NULL &&
                dev->data.disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
                virCgroupAllowDevicePath(cgroup,
                                         dev->data.disk->src) < 0) {
6694 6695 6696
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unable to allow device %s"),
                                dev->data.disk->src);
6697
                goto endjob;
6698 6699 6700
            }
        }

6701
        switch (dev->data.disk->device) {
6702 6703
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
        case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
6704
            ret = qemudDomainChangeEjectableMedia(driver, vm, dev->data.disk);
6705 6706
            if (ret == 0)
                dev->data.disk = NULL;
6707
            break;
6708

6709 6710
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
6711
                ret = qemudDomainAttachUsbMassstorageDevice(driver, vm,
6712
                                                            dev->data.disk, qemuCmdFlags);
6713 6714
                if (ret == 0)
                    dev->data.disk = NULL;
6715
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
6716
                ret = qemudDomainAttachPciDiskDevice(driver, vm,
6717
                                                     dev->data.disk, qemuCmdFlags);
6718 6719
                if (ret == 0)
                    dev->data.disk = NULL;
6720
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
6721
                ret = qemudDomainAttachSCSIDisk(driver, vm,
6722
                                                dev->data.disk, qemuCmdFlags);
6723 6724
                if (ret == 0)
                    dev->data.disk = NULL;
6725
            } else {
6726 6727 6728
                qemuReportError(VIR_ERR_NO_SUPPORT,
                                _("disk bus '%s' cannot be hotplugged."),
                                virDomainDiskBusTypeToString(dev->data.disk->bus));
6729
                /* fallthrough */
6730 6731
            }
            break;
6732

6733
        default:
6734 6735 6736
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("disk device type '%s' cannot be hotplugged"),
                            virDomainDiskDeviceTypeToString(dev->data.disk->device));
6737 6738
            /* Fallthrough */
        }
6739
        if (ret != 0 && cgroup) {
6740 6741
            virCgroupDenyDevicePath(cgroup,
                                    dev->data.disk->src);
6742
        }
6743 6744
    } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) {
        if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
6745
            ret = qemudDomainAttachPciControllerDevice(driver, vm,
6746
                                                       dev->data.controller, qemuCmdFlags);
6747 6748
            if (ret == 0)
                dev->data.controller = NULL;
6749
        } else {
6750 6751 6752
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("disk controller bus '%s' cannot be hotplugged."),
                            virDomainControllerTypeToString(dev->data.controller->type));
6753 6754
            /* fallthrough */
        }
M
Mark McLoughlin 已提交
6755
    } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
6756 6757
        ret = qemudDomainAttachNetDevice(dom->conn, driver, vm,
                                         dev->data.net, qemuCmdFlags);
6758 6759
        if (ret == 0)
            dev->data.net = NULL;
M
Mark McLoughlin 已提交
6760
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
6761
        ret = qemudDomainAttachHostDevice(driver, vm,
6762
                                          dev->data.hostdev, qemuCmdFlags);
6763 6764
        if (ret == 0)
            dev->data.hostdev = NULL;
6765
    } else {
6766 6767 6768
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("device type '%s' cannot be attached"),
                        virDomainDeviceTypeToString(dev->type));
6769
        goto endjob;
6770 6771
    }

6772
    if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
6773 6774
        ret = -1;

6775
endjob:
6776 6777
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
6778

6779
cleanup:
6780 6781 6782
    if (cgroup)
        virCgroupFree(&cgroup);

6783
    virDomainDeviceDefFree(dev);
6784 6785
    if (vm)
        virDomainObjUnlock(vm);
6786
    qemuDriverUnlock(driver);
6787 6788 6789
    return ret;
}

6790 6791 6792 6793
static int qemudDomainAttachDeviceFlags(virDomainPtr dom,
                                        const char *xml,
                                        unsigned int flags) {
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
6794 6795
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify the persistent configuration of a domain"));
6796 6797 6798 6799 6800 6801
        return -1;
    }

    return qemudDomainAttachDevice(dom, xml);
}

6802
static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
6803
                                          virDomainObjPtr vm,
6804 6805
                                          virDomainDeviceDefPtr dev,
                                          unsigned long long qemuCmdFlags)
6806 6807 6808
{
    int i, ret = -1;
    virDomainDiskDefPtr detach = NULL;
6809
    qemuDomainObjPrivatePtr priv = vm->privateData;
6810 6811 6812 6813 6814 6815 6816 6817 6818

    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) {
6819 6820
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("disk %s not found"), dev->data.disk->dst);
6821
        goto cleanup;
6822 6823
    }

6824 6825
    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
6826 6827
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                        _("device cannot be detached without a PCI address"));
6828
        goto cleanup;
6829 6830
    }

6831
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
            qemuDomainObjExitMonitor(vm);
            goto cleanup;
        }
    } else {
        if (qemuMonitorRemovePCIDevice(priv->mon,
                                       &detach->info.addr.pci) < 0) {
            qemuDomainObjExitMonitor(vm);
            goto cleanup;
        }
6843
    }
6844
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6845

6846 6847 6848 6849 6850 6851 6852 6853 6854 6855
    if (vm->def->ndisks > 1) {
        memmove(vm->def->disks + i,
                vm->def->disks + i + 1,
                sizeof(*vm->def->disks) *
                (vm->def->ndisks - (i + 1)));
        vm->def->ndisks--;
        if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
            /* ignore, harmless */
        }
    } else {
6856
        VIR_FREE(vm->def->disks);
6857
        vm->def->ndisks = 0;
6858
    }
6859
    virDomainDiskDefFree(detach);
6860

6861 6862
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
6863
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0)
6864 6865
        VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);

6866
    ret = 0;
6867 6868

cleanup:
6869 6870 6871
    return ret;
}

6872
static int qemudDomainDetachPciControllerDevice(struct qemud_driver *driver,
6873
                                                virDomainObjPtr vm,
6874 6875
                                                virDomainDeviceDefPtr dev,
                                                unsigned long long qemuCmdFlags)
6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889
{
    int i, ret = -1;
    virDomainControllerDefPtr detach = NULL;
    qemuDomainObjPrivatePtr priv = vm->privateData;

    for (i = 0 ; i < vm->def->ncontrollers ; i++) {
        if ((vm->def->controllers[i]->type == dev->data.controller->type) &&
            (vm->def->controllers[i]->idx == dev->data.controller->idx)) {
            detach = vm->def->controllers[i];
            break;
        }
    }

    if (!detach) {
6890 6891 6892 6893
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("disk controller %s:%d not found"),
                        virDomainControllerTypeToString(dev->data.controller->type),
                        dev->data.controller->idx);
6894 6895 6896 6897 6898
        goto cleanup;
    }

    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
6899 6900
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                        _("device cannot be detached without a PCI address"));
6901 6902 6903
        goto cleanup;
    }

6904 6905 6906 6907 6908
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuAssignDeviceControllerAlias(detach) < 0)
            goto cleanup;
    }

6909
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
            qemuDomainObjExitMonitor(vm);
            goto cleanup;
        }
    } else {
        if (qemuMonitorRemovePCIDevice(priv->mon,
                                       &detach->info.addr.pci) < 0) {
            qemuDomainObjExitMonitor(vm);
            goto cleanup;
        }
6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936
    }
    qemuDomainObjExitMonitorWithDriver(driver, vm);

    if (vm->def->ncontrollers > 1) {
        memmove(vm->def->controllers + i,
                vm->def->controllers + i + 1,
                sizeof(*vm->def->controllers) *
                (vm->def->ncontrollers - (i + 1)));
        vm->def->ncontrollers--;
        if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers) < 0) {
            /* ignore, harmless */
        }
    } else {
        VIR_FREE(vm->def->controllers);
        vm->def->ncontrollers = 0;
    }
6937 6938 6939 6940 6941

    if (qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0) {
        VIR_WARN0("Unable to release PCI address on controller");
    }

6942 6943 6944 6945 6946 6947 6948 6949
    virDomainControllerDefFree(detach);

    ret = 0;

cleanup:
    return ret;
}

6950
static int
6951
qemudDomainDetachNetDevice(struct qemud_driver *driver,
6952
                           virDomainObjPtr vm,
6953 6954
                           virDomainDeviceDefPtr dev,
                           unsigned long long qemuCmdFlags)
6955 6956 6957
{
    int i, ret = -1;
    virDomainNetDefPtr detach = NULL;
6958
    qemuDomainObjPrivatePtr priv = vm->privateData;
6959 6960
    int vlan;
    char *hostnet_name = NULL;
6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971

    for (i = 0 ; i < vm->def->nnets ; i++) {
        virDomainNetDefPtr net = vm->def->nets[i];

        if (!memcmp(net->mac, dev->data.net->mac,  sizeof(net->mac))) {
            detach = net;
            break;
        }
    }

    if (!detach) {
6972 6973 6974 6975 6976
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("network device %02x:%02x:%02x:%02x:%02x:%02x not found"),
                        dev->data.net->mac[0], dev->data.net->mac[1],
                        dev->data.net->mac[2], dev->data.net->mac[3],
                        dev->data.net->mac[4], dev->data.net->mac[5]);
6977 6978 6979
        goto cleanup;
    }

6980 6981
    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
6982 6983
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("device cannot be detached without a PCI address"));
6984 6985 6986
        goto cleanup;
    }

6987
    if ((vlan = qemuDomainNetVLAN(detach)) < 0) {
6988 6989
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("unable to determine original VLAN"));
6990 6991 6992 6993
        goto cleanup;
    }

    if (virAsprintf(&hostnet_name, "host%s", detach->info.alias) < 0) {
6994
        virReportOOMError();
6995 6996 6997
        goto cleanup;
    }

6998
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
            qemuDomainObjExitMonitor(vm);
            goto cleanup;
        }
    } else {
        if (qemuMonitorRemovePCIDevice(priv->mon,
                                       &detach->info.addr.pci) < 0) {
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            goto cleanup;
        }
7010
    }
7011

7012
    if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) {
7013
        qemuDomainObjExitMonitorWithDriver(driver, vm);
7014
        goto cleanup;
7015
    }
7016
    qemuDomainObjExitMonitorWithDriver(driver, vm);
7017

7018 7019
#if WITH_MACVTAP
    if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
S
Stefan Berger 已提交
7020 7021
        if (detach->ifname)
            delMacvtap(detach->ifname);
7022 7023 7024
    }
#endif

7025
    if ((driver->macFilter) && (detach->ifname != NULL)) {
7026
        if ((errno = networkDisallowMacOnPort(driver,
7027 7028
                                              detach->ifname,
                                              detach->mac))) {
7029
            virReportSystemError(errno,
7030 7031 7032 7033 7034
             _("failed to remove ebtables rule on  '%s'"),
                                 detach->ifname);
        }
    }

7035 7036 7037 7038 7039 7040 7041 7042 7043 7044
    if (vm->def->nnets > 1) {
        memmove(vm->def->nets + i,
                vm->def->nets + i + 1,
                sizeof(*vm->def->nets) *
                (vm->def->nnets - (i + 1)));
        vm->def->nnets--;
        if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets) < 0) {
            /* ignore, harmless */
        }
    } else {
7045
        VIR_FREE(vm->def->nets);
7046
        vm->def->nnets = 0;
7047
    }
7048
    virDomainNetDefFree(detach);
7049

7050 7051 7052
    ret = 0;

cleanup:
7053
    VIR_FREE(hostnet_name);
7054 7055 7056
    return ret;
}

7057
static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver,
7058
                                          virDomainObjPtr vm,
7059 7060
                                          virDomainDeviceDefPtr dev,
                                          unsigned long long qemuCmdFlags)
7061
{
7062
    virDomainHostdevDefPtr detach = NULL;
7063
    qemuDomainObjPrivatePtr priv = vm->privateData;
7064
    int i, ret;
7065
    pciDevice *pci;
7066 7067

    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
7068 7069 7070 7071
        if (vm->def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
            vm->def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086
        unsigned domain   = vm->def->hostdevs[i]->source.subsys.u.pci.domain;
        unsigned bus      = vm->def->hostdevs[i]->source.subsys.u.pci.bus;
        unsigned slot     = vm->def->hostdevs[i]->source.subsys.u.pci.slot;
        unsigned function = vm->def->hostdevs[i]->source.subsys.u.pci.function;

        if (dev->data.hostdev->source.subsys.u.pci.domain   == domain &&
            dev->data.hostdev->source.subsys.u.pci.bus      == bus &&
            dev->data.hostdev->source.subsys.u.pci.slot     == slot &&
            dev->data.hostdev->source.subsys.u.pci.function == function) {
            detach = vm->def->hostdevs[i];
            break;
        }
    }

    if (!detach) {
7087 7088 7089 7090 7091 7092
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("host pci device %.4x:%.2x:%.2x.%.1x not found"),
                        dev->data.hostdev->source.subsys.u.pci.domain,
                        dev->data.hostdev->source.subsys.u.pci.bus,
                        dev->data.hostdev->source.subsys.u.pci.slot,
                        dev->data.hostdev->source.subsys.u.pci.function);
7093 7094 7095
        return -1;
    }

7096 7097
    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
7098 7099
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("device cannot be detached without a PCI address"));
7100 7101 7102
        return -1;
    }

7103
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
            qemuDomainObjExitMonitor(vm);
            return -1;
        }
    } else {
        if (qemuMonitorRemovePCIDevice(priv->mon,
                                       &detach->info.addr.pci) < 0) {
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            return -1;
        }
7115
    }
7116
    qemuDomainObjExitMonitorWithDriver(driver, vm);
7117 7118 7119

    ret = 0;

7120
    pci = pciGetDevice(detach->source.subsys.u.pci.domain,
7121 7122 7123 7124 7125 7126
                       detach->source.subsys.u.pci.bus,
                       detach->source.subsys.u.pci.slot,
                       detach->source.subsys.u.pci.function);
    if (!pci)
        ret = -1;
    else {
7127
        pciDeviceSetManaged(pci, detach->managed);
7128 7129
        pciDeviceListDel(driver->activePciHostdevs, pci);
        if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
7130
            ret = -1;
7131
        qemudReattachManagedDevice(pci);
7132
        pciFreeDevice(pci);
7133 7134
    }

7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146
    if (vm->def->nhostdevs > 1) {
        memmove(vm->def->hostdevs + i,
                vm->def->hostdevs + i + 1,
                sizeof(*vm->def->hostdevs) *
                (vm->def->nhostdevs - (i + 1)));
        vm->def->nhostdevs--;
        if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs) < 0) {
            /* ignore, harmless */
        }
    } else {
        VIR_FREE(vm->def->hostdevs);
        vm->def->nhostdevs = 0;
7147
    }
7148
    virDomainHostdevDefFree(detach);
7149 7150 7151 7152

    return ret;
}

7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168
static int qemudDomainDetachHostUsbDevice(struct qemud_driver *driver,
                                          virDomainObjPtr vm,
                                          virDomainDeviceDefPtr dev,
                                          unsigned long long qemuCmdFlags)
{
    virDomainHostdevDefPtr detach = NULL;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int i, ret;

    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
        if (vm->def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
            vm->def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
            continue;

        unsigned bus = vm->def->hostdevs[i]->source.subsys.u.usb.bus;
        unsigned device = vm->def->hostdevs[i]->source.subsys.u.usb.device;
7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184
        unsigned product = vm->def->hostdevs[i]->source.subsys.u.usb.product;
        unsigned vendor = vm->def->hostdevs[i]->source.subsys.u.usb.vendor;

        if (dev->data.hostdev->source.subsys.u.usb.bus &&
            dev->data.hostdev->source.subsys.u.usb.device) {
            if (dev->data.hostdev->source.subsys.u.usb.bus == bus &&
                dev->data.hostdev->source.subsys.u.usb.device == device) {
                detach = vm->def->hostdevs[i];
                break;
            }
        } else {
            if (dev->data.hostdev->source.subsys.u.usb.product == product &&
                dev->data.hostdev->source.subsys.u.usb.vendor == vendor) {
                detach = vm->def->hostdevs[i];
                break;
            }
7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234
        }
    }

    if (!detach) {
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("host usb device %03d.%03d not found"),
                        dev->data.hostdev->source.subsys.u.usb.bus,
                        dev->data.hostdev->source.subsys.u.usb.device);
        return -1;
    }

    if (!detach->info.alias) {
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("device cannot be detached without a device alias"));
        return -1;
    }

    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("device cannot be detached with this QEMU version"));
        return -1;
    }

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
    if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
        qemuDomainObjExitMonitorWithDriver(driver, vm);
        return -1;
    }
    qemuDomainObjExitMonitorWithDriver(driver, vm);

    ret = 0;

    if (vm->def->nhostdevs > 1) {
        memmove(vm->def->hostdevs + i,
                vm->def->hostdevs + i + 1,
                sizeof(*vm->def->hostdevs) *
                (vm->def->nhostdevs - (i + 1)));
        vm->def->nhostdevs--;
        if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs) < 0) {
            /* ignore, harmless */
        }
    } else {
        VIR_FREE(vm->def->hostdevs);
        vm->def->nhostdevs = 0;
    }
    virDomainHostdevDefFree(detach);

    return ret;
}

7235
static int qemudDomainDetachHostDevice(struct qemud_driver *driver,
7236
                                       virDomainObjPtr vm,
7237 7238
                                       virDomainDeviceDefPtr dev,
                                       unsigned long long qemuCmdFlags)
7239 7240 7241 7242 7243
{
    virDomainHostdevDefPtr hostdev = dev->data.hostdev;
    int ret;

    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
7244 7245 7246
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev mode '%s' not supported"),
                        virDomainHostdevModeTypeToString(hostdev->mode));
7247 7248 7249 7250 7251
        return -1;
    }

    switch (hostdev->source.subsys.type) {
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
7252
        ret = qemudDomainDetachHostPciDevice(driver, vm, dev, qemuCmdFlags);
7253
        break;
7254 7255 7256
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
        ret = qemudDomainDetachHostUsbDevice(driver, vm, dev, qemuCmdFlags);
        break;
7257
    default:
7258 7259 7260
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev subsys type '%s' not supported"),
                        virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
7261 7262 7263
        return -1;
    }

7264
    if (driver->securityDriver &&
7265
        driver->securityDriver->domainRestoreSecurityHostdevLabel &&
7266
        driver->securityDriver->domainRestoreSecurityHostdevLabel(vm, dev->data.hostdev) < 0)
7267
        VIR_WARN0("Failed to restore host device labelling");
7268

7269 7270 7271
    return ret;
}

7272 7273
static int qemudDomainDetachDevice(virDomainPtr dom,
                                   const char *xml) {
7274 7275
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
7276
    unsigned long long qemuCmdFlags;
7277 7278
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
7279

7280
    qemuDriverLock(driver);
7281
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7282
    if (!vm) {
7283 7284
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7285 7286
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7287
        goto cleanup;
7288 7289
    }

7290 7291 7292
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
7293
    if (!virDomainObjIsActive(vm)) {
7294 7295
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot detach device on inactive domain"));
7296
        goto endjob;
7297 7298
    }

7299
    dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
7300
                                  VIR_DOMAIN_XML_INACTIVE);
7301
    if (dev == NULL)
7302
        goto endjob;
7303

7304 7305 7306 7307
    if (qemudExtractVersionInfo(vm->def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0)
        goto endjob;
7308 7309 7310

    if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
        dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
7311
        dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
7312
        ret = qemudDomainDetachPciDiskDevice(driver, vm, dev, qemuCmdFlags);
7313
    } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
7314
        ret = qemudDomainDetachNetDevice(driver, vm, dev, qemuCmdFlags);
7315 7316
    } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) {
        if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
7317 7318
            ret = qemudDomainDetachPciControllerDevice(driver, vm, dev,
                                                       qemuCmdFlags);
7319
        } else {
7320 7321 7322
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("disk controller bus '%s' cannot be hotunplugged."),
                            virDomainControllerTypeToString(dev->data.controller->type));
7323 7324
            /* fallthrough */
        }
7325
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
7326
        ret = qemudDomainDetachHostDevice(driver, vm, dev, qemuCmdFlags);
7327
    } else {
7328 7329
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("This type of device cannot be hot unplugged"));
7330
    }
7331

7332
    if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
7333 7334
        ret = -1;

7335
endjob:
7336 7337
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
7338

7339 7340
cleanup:
    virDomainDeviceDefFree(dev);
7341 7342
    if (vm)
        virDomainObjUnlock(vm);
7343
    qemuDriverUnlock(driver);
7344 7345 7346
    return ret;
}

7347 7348 7349 7350
static int qemudDomainDetachDeviceFlags(virDomainPtr dom,
                                        const char *xml,
                                        unsigned int flags) {
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
7351 7352
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify the persistent configuration of a domain"));
7353 7354 7355 7356 7357 7358
        return -1;
    }

    return qemudDomainDetachDevice(dom, xml);
}

7359
static int qemudDomainGetAutostart(virDomainPtr dom,
7360
                                   int *autostart) {
7361 7362 7363
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
7364

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

7369
    if (!vm) {
7370 7371
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7372 7373
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7374
        goto cleanup;
7375 7376 7377
    }

    *autostart = vm->autostart;
7378
    ret = 0;
7379

7380
cleanup:
7381 7382
    if (vm)
        virDomainObjUnlock(vm);
7383
    return ret;
7384 7385
}

7386
static int qemudDomainSetAutostart(virDomainPtr dom,
7387
                                   int autostart) {
7388 7389
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
7390 7391
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
7392

7393
    qemuDriverLock(driver);
7394
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7395

7396
    if (!vm) {
7397 7398
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7399 7400
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7401
        goto cleanup;
7402 7403
    }

7404
    if (!vm->persistent) {
7405 7406
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("cannot set autostart for transient domain"));
7407
        goto cleanup;
7408 7409
    }

7410 7411
    autostart = (autostart != 0);

7412
    if (vm->autostart != autostart) {
7413
        if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
7414
            goto cleanup;
7415
        if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
7416
            goto cleanup;
7417

7418 7419
        if (autostart) {
            int err;
7420

7421
            if ((err = virFileMakePath(driver->autostartDir))) {
7422
                virReportSystemError(err,
7423 7424
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
7425 7426
                goto cleanup;
            }
7427

7428
            if (symlink(configFile, autostartLink) < 0) {
7429
                virReportSystemError(errno,
7430 7431
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
7432 7433 7434 7435
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
7436
                virReportSystemError(errno,
7437 7438
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
7439 7440
                goto cleanup;
            }
7441 7442
        }

7443
        vm->autostart = autostart;
7444
    }
7445
    ret = 0;
7446

7447 7448 7449
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
7450 7451
    if (vm)
        virDomainObjUnlock(vm);
7452
    qemuDriverUnlock(driver);
7453
    return ret;
7454 7455
}

7456 7457 7458 7459 7460

static char *qemuGetSchedulerType(virDomainPtr dom,
                                  int *nparams)
{
    struct qemud_driver *driver = dom->conn->privateData;
7461
    char *ret = NULL;
7462

7463
    qemuDriverLock(driver);
7464
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
7465 7466
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        __FUNCTION__);
7467
        goto cleanup;
7468 7469 7470 7471 7472 7473 7474
    }

    if (nparams)
        *nparams = 1;

    ret = strdup("posix");
    if (!ret)
7475
        virReportOOMError();
7476 7477 7478

cleanup:
    qemuDriverUnlock(driver);
7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491
    return ret;
}

static int qemuSetSchedulerParameters(virDomainPtr dom,
                                      virSchedParameterPtr params,
                                      int nparams)
{
    struct qemud_driver *driver = dom->conn->privateData;
    int i;
    virCgroupPtr group = NULL;
    virDomainObjPtr vm = NULL;
    int ret = -1;

7492
    qemuDriverLock(driver);
7493
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
7494 7495
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        __FUNCTION__);
7496
        goto cleanup;
7497 7498 7499 7500 7501
    }

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

    if (vm == NULL) {
7502 7503
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("No such domain %s"), dom->uuid);
7504 7505 7506 7507
        goto cleanup;
    }

    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
7508 7509
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
7510 7511 7512 7513 7514 7515 7516 7517 7518
        goto cleanup;
    }

    for (i = 0; i < nparams; i++) {
        virSchedParameterPtr param = &params[i];

        if (STREQ(param->field, "cpu_shares")) {
            int rc;
            if (param->type != VIR_DOMAIN_SCHED_FIELD_ULLONG) {
7519 7520
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
                                _("invalid type for cpu_shares tunable, expected a 'ullong'"));
7521 7522 7523 7524 7525
                goto cleanup;
            }

            rc = virCgroupSetCpuShares(group, params[i].value.ul);
            if (rc != 0) {
7526
                virReportSystemError(-rc, "%s",
7527 7528 7529 7530
                                     _("unable to set cpu shares tunable"));
                goto cleanup;
            }
        } else {
7531 7532
            qemuReportError(VIR_ERR_INVALID_ARG,
                            _("Invalid parameter `%s'"), param->field);
7533 7534 7535 7536 7537 7538 7539 7540 7541
            goto cleanup;
        }
    }
    ret = 0;

cleanup:
    virCgroupFree(&group);
    if (vm)
        virDomainObjUnlock(vm);
7542
    qemuDriverUnlock(driver);
7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556
    return ret;
}

static int qemuGetSchedulerParameters(virDomainPtr dom,
                                      virSchedParameterPtr params,
                                      int *nparams)
{
    struct qemud_driver *driver = dom->conn->privateData;
    virCgroupPtr group = NULL;
    virDomainObjPtr vm = NULL;
    unsigned long long val;
    int ret = -1;
    int rc;

7557
    qemuDriverLock(driver);
7558
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
7559 7560
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        __FUNCTION__);
7561
        goto cleanup;
7562 7563 7564
    }

    if ((*nparams) != 1) {
7565 7566
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("Invalid parameter count"));
7567
        goto cleanup;
7568 7569 7570 7571 7572
    }

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

    if (vm == NULL) {
7573 7574
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("No such domain %s"), dom->uuid);
7575 7576 7577 7578
        goto cleanup;
    }

    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
7579 7580
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
7581 7582 7583 7584 7585
        goto cleanup;
    }

    rc = virCgroupGetCpuShares(group, &val);
    if (rc != 0) {
7586
        virReportSystemError(-rc, "%s",
7587 7588 7589 7590 7591
                             _("unable to get cpu shares tunable"));
        goto cleanup;
    }
    params[0].value.ul = val;
    params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
C
Chris Lalancette 已提交
7592
    if (virStrcpyStatic(params[0].field, "cpu_shares") == NULL) {
7593 7594
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Field cpu_shares too long for destination"));
C
Chris Lalancette 已提交
7595 7596
        goto cleanup;
    }
7597 7598 7599 7600 7601 7602 7603

    ret = 0;

cleanup:
    virCgroupFree(&group);
    if (vm)
        virDomainObjUnlock(vm);
7604
    qemuDriverUnlock(driver);
7605 7606 7607 7608
    return ret;
}


7609 7610 7611 7612 7613 7614 7615 7616 7617
/* 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)
{
7618
    struct qemud_driver *driver = dom->conn->privateData;
7619
    int i, ret = -1;
7620
    virDomainObjPtr vm;
7621
    virDomainDiskDefPtr disk = NULL;
7622

7623
    qemuDriverLock(driver);
7624
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7625
    qemuDriverUnlock(driver);
7626
    if (!vm) {
7627 7628
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7629 7630
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7631
        goto cleanup;
7632
    }
7633 7634 7635 7636

    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
7637
    if (!virDomainObjIsActive (vm)) {
7638 7639
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
7640
        goto endjob;
7641 7642
    }

7643 7644 7645 7646 7647 7648 7649 7650
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(path, vm->def->disks[i]->dst)) {
            disk = vm->def->disks[i];
            break;
        }
    }

    if (!disk) {
7651 7652
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("invalid path: %s"), path);
7653
        goto endjob;
7654 7655
    }

7656
    if (!disk->info.alias) {
7657 7658
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("missing disk device alias name for %s"), disk->dst);
7659
        goto endjob;
7660
    }
7661

7662
    qemuDomainObjPrivatePtr priv = vm->privateData;
7663 7664
    qemuDomainObjEnterMonitor(vm);
    ret = qemuMonitorGetBlockStatsInfo(priv->mon,
7665
                                       disk->info.alias,
7666 7667 7668 7669 7670 7671
                                       &stats->rd_req,
                                       &stats->rd_bytes,
                                       &stats->wr_req,
                                       &stats->wr_bytes,
                                       &stats->errs);
    qemuDomainObjExitMonitor(vm);
7672

7673
endjob:
7674 7675
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
7676

7677
cleanup:
7678 7679
    if (vm)
        virDomainObjUnlock(vm);
7680
    return ret;
7681 7682
}

7683
#ifdef __linux__
7684 7685 7686 7687 7688
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path,
                           struct _virDomainInterfaceStats *stats)
{
7689 7690
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
7691
    int i;
7692
    int ret = -1;
7693

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

7698
    if (!vm) {
7699 7700
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7701 7702
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7703
        goto cleanup;
7704 7705
    }

D
Daniel P. Berrange 已提交
7706
    if (!virDomainObjIsActive(vm)) {
7707 7708
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
7709
        goto cleanup;
7710 7711 7712
    }

    /* Check the path is one of the domain's network interfaces. */
7713 7714
    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (vm->def->nets[i]->ifname &&
7715 7716 7717 7718
            STREQ (vm->def->nets[i]->ifname, path)) {
            ret = 0;
            break;
        }
7719 7720
    }

7721
    if (ret == 0)
7722
        ret = linuxDomainInterfaceStats(path, stats);
7723
    else
7724 7725
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("invalid path, '%s' is not a known interface"), path);
7726

7727
cleanup:
7728 7729
    if (vm)
        virDomainObjUnlock(vm);
7730 7731
    return ret;
}
7732
#else
7733 7734 7735 7736
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path ATTRIBUTE_UNUSED,
                           struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
7737 7738
    qemuReportError(VIR_ERR_NO_SUPPORT,
                    "%s", __FUNCTION__);
7739 7740
    return -1;
}
7741
#endif
7742

7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758
static int
qemudDomainMemoryStats (virDomainPtr dom,
                        struct _virDomainMemoryStat *stats,
                        unsigned int nr_stats)
{
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    unsigned int ret = -1;

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

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7759 7760
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7761 7762 7763
        goto cleanup;
    }

7764 7765 7766
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

7767 7768 7769 7770 7771 7772
    if (virDomainObjIsActive(vm)) {
        qemuDomainObjPrivatePtr priv = vm->privateData;
        qemuDomainObjEnterMonitor(vm);
        ret = qemuMonitorTextGetMemoryStats(priv->mon, stats, nr_stats);
        qemuDomainObjExitMonitor(vm);
    } else {
7773 7774
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
7775 7776
    }

7777 7778 7779
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;

7780 7781 7782 7783 7784 7785
cleanup:
    if (vm)
        virDomainObjUnlock(vm);
    return ret;
}

7786 7787 7788 7789 7790 7791 7792
static int
qemudDomainBlockPeek (virDomainPtr dom,
                      const char *path,
                      unsigned long long offset, size_t size,
                      void *buffer,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
7793 7794 7795
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int fd = -1, ret = -1, i;
7796

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

7801
    if (!vm) {
7802 7803
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7804 7805
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7806
        goto cleanup;
7807 7808 7809
    }

    if (!path || path[0] == '\0') {
7810 7811
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("NULL or empty path"));
7812
        goto cleanup;
7813 7814 7815
    }

    /* Check the path belongs to this domain. */
7816 7817
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (vm->def->disks[i]->src != NULL &&
7818 7819 7820 7821
            STREQ (vm->def->disks[i]->src, path)) {
            ret = 0;
            break;
        }
7822 7823
    }

7824 7825 7826 7827 7828
    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) {
7829 7830
            virReportSystemError(errno,
                                 _("%s: failed to open"), path);
7831 7832
            goto cleanup;
        }
7833

7834 7835 7836 7837 7838 7839
        /* 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) {
7840 7841
            virReportSystemError(errno,
                                 _("%s: failed to seek or read"), path);
7842 7843 7844 7845 7846
            goto cleanup;
        }

        ret = 0;
    } else {
7847 7848
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("invalid path"));
7849 7850
    }

7851 7852 7853
cleanup:
    if (fd >= 0)
        close (fd);
7854 7855
    if (vm)
        virDomainObjUnlock(vm);
7856 7857 7858
    return ret;
}

R
Richard W.M. Jones 已提交
7859 7860 7861 7862 7863 7864
static int
qemudDomainMemoryPeek (virDomainPtr dom,
                       unsigned long long offset, size_t size,
                       void *buffer,
                       unsigned int flags)
{
7865 7866
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
7867
    char *tmp = NULL;
R
Richard W.M. Jones 已提交
7868 7869
    int fd = -1, ret = -1;

7870
    qemuDriverLock(driver);
7871
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7872
    qemuDriverUnlock(driver);
R
Richard W.M. Jones 已提交
7873 7874

    if (!vm) {
7875 7876
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7877 7878
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7879 7880 7881
        goto cleanup;
    }

7882
    if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
7883 7884
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
7885
        goto cleanup;
R
Richard W.M. Jones 已提交
7886 7887
    }

7888 7889 7890
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
7891
    if (!virDomainObjIsActive(vm)) {
7892 7893
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
7894
        goto endjob;
R
Richard W.M. Jones 已提交
7895 7896
    }

7897
    if (virAsprintf(&tmp, driver->cacheDir,  "/qemu.mem.XXXXXX") < 0) {
7898
        virReportOOMError();
7899
        goto endjob;
7900 7901
    }

R
Richard W.M. Jones 已提交
7902 7903
    /* Create a temporary filename. */
    if ((fd = mkstemp (tmp)) == -1) {
7904 7905
        virReportSystemError(errno,
                             _("mkstemp(\"%s\") failed"), tmp);
7906
        goto endjob;
R
Richard W.M. Jones 已提交
7907 7908
    }

7909
    qemuDomainObjPrivatePtr priv = vm->privateData;
7910
    qemuDomainObjEnterMonitor(vm);
7911
    if (flags == VIR_MEMORY_VIRTUAL) {
7912 7913
        if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
            qemuDomainObjExitMonitor(vm);
7914
            goto endjob;
7915
        }
7916
    } else {
7917 7918
        if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
            qemuDomainObjExitMonitor(vm);
7919
            goto endjob;
7920
        }
R
Richard W.M. Jones 已提交
7921
    }
7922
    qemuDomainObjExitMonitor(vm);
R
Richard W.M. Jones 已提交
7923 7924 7925

    /* Read the memory file into buffer. */
    if (saferead (fd, buffer, size) == (ssize_t) -1) {
7926 7927 7928
        virReportSystemError(errno,
                             _("failed to read temporary file "
                               "created with template %s"), tmp);
7929
        goto endjob;
R
Richard W.M. Jones 已提交
7930 7931 7932
    }

    ret = 0;
7933

7934
endjob:
7935 7936
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
7937

7938
cleanup:
7939
    VIR_FREE(tmp);
R
Richard W.M. Jones 已提交
7940 7941
    if (fd >= 0) close (fd);
    unlink (tmp);
7942 7943
    if (vm)
        virDomainObjUnlock(vm);
R
Richard W.M. Jones 已提交
7944 7945 7946
    return ret;
}

7947

7948 7949
static int
qemudDomainEventRegister (virConnectPtr conn,
7950
                          virConnectDomainEventCallback callback,
7951 7952
                          void *opaque,
                          virFreeCallback freecb)
7953
{
7954 7955 7956
    struct qemud_driver *driver = conn->privateData;
    int ret;

7957
    qemuDriverLock(driver);
7958 7959
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
7960
    qemuDriverUnlock(driver);
7961

7962
    return ret;
7963 7964 7965 7966
}

static int
qemudDomainEventDeregister (virConnectPtr conn,
7967
                            virConnectDomainEventCallback callback)
7968
{
7969 7970 7971
    struct qemud_driver *driver = conn->privateData;
    int ret;

7972
    qemuDriverLock(driver);
7973 7974 7975 7976 7977 7978
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
7979
    qemuDriverUnlock(driver);
7980

7981
    return ret;
7982 7983
}

7984 7985 7986 7987 7988
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
                                        virConnectDomainEventCallback cb,
                                        void *cbopaque,
                                        void *opaque)
7989
{
7990
    struct qemud_driver *driver = opaque;
7991

7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035
    /* 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);
8036 8037
}

D
Daniel Veillard 已提交
8038 8039
/* Migration support. */

C
Chris Lalancette 已提交
8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058
/* Tunnelled migration stream support */
struct qemuStreamMigFile {
    int fd;

    int watch;
    unsigned int cbRemoved;
    unsigned int dispatching;
    virStreamEventCallback cb;
    void *opaque;
    virFreeCallback ff;
};

static int qemuStreamMigRemoveCallback(virStreamPtr stream)
{
    struct qemud_driver *driver = stream->conn->privateData;
    struct qemuStreamMigFile *qemust = stream->privateData;
    int ret = -1;

    if (!qemust) {
8059 8060
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
8061 8062 8063 8064 8065
        return -1;
    }

    qemuDriverLock(driver);
    if (qemust->watch == 0) {
8066 8067
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream does not have a callback registered"));
C
Chris Lalancette 已提交
8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095
        goto cleanup;
    }

    virEventRemoveHandle(qemust->watch);
    if (qemust->dispatching)
        qemust->cbRemoved = 1;
    else if (qemust->ff)
        (qemust->ff)(qemust->opaque);

    qemust->watch = 0;
    qemust->ff = NULL;
    qemust->cb = NULL;
    qemust->opaque = NULL;

    ret = 0;

cleanup:
    qemuDriverUnlock(driver);
    return ret;
}

static int qemuStreamMigUpdateCallback(virStreamPtr stream, int events)
{
    struct qemud_driver *driver = stream->conn->privateData;
    struct qemuStreamMigFile *qemust = stream->privateData;
    int ret = -1;

    if (!qemust) {
8096 8097
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
8098 8099 8100 8101 8102
        return -1;
    }

    qemuDriverLock(driver);
    if (qemust->watch == 0) {
8103 8104
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream does not have a callback registered"));
C
Chris Lalancette 已提交
8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161
        goto cleanup;
    }

    virEventUpdateHandle(qemust->watch, events);

    ret = 0;

cleanup:
    qemuDriverUnlock(driver);
    return ret;
}

static void qemuStreamMigEvent(int watch ATTRIBUTE_UNUSED,
                               int fd ATTRIBUTE_UNUSED,
                               int events,
                               void *opaque)
{
    virStreamPtr stream = opaque;
    struct qemud_driver *driver = stream->conn->privateData;
    struct qemuStreamMigFile *qemust = stream->privateData;
    virStreamEventCallback cb;
    void *cbopaque;
    virFreeCallback ff;

    qemuDriverLock(driver);
    if (!qemust || !qemust->cb) {
        qemuDriverUnlock(driver);
        return;
    }

    cb = qemust->cb;
    cbopaque = qemust->opaque;
    ff = qemust->ff;
    qemust->dispatching = 1;
    qemuDriverUnlock(driver);

    cb(stream, events, cbopaque);

    qemuDriverLock(driver);
    qemust->dispatching = 0;
    if (qemust->cbRemoved && ff)
        (ff)(cbopaque);
    qemuDriverUnlock(driver);
}

static int
qemuStreamMigAddCallback(virStreamPtr st,
                         int events,
                         virStreamEventCallback cb,
                         void *opaque,
                         virFreeCallback ff)
{
    struct qemud_driver *driver = st->conn->privateData;
    struct qemuStreamMigFile *qemust = st->privateData;
    int ret = -1;

    if (!qemust) {
8162 8163
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
8164 8165 8166 8167 8168
        return -1;
    }

    qemuDriverLock(driver);
    if (qemust->watch != 0) {
8169 8170
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream already has a callback registered"));
C
Chris Lalancette 已提交
8171 8172 8173 8174 8175 8176 8177 8178
        goto cleanup;
    }

    if ((qemust->watch = virEventAddHandle(qemust->fd,
                                           events,
                                           qemuStreamMigEvent,
                                           st,
                                           NULL)) < 0) {
8179 8180
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("cannot register file watch on stream"));
C
Chris Lalancette 已提交
8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212
        goto cleanup;
    }

    qemust->cbRemoved = 0;
    qemust->cb = cb;
    qemust->opaque = opaque;
    qemust->ff = ff;
    virStreamRef(st);

    ret = 0;

cleanup:
    qemuDriverUnlock(driver);
    return ret;
}

static void qemuStreamMigFree(struct qemuStreamMigFile *qemust)
{
    if (qemust->fd != -1)
        close(qemust->fd);
    VIR_FREE(qemust);
}

static struct qemuStreamMigFile *qemuStreamMigOpen(virStreamPtr st,
                                                   const char *unixfile)
{
    struct qemuStreamMigFile *qemust = NULL;
    struct sockaddr_un sa_qemu;
    int i = 0;
    int timeout = 3;
    int ret;

8213
    if (VIR_ALLOC(qemust) < 0) {
8214
        virReportOOMError();
C
Chris Lalancette 已提交
8215
        return NULL;
8216
    }
C
Chris Lalancette 已提交
8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277

    qemust->fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (qemust->fd < 0)
        goto cleanup;

    memset(&sa_qemu, 0, sizeof(sa_qemu));
    sa_qemu.sun_family = AF_UNIX;
    if (virStrcpy(sa_qemu.sun_path, unixfile, sizeof(sa_qemu.sun_path)) == NULL)
        goto cleanup;

    do {
        ret = connect(qemust->fd, (struct sockaddr *)&sa_qemu, sizeof(sa_qemu));
        if (ret == 0)
            break;

        if (errno == ENOENT || errno == ECONNREFUSED) {
            /* ENOENT       : Socket may not have shown up yet
             * ECONNREFUSED : Leftover socket hasn't been removed yet */
            continue;
        }

        goto cleanup;
    } while ((++i <= timeout*5) && (usleep(.2 * 1000000) <= 0));

    if ((st->flags & VIR_STREAM_NONBLOCK) && virSetNonBlock(qemust->fd) < 0)
        goto cleanup;

    return qemust;

cleanup:
    qemuStreamMigFree(qemust);
    return NULL;
}

static int
qemuStreamMigClose(virStreamPtr st)
{
    struct qemud_driver *driver = st->conn->privateData;
    struct qemuStreamMigFile *qemust = st->privateData;

    if (!qemust)
        return 0;

    qemuDriverLock(driver);

    qemuStreamMigFree(qemust);

    st->privateData = NULL;

    qemuDriverUnlock(driver);

    return 0;
}

static int qemuStreamMigWrite(virStreamPtr st, const char *bytes, size_t nbytes)
{
    struct qemud_driver *driver = st->conn->privateData;
    struct qemuStreamMigFile *qemust = st->privateData;
    int ret;

    if (!qemust) {
8278 8279
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293
        return -1;
    }

    qemuDriverLock(driver);

retry:
    ret = write(qemust->fd, bytes, nbytes);
    if (ret < 0) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            ret = -2;
        } else if (errno == EINTR) {
            goto retry;
        } else {
            ret = -1;
8294
            virReportSystemError(errno, "%s",
C
Chris Lalancette 已提交
8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332
                                 _("cannot write to stream"));
        }
    }

    qemuDriverUnlock(driver);
    return ret;
}

static virStreamDriver qemuStreamMigDrv = {
    .streamSend = qemuStreamMigWrite,
    .streamFinish = qemuStreamMigClose,
    .streamAbort = qemuStreamMigClose,
    .streamAddCallback = qemuStreamMigAddCallback,
    .streamUpdateCallback = qemuStreamMigUpdateCallback,
    .streamRemoveCallback = qemuStreamMigRemoveCallback
};

/* Prepare is the first step, and it runs on the destination host.
 *
 * This version starts an empty VM listening on a localhost TCP port, and
 * sets up the corresponding virStream to handle the incoming data.
 */
static int
qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
                                virStreamPtr st,
                                unsigned long flags,
                                const char *dname,
                                unsigned long resource ATTRIBUTE_UNUSED,
                                const char *dom_xml)
{
    struct qemud_driver *driver = dconn->privateData;
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    char *migrateFrom;
    virDomainEventPtr event = NULL;
    int ret = -1;
    int internalret;
    char *unixfile = NULL;
8333
    unsigned long long qemuCmdFlags;
C
Chris Lalancette 已提交
8334 8335 8336 8337
    struct qemuStreamMigFile *qemust = NULL;

    qemuDriverLock(driver);
    if (!dom_xml) {
8338 8339
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no domain XML passed"));
C
Chris Lalancette 已提交
8340 8341 8342
        goto cleanup;
    }
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
8343
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
C
Chris Lalancette 已提交
8344 8345 8346 8347
                         "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
        goto cleanup;
    }
    if (st == NULL) {
8348 8349
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("tunnelled migration requested but NULL stream passed"));
C
Chris Lalancette 已提交
8350 8351 8352 8353
        goto cleanup;
    }

    /* Parse the domain XML. */
8354
    if (!(def = virDomainDefParseString(driver->caps, dom_xml,
C
Chris Lalancette 已提交
8355
                                        VIR_DOMAIN_XML_INACTIVE))) {
8356 8357
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to parse XML"));
C
Chris Lalancette 已提交
8358 8359 8360 8361
        goto cleanup;
    }

    /* Target domain name, maybe renamed. */
8362 8363 8364 8365 8366 8367
    if (dname) {
        VIR_FREE(def->name);
        def->name = strdup(dname);
        if (def->name == NULL)
            goto cleanup;
    }
C
Chris Lalancette 已提交
8368

8369 8370
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
C
Chris Lalancette 已提交
8371

8372
    if (!(vm = virDomainAssignDef(driver->caps,
C
Chris Lalancette 已提交
8373 8374
                                  &driver->domains,
                                  def))) {
8375 8376
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to assign new VM"));
C
Chris Lalancette 已提交
8377 8378 8379 8380
        goto cleanup;
    }
    def = NULL;

8381 8382 8383
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

C
Chris Lalancette 已提交
8384 8385 8386 8387 8388
    /* Domain starts inactive, even if the domain XML had an id field. */
    vm->def->id = -1;

    if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.dest.%s",
                    driver->stateDir, vm->def->name) < 0) {
8389
        virReportOOMError();
8390
        goto endjob;
C
Chris Lalancette 已提交
8391 8392 8393 8394 8395
    }
    unlink(unixfile);

    /* check that this qemu version supports the interactive exec */
    if (qemudExtractVersionInfo(vm->def->emulator, NULL, &qemuCmdFlags) < 0) {
8396 8397 8398
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot determine QEMU argv syntax %s"),
                        vm->def->emulator);
8399
        goto endjob;
C
Chris Lalancette 已提交
8400 8401 8402 8403 8404 8405
    }
    if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX)
        internalret = virAsprintf(&migrateFrom, "unix:%s", unixfile);
    else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)
        internalret = virAsprintf(&migrateFrom, "exec:nc -U -l %s", unixfile);
    else {
8406 8407
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("Destination qemu is too old to support tunnelled migration"));
8408
        goto endjob;
C
Chris Lalancette 已提交
8409 8410
    }
    if (internalret < 0) {
8411
        virReportOOMError();
8412
        goto endjob;
C
Chris Lalancette 已提交
8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426
    }
    /* Start the QEMU daemon, with the same command-line arguments plus
     * -incoming unix:/path/to/file or exec:nc -U /path/to/file
     */
    internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, -1);
    VIR_FREE(migrateFrom);
    if (internalret < 0) {
        /* Note that we don't set an error here because qemudStartVMDaemon
         * should have already done that.
         */
        if (!vm->persistent) {
            virDomainRemoveInactive(&driver->domains, vm);
            vm = NULL;
        }
8427
        goto endjob;
C
Chris Lalancette 已提交
8428 8429 8430 8431
    }

    qemust = qemuStreamMigOpen(st, unixfile);
    if (qemust == NULL) {
8432
        qemudShutdownVMDaemon(driver, vm);
8433
        if (!vm->persistent) {
8434 8435
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains, vm);
8436 8437
            vm = NULL;
        }
8438
        virReportSystemError(errno,
C
Chris Lalancette 已提交
8439 8440
                             _("cannot open unix socket '%s' for tunnelled migration"),
                             unixfile);
8441
        goto endjob;
C
Chris Lalancette 已提交
8442 8443 8444 8445 8446 8447 8448 8449 8450 8451
    }

    st->driver = &qemuStreamMigDrv;
    st->privateData = qemust;

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_MIGRATED);
    ret = 0;

8452
endjob:
8453 8454 8455
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
8456

C
Chris Lalancette 已提交
8457 8458
cleanup:
    virDomainDefFree(def);
8459 8460
    if (unixfile)
        unlink(unixfile);
C
Chris Lalancette 已提交
8461 8462 8463 8464 8465 8466 8467 8468 8469
    VIR_FREE(unixfile);
    if (vm)
        virDomainObjUnlock(vm);
    if (event)
        qemuDomainEventQueue(driver, event);
    qemuDriverUnlock(driver);
    return ret;
}

D
Daniel Veillard 已提交
8470 8471 8472 8473
/* Prepare is the first step, and it runs on the destination host.
 *
 * This starts an empty VM listening on a TCP port.
 */
8474
static int ATTRIBUTE_NONNULL (5)
D
Daniel Veillard 已提交
8475 8476 8477 8478 8479
qemudDomainMigratePrepare2 (virConnectPtr dconn,
                            char **cookie ATTRIBUTE_UNUSED,
                            int *cookielen ATTRIBUTE_UNUSED,
                            const char *uri_in,
                            char **uri_out,
C
Chris Lalancette 已提交
8480
                            unsigned long flags,
D
Daniel Veillard 已提交
8481 8482 8483 8484 8485
                            const char *dname,
                            unsigned long resource ATTRIBUTE_UNUSED,
                            const char *dom_xml)
{
    static int port = 0;
8486 8487
    struct qemud_driver *driver = dconn->privateData;
    virDomainDefPtr def = NULL;
D
Daniel Veillard 已提交
8488 8489
    virDomainObjPtr vm = NULL;
    int this_port;
8490
    char *hostname;
D
Daniel Veillard 已提交
8491 8492
    char migrateFrom [64];
    const char *p;
8493
    virDomainEventPtr event = NULL;
8494
    int ret = -1;
8495
    int internalret;
8496 8497

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

8499
    qemuDriverLock(driver);
C
Chris Lalancette 已提交
8500 8501 8502 8503
    if (flags & VIR_MIGRATE_TUNNELLED) {
        /* this is a logical error; we never should have gotten here with
         * VIR_MIGRATE_TUNNELLED set
         */
8504 8505
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Tunnelled migration requested but invalid RPC method called"));
C
Chris Lalancette 已提交
8506 8507 8508
        goto cleanup;
    }

D
Daniel Veillard 已提交
8509
    if (!dom_xml) {
8510 8511
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no domain XML passed"));
8512
        goto cleanup;
D
Daniel Veillard 已提交
8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529
    }

    /* 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 */
8530
        if ((hostname = virGetHostnameLocalhost(0)) == NULL)
8531
            goto cleanup;
D
Daniel Veillard 已提交
8532

8533 8534 8535 8536 8537
        /* XXX this really should have been a properly well-formed
         * URI, but we can't add in tcp:// now without breaking
         * compatability with old targets. We at least make the
         * new targets accept both syntaxes though.
         */
D
Daniel Veillard 已提交
8538
        /* Caller frees */
8539 8540 8541
        internalret = virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port);
        VIR_FREE(hostname);
        if (internalret < 0) {
8542
            virReportOOMError();
8543
            goto cleanup;
D
Daniel Veillard 已提交
8544 8545 8546 8547 8548 8549
        }
    } 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.
         */
8550
        if (!STRPREFIX (uri_in, "tcp:")) {
8551 8552
            qemuReportError (VIR_ERR_INVALID_ARG,
                             "%s", _("only tcp URIs are supported for KVM/QEMU migrations"));
8553
            goto cleanup;
D
Daniel Veillard 已提交
8554 8555 8556 8557
        }

        /* Get the port number. */
        p = strrchr (uri_in, ':');
8558 8559 8560 8561 8562 8563 8564 8565
        if (p == strchr(uri_in, ':')) {
            /* Generate a port */
            this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
            if (port == QEMUD_MIGRATION_NUM_PORTS)
                port = 0;

            /* Caller frees */
            if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0) {
8566
                virReportOOMError();
8567 8568 8569 8570 8571 8572 8573
                goto cleanup;
            }

        } else {
            p++; /* definitely has a ':' in it, see above */
            this_port = virParseNumber (&p);
            if (this_port == -1 || p-uri_in != strlen (uri_in)) {
8574 8575
                qemuReportError(VIR_ERR_INVALID_ARG,
                                "%s", _("URI ended with incorrect ':port'"));
8576 8577
                goto cleanup;
            }
D
Daniel Veillard 已提交
8578 8579 8580
        }
    }

8581
    if (*uri_out)
8582 8583
        VIR_DEBUG("Generated uri_out=%s", *uri_out);

D
Daniel Veillard 已提交
8584
    /* Parse the domain XML. */
8585
    if (!(def = virDomainDefParseString(driver->caps, dom_xml,
8586
                                        VIR_DOMAIN_XML_INACTIVE))) {
8587 8588
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to parse XML"));
8589
        goto cleanup;
D
Daniel Veillard 已提交
8590 8591 8592
    }

    /* Target domain name, maybe renamed. */
8593 8594 8595 8596 8597 8598
    if (dname) {
        VIR_FREE(def->name);
        def->name = strdup(dname);
        if (def->name == NULL)
            goto cleanup;
    }
D
Daniel Veillard 已提交
8599

8600 8601
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
D
Daniel Veillard 已提交
8602

8603
    if (!(vm = virDomainAssignDef(driver->caps,
D
Daniel Veillard 已提交
8604 8605
                                  &driver->domains,
                                  def))) {
8606 8607
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to assign new VM"));
8608
        goto cleanup;
D
Daniel Veillard 已提交
8609
    }
8610
    def = NULL;
D
Daniel Veillard 已提交
8611

8612 8613 8614
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel Veillard 已提交
8615 8616 8617 8618 8619 8620 8621
    /* 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);
8622
    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
8623 8624 8625
        /* Note that we don't set an error here because qemudStartVMDaemon
         * should have already done that.
         */
8626
        if (!vm->persistent) {
8627 8628
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains, vm);
8629 8630
            vm = NULL;
        }
8631
        goto endjob;
D
Daniel Veillard 已提交
8632
    }
8633 8634 8635 8636

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

8639
endjob:
8640 8641 8642
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
8643

8644 8645 8646 8647 8648
cleanup:
    virDomainDefFree(def);
    if (ret != 0) {
        VIR_FREE(*uri_out);
    }
8649 8650
    if (vm)
        virDomainObjUnlock(vm);
8651 8652
    if (event)
        qemuDomainEventQueue(driver, event);
8653
    qemuDriverUnlock(driver);
8654
    return ret;
C
Chris Lalancette 已提交
8655 8656 8657

}

8658 8659 8660 8661

/* Perform migration using QEMU's native TCP migrate support,
 * not encrypted obviously
 */
8662
static int doNativeMigrate(struct qemud_driver *driver,
8663 8664 8665 8666 8667 8668 8669
                           virDomainObjPtr vm,
                           const char *uri,
                           unsigned long flags ATTRIBUTE_UNUSED,
                           const char *dname ATTRIBUTE_UNUSED,
                           unsigned long resource)
{
    int ret = -1;
8670
    xmlURIPtr uribits = NULL;
8671
    qemuDomainObjPrivatePtr priv = vm->privateData;
8672 8673 8674 8675 8676 8677

    /* Issue the migrate command. */
    if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) {
        /* HACK: source host generates bogus URIs, so fix them up */
        char *tmpuri;
        if (virAsprintf(&tmpuri, "tcp://%s", uri + strlen("tcp:")) < 0) {
8678
            virReportOOMError();
8679 8680 8681 8682 8683 8684 8685 8686
            goto cleanup;
        }
        uribits = xmlParseURI(tmpuri);
        VIR_FREE(tmpuri);
    } else {
        uribits = xmlParseURI(uri);
    }
    if (!uribits) {
8687 8688
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot parse URI %s"), uri);
8689 8690 8691
        goto cleanup;
    }

8692
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
8693
    if (resource > 0 &&
8694
        qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) {
8695
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8696
        goto cleanup;
8697
    }
8698

8699
    if (qemuMonitorMigrateToHost(priv->mon, 1, uribits->server, uribits->port) < 0) {
8700
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8701 8702
        goto cleanup;
    }
8703
    qemuDomainObjExitMonitorWithDriver(driver, vm);
8704

8705
    if (qemuDomainWaitForMigrationComplete(driver, vm) < 0)
8706 8707 8708 8709 8710 8711 8712 8713 8714 8715
        goto cleanup;

    ret = 0;

cleanup:
    xmlFreeURI(uribits);
    return ret;
}


8716 8717
#define TUNNEL_SEND_BUF_SIZE 65536

8718
static int doTunnelSendAll(virStreamPtr st,
8719 8720
                           int sock)
{
8721 8722 8723 8724 8725 8726 8727 8728
    char *buffer;
    int nbytes = TUNNEL_SEND_BUF_SIZE;

    if (VIR_ALLOC_N(buffer, TUNNEL_SEND_BUF_SIZE) < 0) {
        virReportOOMError();
        virStreamAbort(st);
        return -1;
    }
8729 8730 8731 8732 8733

    /* XXX should honour the 'resource' parameter here */
    for (;;) {
        nbytes = saferead(sock, buffer, nbytes);
        if (nbytes < 0) {
8734
            virReportSystemError(errno, "%s",
8735
                                 _("tunnelled migration failed to read from qemu"));
8736 8737
            virStreamAbort(st);
            VIR_FREE(buffer);
8738 8739 8740 8741 8742 8743 8744
            return -1;
        }
        else if (nbytes == 0)
            /* EOF; get out of here */
            break;

        if (virStreamSend(st, buffer, nbytes) < 0) {
8745 8746
            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                            _("Failed to write migration data to remote libvirtd"));
8747
            VIR_FREE(buffer);
8748 8749 8750 8751
            return -1;
        }
    }

8752 8753
    VIR_FREE(buffer);

8754 8755 8756 8757 8758 8759 8760
    if (virStreamFinish(st) < 0)
        /* virStreamFinish set the error for us */
        return -1;

    return 0;
}

C
Chris Lalancette 已提交
8761
static int doTunnelMigrate(virDomainPtr dom,
8762
                           struct qemud_driver *driver,
8763
                           virConnectPtr dconn,
C
Chris Lalancette 已提交
8764
                           virDomainObjPtr vm,
8765
                           const char *dom_xml,
C
Chris Lalancette 已提交
8766 8767 8768 8769 8770
                           const char *uri,
                           unsigned long flags,
                           const char *dname,
                           unsigned long resource)
{
8771
    qemuDomainObjPrivatePtr priv = vm->privateData;
8772 8773
    int client_sock = -1;
    int qemu_sock = -1;
C
Chris Lalancette 已提交
8774 8775
    struct sockaddr_un sa_qemu, sa_client;
    socklen_t addrlen;
8776
    virDomainPtr ddomain = NULL;
C
Chris Lalancette 已提交
8777
    int retval = -1;
8778
    virStreamPtr st = NULL;
C
Chris Lalancette 已提交
8779 8780
    char *unixfile = NULL;
    int internalret;
8781
    unsigned long long qemuCmdFlags;
C
Chris Lalancette 已提交
8782 8783 8784
    int status;
    unsigned long long transferred, remaining, total;

8785 8786 8787 8788 8789 8790 8791 8792
    /*
     * The order of operations is important here to avoid touching
     * the source VM until we are very sure we can successfully
     * start the migration operation.
     *
     *   1. setup local support infrastructure (eg sockets)
     *   2. setup destination fully
     *   3. start migration on source
C
Chris Lalancette 已提交
8793 8794
     */

8795

8796
    /* Stage 1. setup local support infrastructure */
C
Chris Lalancette 已提交
8797 8798 8799

    if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.src.%s",
                    driver->stateDir, vm->def->name) < 0) {
8800
        virReportOOMError();
8801
        goto cleanup;
C
Chris Lalancette 已提交
8802 8803 8804 8805
    }

    qemu_sock = socket(AF_UNIX, SOCK_STREAM, 0);
    if (qemu_sock < 0) {
8806
        virReportSystemError(errno, "%s",
C
Chris Lalancette 已提交
8807
                             _("cannot open tunnelled migration socket"));
8808
        goto cleanup;
C
Chris Lalancette 已提交
8809 8810 8811 8812 8813
    }
    memset(&sa_qemu, 0, sizeof(sa_qemu));
    sa_qemu.sun_family = AF_UNIX;
    if (virStrcpy(sa_qemu.sun_path, unixfile,
                  sizeof(sa_qemu.sun_path)) == NULL) {
8814 8815 8816
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unix socket '%s' too big for destination"),
                        unixfile);
8817
        goto cleanup;
C
Chris Lalancette 已提交
8818 8819 8820
    }
    unlink(unixfile);
    if (bind(qemu_sock, (struct sockaddr *)&sa_qemu, sizeof(sa_qemu)) < 0) {
8821
        virReportSystemError(errno,
C
Chris Lalancette 已提交
8822 8823
                             _("Cannot bind to unix socket '%s' for tunnelled migration"),
                             unixfile);
8824
        goto cleanup;
C
Chris Lalancette 已提交
8825 8826
    }
    if (listen(qemu_sock, 1) < 0) {
8827
        virReportSystemError(errno,
C
Chris Lalancette 已提交
8828 8829
                             _("Cannot listen on unix socket '%s' for tunnelled migration"),
                             unixfile);
8830
        goto cleanup;
C
Chris Lalancette 已提交
8831 8832 8833 8834
    }

    /* check that this qemu version supports the unix migration */
    if (qemudExtractVersionInfo(vm->def->emulator, NULL, &qemuCmdFlags) < 0) {
8835 8836 8837
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot extract Qemu version from '%s'"),
                        vm->def->emulator);
8838 8839 8840 8841 8842
        goto cleanup;
    }

    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX) &&
        !(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)) {
8843 8844
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("Source qemu is too old to support tunnelled migration"));
8845
        goto cleanup;
C
Chris Lalancette 已提交
8846
    }
8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867


    /* Stage 2. setup destination fully
     *
     * Once stage 2 has completed successfully, we *must* call finish
     * to cleanup the target whether we succeed or fail
     */
    st = virStreamNew(dconn, 0);
    if (st == NULL)
        /* virStreamNew only fails on OOM, and it reports the error itself */
        goto cleanup;

    internalret = dconn->driver->domainMigratePrepareTunnel(dconn, st,
                                                            flags, dname,
                                                            resource, dom_xml);

    if (internalret < 0)
        /* domainMigratePrepareTunnel sets the error for us */
        goto cleanup;

    /*   3. start migration on source */
8868
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
C
Chris Lalancette 已提交
8869
    if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX)
8870
        internalret = qemuMonitorMigrateToUnix(priv->mon, 1, unixfile);
C
Chris Lalancette 已提交
8871 8872
    else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) {
        const char *args[] = { "nc", "-U", unixfile, NULL };
8873
        internalret = qemuMonitorMigrateToCommand(priv->mon, 1, args, "/dev/null");
8874 8875
    } else {
        internalret = -1;
C
Chris Lalancette 已提交
8876
    }
8877
    qemuDomainObjExitMonitorWithDriver(driver, vm);
C
Chris Lalancette 已提交
8878
    if (internalret < 0) {
8879 8880
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("tunnelled migration monitor command failed"));
8881
        goto finish;
C
Chris Lalancette 已提交
8882 8883
    }

8884 8885 8886
    /* From this point onwards we *must* call cancel to abort the
     * migration on source if anything goes wrong */

C
Chris Lalancette 已提交
8887 8888 8889
    /* it is also possible that the migrate didn't fail initially, but
     * rather failed later on.  Check the output of "info migrate"
     */
8890
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
8891 8892
    if (qemuMonitorGetMigrationStatus(priv->mon,
                                      &status,
C
Chris Lalancette 已提交
8893 8894 8895
                                      &transferred,
                                      &remaining,
                                      &total) < 0) {
8896
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8897
        goto cancel;
C
Chris Lalancette 已提交
8898
    }
8899
    qemuDomainObjExitMonitorWithDriver(driver, vm);
C
Chris Lalancette 已提交
8900 8901

    if (status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) {
8902 8903
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s",_("migrate failed"));
8904
        goto cancel;
C
Chris Lalancette 已提交
8905 8906 8907 8908 8909 8910
    }

    addrlen = sizeof(sa_client);
    while ((client_sock = accept(qemu_sock, (struct sockaddr *)&sa_client, &addrlen)) < 0) {
        if (errno == EAGAIN || errno == EINTR)
            continue;
8911
        virReportSystemError(errno, "%s",
C
Chris Lalancette 已提交
8912
                             _("tunnelled migration failed to accept from qemu"));
8913
        goto cancel;
C
Chris Lalancette 已提交
8914 8915
    }

8916
    retval = doTunnelSendAll(st, client_sock);
8917

8918
cancel:
8919
    if (retval != 0) {
8920
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
8921
        qemuMonitorMigrateCancel(priv->mon);
8922
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8923
    }
C
Chris Lalancette 已提交
8924

8925
finish:
C
Chris Lalancette 已提交
8926 8927 8928
    dname = dname ? dname : dom->name;
    ddomain = dconn->driver->domainMigrateFinish2
        (dconn, dname, NULL, 0, uri, flags, retval);
8929 8930 8931 8932 8933 8934 8935

cleanup:
    if (client_sock != -1)
        close(client_sock);
    if (qemu_sock != -1)
        close(qemu_sock);

C
Chris Lalancette 已提交
8936 8937 8938
    if (ddomain)
        virUnrefDomain(ddomain);

8939 8940 8941 8942
    if (unixfile) {
        unlink(unixfile);
        VIR_FREE(unixfile);
    }
C
Chris Lalancette 已提交
8943

8944 8945 8946
    if (st)
        /* don't call virStreamFree(), because that resets any pending errors */
        virUnrefStream(st);
8947 8948 8949 8950
    return retval;
}


8951 8952 8953 8954
/* This is essentially a simplified re-impl of
 * virDomainMigrateVersion2 from libvirt.c, but running in source
 * libvirtd context, instead of client app context */
static int doNonTunnelMigrate(virDomainPtr dom,
8955
                              struct qemud_driver *driver,
8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980
                              virConnectPtr dconn,
                              virDomainObjPtr vm,
                              const char *dom_xml,
                              const char *uri ATTRIBUTE_UNUSED,
                              unsigned long flags,
                              const char *dname,
                              unsigned long resource)
{
    virDomainPtr ddomain = NULL;
    int retval = -1;
    char *uri_out = NULL;

    /* NB we don't pass 'uri' into this, since that's the libvirtd
     * URI in this context - so we let dest pick it */
    if (dconn->driver->domainMigratePrepare2(dconn,
                                             NULL, /* cookie */
                                             0, /* cookielen */
                                             NULL, /* uri */
                                             &uri_out,
                                             flags, dname,
                                             resource, dom_xml) < 0)
        /* domainMigratePrepare2 sets the error for us */
        goto cleanup;

    if (uri_out == NULL) {
8981 8982
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("domainMigratePrepare2 did not set uri"));
8983
        goto cleanup;
8984 8985
    }

8986
    if (doNativeMigrate(driver, vm, uri_out, flags, dname, resource) < 0)
8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003
        goto finish;

    retval = 0;

finish:
    dname = dname ? dname : dom->name;
    ddomain = dconn->driver->domainMigrateFinish2
        (dconn, dname, NULL, 0, uri_out, flags, retval);

    if (ddomain)
        virUnrefDomain(ddomain);

cleanup:
    return retval;
}


9004
static int doPeer2PeerMigrate(virDomainPtr dom,
9005
                              struct qemud_driver *driver,
9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021
                              virDomainObjPtr vm,
                              const char *uri,
                              unsigned long flags,
                              const char *dname,
                              unsigned long resource)
{
    int ret = -1;
    virConnectPtr dconn = NULL;
    char *dom_xml;

    /* the order of operations is important here; we make sure the
     * destination side is completely setup before we touch the source
     */

    dconn = virConnectOpen(uri);
    if (dconn == NULL) {
9022 9023
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("Failed to connect to remote libvirt URI %s"), uri);
9024 9025 9026
        return -1;
    }
    if (!VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
9027
                                  VIR_DRV_FEATURE_MIGRATION_P2P)) {
9028 9029
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                        _("Destination libvirt does not support peer-to-peer migration protocol"));
9030 9031 9032
        goto cleanup;
    }

9033
    dom_xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
9034
    if (!dom_xml) {
9035 9036
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to get domain xml"));
9037 9038 9039
        goto cleanup;
    }

9040
    if (flags & VIR_MIGRATE_TUNNELLED)
9041
        ret = doTunnelMigrate(dom, driver, dconn, vm, dom_xml, uri, flags, dname, resource);
9042
    else
9043
        ret = doNonTunnelMigrate(dom, driver, dconn, vm, dom_xml, uri, flags, dname, resource);
9044 9045 9046

cleanup:
    VIR_FREE(dom_xml);
C
Chris Lalancette 已提交
9047 9048 9049
    /* don't call virConnectClose(), because that resets any pending errors */
    virUnrefConnect(dconn);

9050
    return ret;
D
Daniel Veillard 已提交
9051 9052
}

9053

D
Daniel Veillard 已提交
9054 9055 9056 9057 9058 9059
/* 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,
9060
                           unsigned long flags,
9061
                           const char *dname,
D
Daniel Veillard 已提交
9062 9063
                           unsigned long resource)
{
9064 9065
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
9066
    virDomainEventPtr event = NULL;
9067
    int ret = -1;
9068
    int resume = 0;
9069
    qemuDomainObjPrivatePtr priv;
D
Daniel Veillard 已提交
9070

9071
    qemuDriverLock(driver);
9072
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
D
Daniel Veillard 已提交
9073
    if (!vm) {
9074 9075
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
9076 9077
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
9078
        goto cleanup;
D
Daniel Veillard 已提交
9079
    }
9080
    priv = vm->privateData;
D
Daniel Veillard 已提交
9081

9082 9083
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;
9084
    priv->jobActive = QEMU_JOB_MIGRATION;
9085

D
Daniel P. Berrange 已提交
9086
    if (!virDomainObjIsActive(vm)) {
9087 9088
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
9089
        goto endjob;
D
Daniel Veillard 已提交
9090 9091
    }

9092 9093 9094
    memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
    priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;

9095
    resume = vm->state == VIR_DOMAIN_RUNNING;
9096
    if (!(flags & VIR_MIGRATE_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
9097
        if (qemuDomainMigrateOffline(driver, vm) < 0)
9098
            goto endjob;
9099 9100
    }

9101
    if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
9102
        if (doPeer2PeerMigrate(dom, driver, vm, uri, flags, dname, resource) < 0)
9103
            /* doPeer2PeerMigrate already set the error, so just get out */
9104
            goto endjob;
9105
    } else {
9106
        if (doNativeMigrate(driver, vm, uri, flags, dname, resource) < 0)
9107
            goto endjob;
9108 9109
    }

D
Daniel Veillard 已提交
9110
    /* Clean up the source domain. */
9111
    qemudShutdownVMDaemon(driver, vm);
9112
    resume = 0;
9113 9114 9115 9116

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
C
Chris Lalancette 已提交
9117
    if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
9118
        virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
9119 9120
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains, vm);
9121 9122
        vm = NULL;
    }
9123
    ret = 0;
D
Daniel Veillard 已提交
9124

9125
endjob:
9126
    if (resume && vm->state == VIR_DOMAIN_PAUSED) {
9127
        /* we got here through some sort of failure; start the domain again */
9128
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
9129
        if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) {
9130 9131 9132 9133
            /* Hm, we already know we are in error here.  We don't want to
             * overwrite the previous error, though, so we just throw something
             * to the logs and hope for the best
             */
9134
            VIR_ERROR(_("Failed to resume guest %s after failure"),
9135
                      vm->def->name);
9136
        }
9137
        qemuDomainObjExitMonitorWithDriver(driver, vm);
9138

9139
        vm->state = VIR_DOMAIN_RUNNING;
9140 9141 9142 9143
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
    }
9144 9145 9146
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
9147

9148
cleanup:
9149 9150
    if (vm)
        virDomainObjUnlock(vm);
9151 9152
    if (event)
        qemuDomainEventQueue(driver, event);
9153
    qemuDriverUnlock(driver);
9154
    return ret;
D
Daniel Veillard 已提交
9155 9156 9157 9158 9159 9160 9161 9162 9163
}

/* 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,
C
Chris Lalancette 已提交
9164
                           unsigned long flags,
D
Daniel Veillard 已提交
9165 9166
                           int retcode)
{
9167 9168 9169
    struct qemud_driver *driver = dconn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
9170
    virDomainEventPtr event = NULL;
9171
    virErrorPtr orig_err;
C
Chris Lalancette 已提交
9172
    int newVM = 1;
D
Daniel Veillard 已提交
9173

9174 9175 9176
    /* Migration failed. Save the current error so nothing squashes it */
    orig_err = virSaveLastError();

9177
    qemuDriverLock(driver);
9178
    vm = virDomainFindByName(&driver->domains, dname);
D
Daniel Veillard 已提交
9179
    if (!vm) {
9180 9181
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching name '%s'"), dname);
9182
        goto cleanup;
D
Daniel Veillard 已提交
9183 9184
    }

9185 9186 9187
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel Veillard 已提交
9188 9189 9190 9191
    /* Did the migration go as planned?  If yes, return the domain
     * object, but if no, clean up the empty qemu process.
     */
    if (retcode == 0) {
C
Chris Lalancette 已提交
9192 9193 9194 9195 9196
        if (flags & VIR_MIGRATE_PERSIST_DEST) {
            if (vm->persistent)
                newVM = 0;
            vm->persistent = 1;

9197
            if (virDomainSaveConfig(driver->configDir, vm->def) < 0) {
C
Chris Lalancette 已提交
9198 9199 9200 9201 9202 9203 9204 9205 9206 9207
                /* Hmpf.  Migration was successful, but making it persistent
                 * was not.  If we report successful, then when this domain
                 * shuts down, management tools are in for a surprise.  On the
                 * other hand, if we report failure, then the management tools
                 * might try to restart the domain on the source side, even
                 * though the domain is actually running on the destination.
                 * Return a NULL dom pointer, and hope that this is a rare
                 * situation and management tools are smart.
                 */
                vm = NULL;
9208
                goto endjob;
C
Chris Lalancette 已提交
9209 9210 9211 9212 9213 9214 9215 9216 9217
            }

            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_DEFINED,
                                             newVM ?
                                             VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                             VIR_DOMAIN_EVENT_DEFINED_UPDATED);
            if (event)
                qemuDomainEventQueue(driver, event);
9218
            event = NULL;
C
Chris Lalancette 已提交
9219 9220

        }
9221
        qemuDomainObjPrivatePtr priv = vm->privateData;
D
Daniel Veillard 已提交
9222
        dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
9223

9224 9225 9226 9227 9228 9229 9230 9231
        if (!(flags & VIR_MIGRATE_PAUSED)) {
            /* run 'cont' on the destination, which allows migration on qemu
             * >= 0.10.6 to work properly.  This isn't strictly necessary on
             * older qemu's, but it also doesn't hurt anything there
             */
            qemuDomainObjEnterMonitorWithDriver(driver, vm);
            if (qemuMonitorStartCPUs(priv->mon, dconn) < 0) {
                if (virGetLastError() == NULL)
9232 9233
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("resume operation failed"));
9234 9235 9236
                qemuDomainObjExitMonitorWithDriver(driver, vm);
                goto endjob;
            }
9237
            qemuDomainObjExitMonitorWithDriver(driver, vm);
9238 9239

            vm->state = VIR_DOMAIN_RUNNING;
9240 9241
        }

9242 9243 9244
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
9245 9246 9247 9248 9249 9250
        if (vm->state == VIR_DOMAIN_PAUSED) {
            qemuDomainEventQueue(driver, event);
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_SUSPENDED,
                                             VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
        }
9251
        virDomainSaveStatus(driver->caps, driver->stateDir, vm);
D
Daniel Veillard 已提交
9252
    } else {
9253
        qemudShutdownVMDaemon(driver, vm);
9254 9255 9256
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
9257
        if (!vm->persistent) {
9258 9259
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains, vm);
9260 9261
            vm = NULL;
        }
D
Daniel Veillard 已提交
9262
    }
9263

9264
endjob:
9265 9266 9267
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
9268

9269
cleanup:
9270 9271 9272 9273
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
9274 9275
    if (vm)
        virDomainObjUnlock(vm);
9276 9277
    if (event)
        qemuDomainEventQueue(driver, event);
9278
    qemuDriverUnlock(driver);
9279
    return dom;
D
Daniel Veillard 已提交
9280 9281
}

9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297
static int
qemudNodeDeviceGetPciInfo (virNodeDevicePtr dev,
                           unsigned *domain,
                           unsigned *bus,
                           unsigned *slot,
                           unsigned *function)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

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

9298
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE);
9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315
    if (!def)
        goto out;

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

        cap = cap->next;
    }

    if (!cap) {
9316 9317
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("device %s is not a PCI device"), dev->name);
9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337
        goto out;
    }

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

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

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

9338
    pci = pciGetDevice(domain, bus, slot, function);
9339 9340 9341
    if (!pci)
        return -1;

9342
    if (pciDettachDevice(pci) < 0)
9343 9344 9345 9346
        goto out;

    ret = 0;
out:
9347
    pciFreeDevice(pci);
9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360
    return ret;
}

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

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

9361
    pci = pciGetDevice(domain, bus, slot, function);
9362 9363 9364
    if (!pci)
        return -1;

9365
    if (pciReAttachDevice(pci) < 0)
9366 9367 9368 9369
        goto out;

    ret = 0;
out:
9370
    pciFreeDevice(pci);
9371 9372 9373 9374 9375 9376
    return ret;
}

static int
qemudNodeDeviceReset (virNodeDevicePtr dev)
{
9377
    struct qemud_driver *driver = dev->conn->privateData;
9378 9379 9380 9381 9382 9383 9384
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

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

9385
    pci = pciGetDevice(domain, bus, slot, function);
9386 9387 9388
    if (!pci)
        return -1;

9389 9390
    qemuDriverLock(driver);

9391
    if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
9392 9393 9394 9395
        goto out;

    ret = 0;
out:
9396
    qemuDriverUnlock(driver);
9397
    pciFreeDevice(pci);
9398 9399 9400
    return ret;
}

9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411
static int
qemuCPUCompare(virConnectPtr conn,
               const char *xmlDesc,
               unsigned int flags ATTRIBUTE_UNUSED)
{
    struct qemud_driver *driver = conn->privateData;
    int ret = VIR_CPU_COMPARE_ERROR;

    qemuDriverLock(driver);

    if (!driver->caps || !driver->caps->host.cpu) {
9412 9413
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("cannot get host CPU capabilities"));
9414 9415
    }
    else
9416
        ret = cpuCompareXML(driver->caps->host.cpu, xmlDesc);
9417 9418 9419 9420 9421 9422

    qemuDriverUnlock(driver);

    return ret;
}

9423

9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436
static char *
qemuCPUBaseline(virConnectPtr conn ATTRIBUTE_UNUSED,
                const char **xmlCPUs,
                unsigned int ncpus,
                unsigned int flags ATTRIBUTE_UNUSED)
{
    char *cpu;

    cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0);

    return cpu;
}

9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479

static int qemuDomainGetJobInfo(virDomainPtr dom,
                                virDomainJobInfoPtr info) {
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    qemuDriverLock(driver);
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
    qemuDriverUnlock(driver);
    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
        goto cleanup;
    }

    priv = vm->privateData;

    if (virDomainObjIsActive(vm)) {
        if (priv->jobActive) {
            memcpy(info, &priv->jobInfo, sizeof(*info));
        } else {
            memset(info, 0, sizeof(*info));
            info->type = VIR_DOMAIN_JOB_NONE;
        }
    } else {
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
        goto cleanup;
    }

    ret = 0;

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


9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501
static int qemuDomainAbortJob(virDomainPtr dom) {
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    qemuDriverLock(driver);
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
    qemuDriverUnlock(driver);
    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
        goto cleanup;
    }

    priv = vm->privateData;

    if (virDomainObjIsActive(vm)) {
        if (priv->jobActive) {
            VIR_DEBUG("Requesting cancellation of job on vm %s", vm->def->name);
9502
            priv->jobSignals |= QEMU_JOB_SIGNAL_CANCEL;
9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522
        } else {
            qemuReportError(VIR_ERR_OPERATION_INVALID,
                            "%s", _("no job is active on the domain"));
            goto cleanup;
        }
    } else {
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
        goto cleanup;
    }

    ret = 0;

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


9523 9524 9525 9526 9527
static virDriver qemuDriver = {
    VIR_DRV_QEMU,
    "QEMU",
    qemudOpen, /* open */
    qemudClose, /* close */
D
Daniel Veillard 已提交
9528
    qemudSupportsFeature, /* supports_feature */
9529 9530
    qemudGetType, /* type */
    qemudGetVersion, /* version */
9531
    NULL, /* libvirtVersion (impl. in libvirt.c) */
9532
    virGetHostname, /* getHostname */
9533
    qemudGetMaxVCPUs, /* getMaxVcpus */
9534
    nodeGetInfo, /* nodeGetInfo */
9535 9536 9537
    qemudGetCapabilities, /* getCapabilities */
    qemudListDomains, /* listDomains */
    qemudNumDomains, /* numOfDomains */
9538
    qemudDomainCreate, /* domainCreateXML */
9539 9540 9541 9542 9543
    qemudDomainLookupByID, /* domainLookupByID */
    qemudDomainLookupByUUID, /* domainLookupByUUID */
    qemudDomainLookupByName, /* domainLookupByName */
    qemudDomainSuspend, /* domainSuspend */
    qemudDomainResume, /* domainResume */
9544
    qemudDomainShutdown, /* domainShutdown */
9545 9546 9547
    NULL, /* domainReboot */
    qemudDomainDestroy, /* domainDestroy */
    qemudDomainGetOSType, /* domainGetOSType */
9548
    qemudDomainGetMaxMemory, /* domainGetMaxMemory */
9549
    NULL, /* domainSetMaxMemory */
9550
    qemudDomainSetMemory, /* domainSetMemory */
9551 9552 9553
    qemudDomainGetInfo, /* domainGetInfo */
    qemudDomainSave, /* domainSave */
    qemudDomainRestore, /* domainRestore */
P
Paolo Bonzini 已提交
9554
    qemudDomainCoreDump, /* domainCoreDump */
9555
    qemudDomainSetVcpus, /* domainSetVcpus */
9556 9557
    qemudDomainPinVcpu, /* domainPinVcpu */
    qemudDomainGetVcpus, /* domainGetVcpus */
9558
    qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
9559 9560
    qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */
    qemudNodeGetSecurityModel, /* nodeGetSecurityModel */
9561
    qemudDomainDumpXML, /* domainDumpXML */
9562
    qemuDomainXMLFromNative, /* domainXmlFromNative */
9563
    qemuDomainXMLToNative, /* domainXMLToNative */
9564 9565
    qemudListDefinedDomains, /* listDefinedDomains */
    qemudNumDefinedDomains, /* numOfDefinedDomains */
9566 9567 9568
    qemudDomainStart, /* domainCreate */
    qemudDomainDefine, /* domainDefineXML */
    qemudDomainUndefine, /* domainUndefine */
9569
    qemudDomainAttachDevice, /* domainAttachDevice */
9570
    qemudDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
9571
    qemudDomainDetachDevice, /* domainDetachDevice */
9572
    qemudDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
9573 9574
    qemudDomainGetAutostart, /* domainGetAutostart */
    qemudDomainSetAutostart, /* domainSetAutostart */
9575 9576 9577
    qemuGetSchedulerType, /* domainGetSchedulerType */
    qemuGetSchedulerParameters, /* domainGetSchedulerParameters */
    qemuSetSchedulerParameters, /* domainSetSchedulerParameters */
D
Daniel Veillard 已提交
9578 9579
    NULL, /* domainMigratePrepare (v1) */
    qemudDomainMigratePerform, /* domainMigratePerform */
9580
    NULL, /* domainMigrateFinish */
9581
    qemudDomainBlockStats, /* domainBlockStats */
9582
    qemudDomainInterfaceStats, /* domainInterfaceStats */
9583
    qemudDomainMemoryStats, /* domainMemoryStats */
9584
    qemudDomainBlockPeek, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
9585
    qemudDomainMemoryPeek, /* domainMemoryPeek */
9586 9587
    nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    nodeGetFreeMemory,  /* getFreeMemory */
9588 9589
    qemudDomainEventRegister, /* domainEventRegister */
    qemudDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
9590 9591
    qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
    qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
9592 9593 9594
    qemudNodeDeviceDettach, /* nodeDeviceDettach */
    qemudNodeDeviceReAttach, /* nodeDeviceReAttach */
    qemudNodeDeviceReset, /* nodeDeviceReset */
C
Chris Lalancette 已提交
9595
    qemudDomainMigratePrepareTunnel, /* domainMigratePrepareTunnel */
9596 9597 9598 9599
    qemuIsEncrypted,
    qemuIsSecure,
    qemuDomainIsActive,
    qemuDomainIsPersistent,
9600
    qemuCPUCompare, /* cpuCompare */
9601
    qemuCPUBaseline, /* cpuBaseline */
9602
    qemuDomainGetJobInfo, /* domainGetJobInfo */
9603
    qemuDomainAbortJob, /* domainAbortJob */
9604
    NULL, /* domainMigrateSetMaxDowntime */
9605 9606 9607
};


9608
static virStateDriver qemuStateDriver = {
9609
    .name = "QEMU",
9610 9611 9612 9613
    .initialize = qemudStartup,
    .cleanup = qemudShutdown,
    .reload = qemudReload,
    .active = qemudActive,
9614
};
9615

9616
int qemuRegister(void) {
9617 9618 9619 9620
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}