qemu_driver.c 262.8 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
#include "virterror_internal.h"
51
#include "logging.h"
52
#include "datatypes.h"
53 54
#include "qemu_driver.h"
#include "qemu_conf.h"
55
#include "qemu_monitor.h"
56
#include "qemu_monitor_text.h"
57
#include "qemu_bridge_filter.h"
J
Jim Meyering 已提交
58
#include "c-ctype.h"
59
#include "event.h"
60
#include "buf.h"
61
#include "util.h"
62
#include "nodeinfo.h"
63
#include "stats_linux.h"
64
#include "capabilities.h"
65
#include "memory.h"
66
#include "uuid.h"
67
#include "domain_conf.h"
68 69
#include "node_device_conf.h"
#include "pci.h"
70
#include "hostusb.h"
71
#include "processinfo.h"
72 73
#include "qemu_security_stacked.h"
#include "qemu_security_dac.h"
74
#include "cgroup.h"
C
Chris Lalancette 已提交
75
#include "libvirt_internal.h"
76
#include "xml.h"
77
#include "cpu/cpu.h"
78
#include "macvtap.h"
79

80

81 82
#define VIR_FROM_THIS VIR_FROM_QEMU

83 84 85
typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
struct _qemuDomainObjPrivate {
86 87 88 89 90
    virCond jobCond; /* Use in conjunction with main virDomainObjPtr lock */
    int jobActive; /* Non-zero if a job is active. Only 1 job is allowed at any time
                    * A job includes *all* monitor commands, even those just querying
                    * information, not merely actions */

91
    qemuMonitorPtr mon;
92
    virDomainChrDefPtr monConfig;
D
Daniel P. Berrange 已提交
93
    int monJSON;
94 95 96

    int nvcpupids;
    int *vcpupids;
97 98

    qemuDomainPCIAddressSetPtr pciaddrs;
99
    int persistentAddrs;
100 101
};

102 103
static int qemudShutdown(void);

104 105
static void qemuDriverLock(struct qemud_driver *driver)
{
106
    virMutexLock(&driver->lock);
107 108 109
}
static void qemuDriverUnlock(struct qemud_driver *driver)
{
110
    virMutexUnlock(&driver->lock);
111 112
}

113 114 115
static void qemuDomainEventFlush(int timer, void *opaque);
static void qemuDomainEventQueue(struct qemud_driver *driver,
                                 virDomainEventPtr event);
116

117 118
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
119
                              virDomainObjPtr vm,
120 121
                              const char *migrateFrom,
                              int stdin_fd);
122

123
static void qemudShutdownVMDaemon(struct qemud_driver *driver,
124
                                  virDomainObjPtr vm);
125

126
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
127

128
static int qemuDetectVcpuPIDs(struct qemud_driver *driver,
129
                              virDomainObjPtr vm);
130

131 132 133
static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
                                       virDomainDefPtr def);

J
Jim Meyering 已提交
134
static struct qemud_driver *qemu_driver = NULL;
135

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

static void *qemuDomainObjPrivateAlloc(void)
{
    qemuDomainObjPrivatePtr priv;

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

    return priv;
}

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

151
    qemuDomainPCIAddressSetFree(priv->pciaddrs);
152 153 154
    virDomainChrDefFree(priv->monConfig);
    VIR_FREE(priv->vcpupids);

155 156 157 158 159 160 161 162 163
    /* 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);
}


164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
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 已提交
182 183
        if (priv->monJSON)
            virBufferAddLit(buf, " json='1'");
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
        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) {
210
        virReportOOMError();
211 212 213
        goto error;
    }

214
    if (!(priv->monConfig->info.alias = strdup("monitor"))) {
215
        virReportOOMError();
216 217 218
        goto error;
    }

219
    if (!(monitorpath =
220
          virXPathString("string(./monitor[1]/@path)", ctxt))) {
221 222
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no monitor path"));
223 224 225
        goto error;
    }

226
    tmp = virXPathString("string(./monitor[1]/@type)", ctxt);
227 228 229 230 231 232
    if (tmp)
        priv->monConfig->type = virDomainChrTypeFromString(tmp);
    else
        priv->monConfig->type = VIR_DOMAIN_CHR_TYPE_PTY;
    VIR_FREE(tmp);

233
    if (virXPathBoolean("count(./monitor[@json = '1']) > 0", ctxt)) {
D
Daniel P. Berrange 已提交
234
        priv->monJSON = 1;
235 236 237
    } else {
        priv->monJSON = 0;
    }
D
Daniel P. Berrange 已提交
238

239 240 241 242 243 244 245 246 247
    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);
248 249 250
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unsupported monitor type '%s'"),
                        virDomainChrTypeToString(priv->monConfig->type));
251 252 253
        goto error;
    }

254
    n = virXPathNodeSet("./vcpus/vcpu", ctxt, &nodes);
255 256 257 258 259
    if (n < 0)
        goto error;
    if (n) {
        priv->nvcpupids = n;
        if (VIR_REALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) {
260
            virReportOOMError();
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
            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:
281 282
    virDomainChrDefFree(priv->monConfig);
    priv->monConfig = NULL;
283 284 285 286 287 288
    VIR_FREE(nodes);
    return -1;
}



289 290 291 292 293 294 295 296 297
/*
 * 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
 */
298 299 300 301

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

302 303 304 305
static int qemuDomainObjBeginJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
static int qemuDomainObjBeginJob(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
306 307 308 309
    struct timeval now;
    unsigned long long then;

    if (gettimeofday(&now, NULL) < 0) {
310
        virReportSystemError(errno, "%s",
311 312 313 314 315
                             _("cannot get time of day"));
        return -1;
    }
    then = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
    then += QEMU_JOB_WAIT_TIME;
316 317 318 319

    virDomainObjRef(obj);

    while (priv->jobActive) {
320
        if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
321
            virDomainObjUnref(obj);
322
            if (errno == ETIMEDOUT)
323 324
                qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
                                "%s", _("cannot acquire state change lock"));
325
            else
326
                virReportSystemError(errno,
327
                                     "%s", _("cannot acquire job mutex"));
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
            return -1;
        }
    }
    priv->jobActive = 1;

    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;
348 349 350 351
    struct timeval now;
    unsigned long long then;

    if (gettimeofday(&now, NULL) < 0) {
352
        virReportSystemError(errno, "%s",
353 354 355 356 357
                             _("cannot get time of day"));
        return -1;
    }
    then = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
    then += QEMU_JOB_WAIT_TIME;
358 359 360 361 362

    virDomainObjRef(obj);
    qemuDriverUnlock(driver);

    while (priv->jobActive) {
363
        if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
364
            virDomainObjUnref(obj);
365
            if (errno == ETIMEDOUT)
366 367
                qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
                                "%s", _("cannot acquire state change lock"));
368
            else
369
                virReportSystemError(errno,
370
                                     "%s", _("cannot acquire job mutex"));
M
Matthias Bolte 已提交
371
            qemuDriverLock(driver);
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
            return -1;
        }
    }
    priv->jobActive = 1;

    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
389 390 391
 *
 * Returns remaining refcount on 'obj', maybe 0 to indicated it
 * was deleted
392
 */
393
static int ATTRIBUTE_RETURN_CHECK qemuDomainObjEndJob(virDomainObjPtr obj)
394 395 396 397 398 399
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    priv->jobActive = 0;
    virCondSignal(&priv->jobCond);

400
    return virDomainObjUnref(obj);
401 402 403 404 405 406 407 408 409 410 411
}


/*
 * 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
 */
412 413 414 415 416
static void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;

    qemuMonitorLock(priv->mon);
417
    qemuMonitorRef(priv->mon);
418
    virDomainObjUnlock(obj);
419 420 421
}


422 423 424 425
/* obj must NOT be locked before calling, qemud_driver must be unlocked
 *
 * Should be paired with an earlier  qemuDomainObjEnterMonitor() call
 */
426 427 428
static void qemuDomainObjExitMonitor(virDomainObjPtr obj)
{
    qemuDomainObjPrivatePtr priv = obj->privateData;
429 430 431 432 433 434
    int refs;

    refs = qemuMonitorUnref(priv->mon);

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

436
    virDomainObjLock(obj);
437 438 439 440 441

    if (refs == 0) {
        virDomainObjUnref(obj);
        priv->mon = NULL;
    }
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
}


/*
 * 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);
458
    qemuMonitorRef(priv->mon);
459 460 461 462 463 464 465 466 467 468 469 470 471
    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;
472 473 474 475 476 477
    int refs;

    refs = qemuMonitorUnref(priv->mon);

    if (refs > 0)
        qemuMonitorUnlock(priv->mon);
478 479 480

    qemuDriverLock(driver);
    virDomainObjLock(obj);
481 482 483 484 485

    if (refs == 0) {
        virDomainObjUnref(obj);
        priv->mon = NULL;
    }
486 487 488
}


489 490 491 492 493 494 495 496 497
static int qemuCgroupControllerActive(struct qemud_driver *driver,
                                      int controller)
{
    if (driver->cgroup == NULL)
        return 0;
    if (driver->cgroupControllers & (1 << controller))
        return 1;
    return 0;
}
498

499
static int
500
qemudLogFD(struct qemud_driver *driver, const char* name)
501 502 503
{
    char logfile[PATH_MAX];
    mode_t logmode;
G
Guido Günther 已提交
504
    int ret, fd = -1;
505

506 507
    if ((ret = snprintf(logfile, sizeof(logfile), "%s/%s.log",
                        driver->logDir, name))
G
Guido Günther 已提交
508
        < 0 || ret >= sizeof(logfile)) {
509
        virReportOOMError();
510 511 512 513
        return -1;
    }

    logmode = O_CREAT | O_WRONLY;
514 515
    /* Only logrotate files in /var/log, so only append if running privileged */
    if (driver->privileged)
516
        logmode |= O_APPEND;
517 518 519
    else
        logmode |= O_TRUNC;

520
    if ((fd = open(logfile, logmode, S_IRUSR | S_IWUSR)) < 0) {
521
        virReportSystemError(errno,
522 523
                             _("failed to create logfile %s"),
                             logfile);
524 525
        return -1;
    }
526
    if (virSetCloseExec(fd) < 0) {
527
        virReportSystemError(errno, "%s",
528
                             _("Unable to set VM logfile close-on-exec flag"));
529 530 531 532 533 534 535
        close(fd);
        return -1;
    }
    return fd;
}


536
static int
537
qemudLogReadFD(const char* logDir, const char* name, off_t pos)
538 539 540 541 542 543 544
{
    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)) {
545 546 547
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("failed to build logfile name %s/%s.log"),
                        logDir, name);
548 549 550 551 552
        return -1;
    }


    if ((fd = open(logfile, logmode)) < 0) {
553
        virReportSystemError(errno,
554 555
                             _("failed to create logfile %s"),
                             logfile);
556 557
        return -1;
    }
558
    if (virSetCloseExec(fd) < 0) {
559
        virReportSystemError(errno, "%s",
560
                             _("Unable to set VM logfile close-on-exec flag"));
561 562 563
        close(fd);
        return -1;
    }
564
    if (pos < 0 || lseek(fd, pos, SEEK_SET) < 0) {
565
      virReportSystemError(pos < 0 ? 0 : errno,
566 567
                             _("Unable to seek to %lld in %s"),
                             (long long) pos, logfile);
568 569 570 571 572 573
        close(fd);
    }
    return fd;
}


574 575 576 577 578 579 580 581 582 583 584 585
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 已提交
586
        !virDomainObjIsActive(vm)) {
587 588 589 590 591 592
        int ret;

        virResetLastError();
        ret = qemudStartVMDaemon(data->conn, data->driver, vm, NULL, -1);
        if (ret < 0) {
            virErrorPtr err = virGetLastError();
593
            VIR_ERROR(_("Failed to autostart VM '%s': %s"),
594 595 596 597 598 599 600 601 602 603 604 605 606 607
                      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);
}

608 609
static void
qemudAutostartConfigs(struct qemud_driver *driver) {
610 611 612 613 614
    /* 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
     */
615 616 617
    virConnectPtr conn = virConnectOpen(driver->privileged ?
                                        "qemu:///system" :
                                        "qemu:///session");
618
    /* Ignoring NULL conn which is mostly harmless here */
619
    struct qemuAutostartData data = { driver, conn };
620

621
    qemuDriverLock(driver);
622
    virHashForEach(driver->domains.objs, qemuAutostartDomain, &data);
623
    qemuDriverUnlock(driver);
624

625 626
    if (conn)
        virConnectClose(conn);
627 628
}

629 630 631 632 633 634 635 636 637

/**
 * qemudRemoveDomainStatus
 *
 * remove all state files of a domain from statedir
 *
 * Returns 0 on success
 */
static int
638
qemudRemoveDomainStatus(struct qemud_driver *driver,
639 640
                        virDomainObjPtr vm)
{
641
    char ebuf[1024];
642 643 644
    char *file = NULL;

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

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

654 655 656
    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)));
657

D
Daniel Veillard 已提交
658

659
    return 0;
660 661
}

662 663 664 665 666 667 668 669 670 671 672 673 674 675

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

676
    VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name);
677 678 679 680 681 682 683 684
    virDomainObjLock(vm);

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

685
    qemudShutdownVMDaemon(driver, vm);
686 687 688 689 690 691 692 693 694 695 696 697 698
    if (!vm->persistent)
        virDomainRemoveInactive(&driver->domains, vm);
    else
        virDomainObjUnlock(vm);

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


699 700 701
static virDomainDiskDefPtr
findDomainDiskByPath(virDomainObjPtr vm,
                     const char *path)
702 703 704 705 706 707 708
{
    int i;

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

        disk = vm->def->disks[i];
709 710
        if (disk->src != NULL && STREQ(disk->src, path))
            return disk;
711
    }
712 713 714 715

    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                    _("no disk found with path %s"),
                    path);
716 717 718 719
    return NULL;
}

static int
720 721 722 723
getVolumeQcowPassphrase(virConnectPtr conn,
                        virDomainDiskDefPtr disk,
                        char **secretRet,
                        size_t *secretLen)
724 725 726 727 728
{
    virSecretPtr secret;
    char *passphrase;
    unsigned char *data;
    size_t size;
729
    int ret = -1;
730
    virStorageEncryptionPtr enc;
731

732 733 734 735 736 737 738
    if (!disk->encryption) {
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("disk %s does not have any encryption information"),
                        disk->src);
        return -1;
    }
    enc = disk->encryption;
739 740

    if (!conn) {
741 742
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("cannot find secrets without a connection"));
743
        goto cleanup;
744 745 746 747 748
    }

    if (conn->secretDriver == NULL ||
        conn->secretDriver->lookupByUUID == NULL ||
        conn->secretDriver->getValue == NULL) {
749 750
        qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
                        _("secret storage not supported"));
751
        goto cleanup;
752 753 754 755 756 757
    }

    if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
        enc->nsecrets != 1 ||
        enc->secrets[0]->type !=
        VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) {
758
        qemuReportError(VIR_ERR_INVALID_DOMAIN,
759
                        _("invalid <encryption> for volume %s"), disk->src);
760
        goto cleanup;
761 762 763 764 765
    }

    secret = conn->secretDriver->lookupByUUID(conn,
                                              enc->secrets[0]->uuid);
    if (secret == NULL)
766
        goto cleanup;
767 768 769 770
    data = conn->secretDriver->getValue(secret, &size,
                                        VIR_SECRET_GET_VALUE_INTERNAL_CALL);
    virUnrefSecret(secret);
    if (data == NULL)
771
        goto cleanup;
772 773 774 775

    if (memchr(data, '\0', size) != NULL) {
        memset(data, 0, size);
        VIR_FREE(data);
776 777
        qemuReportError(VIR_ERR_INVALID_SECRET,
                        _("format='qcow' passphrase for %s must not contain a "
778
                          "'\\0'"), disk->src);
779
        goto cleanup;
780 781 782 783 784
    }

    if (VIR_ALLOC_N(passphrase, size + 1) < 0) {
        memset(data, 0, size);
        VIR_FREE(data);
785
        virReportOOMError();
786
        goto cleanup;
787 788 789 790 791 792 793 794 795 796
    }
    memcpy(passphrase, data, size);
    passphrase[size] = '\0';

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

    *secretRet = passphrase;
    *secretLen = size;

797 798 799
    ret = 0;

cleanup:
800 801
    return ret;
}
802

803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823
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);
824
    return ret;
825 826
}

827 828 829 830 831
static qemuMonitorCallbacks monitorCallbacks = {
    .eofNotify = qemuHandleMonitorEOF,
    .diskSecretLookup = findVolumeQcowPassphrase,
};

832
static int
833
qemuConnectMonitor(virDomainObjPtr vm)
834
{
835
    qemuDomainObjPrivatePtr priv = vm->privateData;
836

837 838 839 840
    /* Hold an extra reference because we can't allow 'vm' to be
     * deleted while the monitor is active */
    virDomainObjRef(vm);

841 842
    if ((priv->mon = qemuMonitorOpen(vm,
                                     priv->monConfig,
D
Daniel P. Berrange 已提交
843
                                     priv->monJSON,
844
                                     &monitorCallbacks)) == NULL) {
845
        VIR_ERROR(_("Failed to connect monitor for %s"), vm->def->name);
846
        return -1;
847
    }
848

849 850
    return 0;
}
851 852 853 854

/*
 * Open an existing VM's monitor, re-detect VCPU threads
 * and re-reserve the security labels in use
855
 */
856 857
static void
qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
858
{
859 860
    virDomainObjPtr obj = payload;
    struct qemud_driver *driver = opaque;
861
    qemuDomainObjPrivatePtr priv;
862
    unsigned long long qemuCmdFlags;
863 864

    virDomainObjLock(obj);
865

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

868 869
    priv = obj->privateData;

870 871
    /* XXX check PID liveliness & EXE path */
    if (qemuConnectMonitor(obj) < 0)
872
        goto error;
873

874 875 876 877
    if (qemuUpdateActivePciHostdevs(driver, obj->def) < 0) {
        goto error;
    }

878 879 880 881 882 883 884 885 886
    /* 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;

887 888 889
    if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(obj->def)))
        goto error;

890
    if (driver->securityDriver &&
891
        driver->securityDriver->domainReserveSecurityLabel &&
892
        driver->securityDriver->domainReserveSecurityLabel(obj) < 0)
893
        goto error;
894

895 896
    if (obj->def->id >= driver->nextvmid)
        driver->nextvmid = obj->def->id + 1;
897

898 899
    virDomainObjUnlock(obj);
    return;
900

901
error:
902 903 904
    /* 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 */
905
    qemudShutdownVMDaemon(driver, obj);
906 907 908 909
    if (!obj->persistent)
        virDomainRemoveInactive(&driver->domains, obj);
    else
        virDomainObjUnlock(obj);
910
}
911

912
/**
913
 * qemudReconnectDomains
914 915 916 917 918 919 920
 *
 * Try to re-open the resources for live VMs that we care
 * about.
 */
static void
qemuReconnectDomains(struct qemud_driver *driver)
{
921
    virHashForEach(driver->domains.objs, qemuReconnectDomain, driver);
922 923
}

924

925 926 927 928 929 930
static int
qemudSecurityInit(struct qemud_driver *qemud_drv)
{
    int ret;
    virSecurityDriverPtr security_drv;

931 932 933
    qemuSecurityStackedSetDriver(qemud_drv);
    qemuSecurityDACSetDriver(qemud_drv);

934 935 936 937 938 939
    ret = virSecurityDriverStartup(&security_drv,
                                   qemud_drv->securityDriverName);
    if (ret == -1) {
        VIR_ERROR0(_("Failed to start security driver"));
        return -1;
    }
940 941 942

    /* No primary security driver wanted to be enabled: just setup
     * the DAC driver on its own */
943
    if (ret == -2) {
944
        qemud_drv->securityDriver = &qemuDACSecurityDriver;
945
        VIR_INFO0(_("No security driver available"));
946 947 948 949 950
    } else {
        qemud_drv->securityPrimaryDriver = security_drv;
        qemud_drv->securitySecondaryDriver = &qemuDACSecurityDriver;
        qemud_drv->securityDriver = &qemuStackedSecurityDriver;
        VIR_INFO("Initialized security driver %s", security_drv->name);
951 952
    }

953
    return 0;
954
}
955 956


957 958
static virCapsPtr
qemuCreateCapabilities(virCapsPtr oldcaps,
959
                       struct qemud_driver *driver)
960 961 962 963 964
{
    virCapsPtr caps;

    /* Basic host arch / guest machine capabilities */
    if (!(caps = qemudCapsInit(oldcaps))) {
965
        virReportOOMError();
966 967 968 969 970 971 972 973 974 975 976
        return NULL;
    }

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


    /* Security driver data */
977
    if (driver->securityPrimaryDriver) {
978 979
        const char *doi, *model;

980 981
        doi = virSecurityDriverGetDOI(driver->securityPrimaryDriver);
        model = virSecurityDriverGetModel(driver->securityPrimaryDriver);
982 983 984 985 986 987 988 989 990 991 992 993 994

        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:
995
    virReportOOMError();
996 997 998
    virCapabilitiesFree(caps);
    return NULL;
}
999

1000 1001 1002 1003 1004 1005
/**
 * qemudStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
1006
qemudStartup(int privileged) {
1007
    char *base = NULL;
D
Daniel P. Berrange 已提交
1008
    char driverConf[PATH_MAX];
1009
    int rc;
1010

1011
    if (VIR_ALLOC(qemu_driver) < 0)
1012 1013
        return -1;

1014
    if (virMutexInit(&qemu_driver->lock) < 0) {
1015
        VIR_ERROR("%s", _("cannot initialize mutex"));
1016 1017 1018
        VIR_FREE(qemu_driver);
        return -1;
    }
1019
    qemuDriverLock(qemu_driver);
1020
    qemu_driver->privileged = privileged;
1021

1022 1023 1024
    /* Don't have a dom0 so start from 1 */
    qemu_driver->nextvmid = 1;

1025 1026 1027
    if (virDomainObjListInit(&qemu_driver->domains) < 0)
        goto out_of_memory;

1028
    /* Init callback list */
1029
    if (VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
1030
        goto out_of_memory;
1031 1032 1033 1034 1035 1036
    if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew()))
        goto out_of_memory;

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

1038
    if (privileged) {
1039 1040
        if (virAsprintf(&qemu_driver->logDir,
                        "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
1041
            goto out_of_memory;
1042

D
Daniel P. Berrange 已提交
1043
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
1044
            goto out_of_memory;
1045 1046

        if (virAsprintf(&qemu_driver->stateDir,
1047
                      "%s/run/libvirt/qemu", LOCAL_STATE_DIR) == -1)
1048
            goto out_of_memory;
1049 1050 1051 1052 1053 1054 1055 1056

        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;
1057
    } else {
1058
        uid_t uid = geteuid();
1059
        char *userdir = virGetUserDirectory(uid);
1060
        if (!userdir)
1061
            goto error;
1062

1063
        if (virAsprintf(&qemu_driver->logDir,
1064 1065
                        "%s/.libvirt/qemu/log", userdir) == -1) {
            VIR_FREE(userdir);
1066
            goto out_of_memory;
1067
        }
1068

1069 1070
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
            VIR_FREE(userdir);
1071
            goto out_of_memory;
1072 1073
        }
        VIR_FREE(userdir);
1074 1075 1076

        if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", base) == -1)
            goto out_of_memory;
1077 1078 1079 1080
        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;
1081 1082
    }

L
Laine Stump 已提交
1083
    if (virFileMakePath(qemu_driver->stateDir) != 0) {
1084
        char ebuf[1024];
1085
        VIR_ERROR(_("Failed to create state dir '%s': %s"),
1086
                  qemu_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
1087
        goto error;
1088
    }
L
Laine Stump 已提交
1089
    if (virFileMakePath(qemu_driver->libDir) != 0) {
1090
        char ebuf[1024];
1091
        VIR_ERROR(_("Failed to create lib dir '%s': %s"),
1092 1093 1094
                  qemu_driver->libDir, virStrerror(errno, ebuf, sizeof ebuf));
        goto error;
    }
L
Laine Stump 已提交
1095
    if (virFileMakePath(qemu_driver->cacheDir) != 0) {
1096
        char ebuf[1024];
1097
        VIR_ERROR(_("Failed to create cache dir '%s': %s"),
1098 1099 1100
                  qemu_driver->cacheDir, virStrerror(errno, ebuf, sizeof ebuf));
        goto error;
    }
1101 1102 1103 1104

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

1109
    if (virAsprintf(&qemu_driver->configDir, "%s/qemu", base) == -1)
1110 1111
        goto out_of_memory;

1112
    if (virAsprintf(&qemu_driver->autostartDir, "%s/qemu/autostart", base) == -1)
1113 1114
        goto out_of_memory;

1115
    VIR_FREE(base);
1116

1117 1118 1119 1120 1121 1122 1123
    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)));
    }

1124 1125 1126 1127
    if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
        goto error;
    }

1128 1129
    if (qemudSecurityInit(qemu_driver) < 0)
        goto error;
D
Daniel P. Berrange 已提交
1130

1131
    if ((qemu_driver->caps = qemuCreateCapabilities(NULL,
1132
                                                    qemu_driver)) == NULL)
1133
        goto error;
1134

1135
    if ((qemu_driver->activePciHostdevs = pciDeviceListNew()) == NULL)
1136 1137
        goto error;

1138 1139
    if (privileged) {
        if (chown(qemu_driver->libDir, qemu_driver->user, qemu_driver->group) < 0) {
1140
            virReportSystemError(errno,
1141 1142 1143 1144 1145
                                 _("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) {
1146
            virReportSystemError(errno,
1147 1148 1149 1150 1151 1152
                                 _("unable to set ownership of '%s' to %d:%d"),
                                 qemu_driver->cacheDir, qemu_driver->user, qemu_driver->group);
            goto error;
        }
    }

1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
    /* 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) {
1167
            virReportSystemError(rc,
1168 1169 1170 1171 1172 1173
                                 _("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) {
1174
            virReportSystemError(errno,
1175 1176 1177 1178 1179 1180 1181 1182 1183
                                 _("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;
    }

1184
    /* Get all the running persistent or transient configs first */
1185
    if (virDomainLoadAllConfigs(qemu_driver->caps,
1186 1187 1188 1189 1190 1191 1192 1193 1194
                                &qemu_driver->domains,
                                qemu_driver->stateDir,
                                NULL,
                                1, NULL, NULL) < 0)
        goto error;

    qemuReconnectDomains(qemu_driver);

    /* Then inactive persistent configs */
1195
    if (virDomainLoadAllConfigs(qemu_driver->caps,
1196 1197
                                &qemu_driver->domains,
                                qemu_driver->configDir,
1198
                                qemu_driver->autostartDir,
1199
                                0, NULL, NULL) < 0)
1200
        goto error;
1201 1202
    qemuDriverUnlock(qemu_driver);

1203 1204
    qemudAutostartConfigs(qemu_driver);

1205

1206 1207
    return 0;

1208
out_of_memory:
1209
    virReportOOMError();
1210 1211 1212
error:
    if (qemu_driver)
        qemuDriverUnlock(qemu_driver);
1213
    VIR_FREE(base);
1214
    qemudShutdown();
1215 1216 1217
    return -1;
}

1218 1219 1220 1221
static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
{
    struct qemud_driver *driver = opaque;

1222 1223 1224 1225 1226 1227 1228 1229
    if (newVM) {
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
        if (event)
            qemuDomainEventQueue(driver, event);
    }
1230 1231
}

1232 1233 1234 1235 1236 1237 1238 1239
/**
 * qemudReload:
 *
 * Function to restart the QEmu daemon, it will recheck the configuration
 * files and update its state and the networking
 */
static int
qemudReload(void) {
1240 1241 1242
    if (!qemu_driver)
        return 0;

1243
    qemuDriverLock(qemu_driver);
1244
    virDomainLoadAllConfigs(qemu_driver->caps,
1245 1246
                            &qemu_driver->domains,
                            qemu_driver->configDir,
1247
                            qemu_driver->autostartDir,
1248
                            0, qemudNotifyLoadDomain, qemu_driver);
1249
    qemuDriverUnlock(qemu_driver);
1250

1251
    qemudAutostartConfigs(qemu_driver);
1252 1253

    return 0;
1254 1255
}

1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
/**
 * 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) {
1266
    int active = 0;
1267

1268 1269 1270
    if (!qemu_driver)
        return 0;

1271
    /* XXX having to iterate here is not great because it requires many locks */
1272
    qemuDriverLock(qemu_driver);
1273
    active = virDomainObjListNumOfDomains(&qemu_driver->domains, 1);
1274 1275
    qemuDriverUnlock(qemu_driver);
    return active;
1276 1277
}

1278 1279 1280 1281 1282 1283 1284
/**
 * qemudShutdown:
 *
 * Shutdown the QEmu daemon, it will stop all active domains and networks
 */
static int
qemudShutdown(void) {
1285
    int i;
1286

1287
    if (!qemu_driver)
1288
        return -1;
1289

1290
    qemuDriverLock(qemu_driver);
1291
    pciDeviceListFree(qemu_driver->activePciHostdevs);
1292 1293
    virCapabilitiesFree(qemu_driver->caps);

1294
    virDomainObjListDeinit(&qemu_driver->domains);
1295

1296
    VIR_FREE(qemu_driver->securityDriverName);
1297
    VIR_FREE(qemu_driver->logDir);
1298 1299
    VIR_FREE(qemu_driver->configDir);
    VIR_FREE(qemu_driver->autostartDir);
1300
    VIR_FREE(qemu_driver->stateDir);
1301 1302
    VIR_FREE(qemu_driver->libDir);
    VIR_FREE(qemu_driver->cacheDir);
1303
    VIR_FREE(qemu_driver->vncTLSx509certdir);
J
Jim Meyering 已提交
1304
    VIR_FREE(qemu_driver->vncListen);
1305
    VIR_FREE(qemu_driver->vncPassword);
1306
    VIR_FREE(qemu_driver->vncSASLdir);
1307
    VIR_FREE(qemu_driver->saveImageFormat);
1308 1309
    VIR_FREE(qemu_driver->hugetlbfs_mount);
    VIR_FREE(qemu_driver->hugepage_path);
D
Daniel P. Berrange 已提交
1310

1311 1312 1313 1314 1315 1316
    if (qemu_driver->cgroupDeviceACL) {
        for (i = 0 ; qemu_driver->cgroupDeviceACL[i] != NULL ; i++)
            VIR_FREE(qemu_driver->cgroupDeviceACL[i]);
        VIR_FREE(qemu_driver->cgroupDeviceACL);
    }

1317 1318
    /* Free domain callback list */
    virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks);
1319 1320 1321 1322
    virDomainEventQueueFree(qemu_driver->domainEventQueue);

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

1324 1325 1326
    if (qemu_driver->brctl)
        brShutdown(qemu_driver->brctl);

1327 1328
    virCgroupFree(&qemu_driver->cgroup);

1329
    qemuDriverUnlock(qemu_driver);
1330
    virMutexDestroy(&qemu_driver->lock);
1331
    VIR_FREE(qemu_driver);
1332 1333

    return 0;
1334 1335
}

1336
typedef int qemuLogHandleOutput(virDomainObjPtr vm,
1337 1338
                                const char *output,
                                int fd);
1339 1340 1341 1342 1343

/*
 * Returns -1 for error, 0 on success
 */
static int
1344
qemudReadLogOutput(virDomainObjPtr vm,
1345 1346
                   int fd,
                   char *buf,
G
Guido Günther 已提交
1347
                   size_t buflen,
1348
                   qemuLogHandleOutput func,
1349 1350 1351
                   const char *what,
                   int timeout)
{
1352
    int retries = (timeout*10);
1353
    int got = 0;
1354 1355 1356
    buf[0] = '\0';

    while (retries) {
1357
        ssize_t func_ret, ret;
1358
        int isdead = 0;
G
Guido Günther 已提交
1359

1360
        func_ret = func(vm, buf, fd);
1361

1362 1363
        if (kill(vm->pid, 0) == -1 && errno == ESRCH)
            isdead = 1;
1364

1365 1366
        /* Any failures should be detected before we read the log, so we
         * always have something useful to report on failure. */
1367 1368
        ret = saferead(fd, buf+got, buflen-got-1);
        if (ret < 0) {
1369
            virReportSystemError(errno,
1370 1371 1372 1373 1374
                                 _("Failure while reading %s log output"),
                                 what);
            return -1;
        }

1375 1376 1377
        got += ret;
        buf[got] = '\0';
        if (got == buflen-1) {
1378
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
1379 1380
                            _("Out of space while reading %s log output: %s"),
                            what, buf);
1381 1382 1383 1384
            return -1;
        }

        if (isdead) {
1385
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
1386 1387
                            _("Process exited while reading %s log output: %s"),
                            what, buf);
1388 1389 1390
            return -1;
        }

1391 1392
        if (func_ret <= 0)
            return func_ret;
1393 1394 1395 1396

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

1398
    qemuReportError(VIR_ERR_INTERNAL_ERROR,
1399 1400
                    _("Timed out while reading %s log output: %s"),
                    what, buf);
1401 1402 1403
    return -1;
}

1404

1405 1406 1407 1408 1409 1410 1411 1412
/*
 * 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
 */
1413
static int
1414
qemudExtractTTYPath(const char *haystack,
1415 1416
                    size_t *offset,
                    char **path)
1417
{
1418
    static const char needle[] = "char device redirected to";
1419
    char *tmp, *dev;
1420

1421
    VIR_FREE(*path);
1422
    /* First look for our magic string */
1423 1424 1425 1426 1427
    if (!(tmp = strstr(haystack + *offset, needle))) {
        return 1;
    }
    tmp += sizeof(needle);
    dev = tmp;
1428

1429 1430 1431 1432 1433
    /*
     * And look for first whitespace character and nul terminate
     * to mark end of the pty path
     */
    while (*tmp) {
1434
        if (c_isspace(*tmp)) {
1435 1436
            *path = strndup(dev, tmp-dev);
            if (*path == NULL) {
1437
                virReportOOMError();
1438 1439
                return -1;
            }
1440

1441
            /* ... now further update offset till we get EOL */
1442
            *offset = tmp - haystack;
1443 1444
            return 0;
        }
1445
        tmp++;
1446 1447 1448 1449 1450
    }

    /*
     * We found a path, but didn't find any whitespace,
     * so it must be still incomplete - we should at
1451 1452
     * least see a \n - indicate that we want to carry
     * on trying again
1453
     */
1454
    return 1;
1455 1456
}

1457
static int
1458
qemudFindCharDevicePTYsMonitor(virDomainObjPtr vm,
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
                               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) {                                           \
1474 1475 1476
                if (chr->data.file.path == NULL) {                        \
                    /* neither the log output nor 'info chardev' had a */ \
                    /* pty path for this chardev, report an error */      \
1477 1478 1479
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,               \
                                    _("no assigned pty for device %s"), id); \
                    return -1;                                            \
1480 1481 1482 1483 1484
                } else {                                                  \
                    /* 'info chardev' had no pty path for this chardev, */\
                    /* but the log output had, so we're fine */           \
                    continue;                                             \
                }                                                         \
1485 1486
            }                                                             \
                                                                          \
1487
            VIR_FREE(chr->data.file.path);                                \
1488
            chr->data.file.path = strdup(path);                           \
1489 1490
                                                                          \
            if (chr->data.file.path == NULL) {                            \
1491
                virReportOOMError();                                      \
1492 1493
                return -1;                                                \
            }                                                             \
1494 1495 1496 1497 1498 1499
        }                                                                 \
    }

    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");
1500
#undef LOOKUP_PTYS
1501 1502 1503 1504

    return 0;
}

1505
static int
1506
qemudFindCharDevicePTYs(virDomainObjPtr vm,
1507 1508
                        const char *output,
                        int fd ATTRIBUTE_UNUSED)
1509
{
1510
    size_t offset = 0;
1511
    int ret, i;
1512 1513

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

1517
    /* first comes the serial devices */
1518 1519
    for (i = 0 ; i < vm->def->nserials ; i++) {
        virDomainChrDefPtr chr = vm->def->serials[i];
1520
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
1521
            if ((ret = qemudExtractTTYPath(output, &offset,
1522
                                           &chr->data.file.path)) != 0)
1523
                return ret;
1524 1525 1526
        }
    }

1527
    /* then the parallel devices */
1528 1529
    for (i = 0 ; i < vm->def->nparallels ; i++) {
        virDomainChrDefPtr chr = vm->def->parallels[i];
1530
        if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
1531
            if ((ret = qemudExtractTTYPath(output, &offset,
1532
                                           &chr->data.file.path)) != 0)
1533
                return ret;
1534 1535 1536
        }
    }

1537 1538 1539 1540
    /* 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) {
1541
            if ((ret = qemudExtractTTYPath(output, &offset,
1542 1543 1544 1545 1546
                                           &chr->data.file.path)) != 0)
                return ret;
        }
    }

1547
    return 0;
1548 1549
}

1550 1551 1552 1553 1554
static void qemudFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED)
{
    VIR_FREE(payload);
}

1555
static int
1556
qemudWaitForMonitor(struct qemud_driver* driver,
1557
                    virDomainObjPtr vm, off_t pos)
1558
{
1559
    char buf[4096]; /* Plenty of space to get startup greeting */
1560
    int logfd;
1561
    int ret = -1;
1562

1563
    if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos))
1564
        < 0)
1565
        return -1;
1566

1567
    ret = qemudReadLogOutput(vm, logfd, buf, sizeof(buf),
1568
                             qemudFindCharDevicePTYs,
1569
                             "console", 30);
1570
    if (close(logfd) < 0) {
1571
        char ebuf[4096];
1572
        VIR_WARN(_("Unable to close logfile: %s"),
1573 1574
                 virStrerror(errno, ebuf, sizeof ebuf));
    }
1575

1576
    if (ret < 0)
1577
        return -1;
1578

1579 1580
    VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
    if (qemuConnectMonitor(vm) < 0)
1581 1582
        return -1;

1583 1584 1585 1586 1587 1588
    /* 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) {
1589
        virReportOOMError();
1590 1591 1592
        goto cleanup;
    }

1593
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
1594 1595
    qemuDomainObjPrivatePtr priv = vm->privateData;
    ret = qemuMonitorGetPtyPaths(priv->mon, paths);
1596
    qemuDomainObjExitMonitorWithDriver(driver, vm);
1597 1598 1599

    VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret);
    if (ret == 0) {
1600
        ret = qemudFindCharDevicePTYsMonitor(vm, paths);
1601 1602 1603 1604 1605 1606 1607 1608
    }

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

    return ret;
1609 1610
}

1611
static int
1612
qemuDetectVcpuPIDs(struct qemud_driver *driver,
1613 1614 1615
                   virDomainObjPtr vm) {
    pid_t *cpupids = NULL;
    int ncpupids;
1616
    qemuDomainObjPrivatePtr priv = vm->privateData;
1617

1618
    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
1619 1620
        priv->nvcpupids = 1;
        if (VIR_ALLOC_N(priv->vcpupids, priv->nvcpupids) < 0) {
1621
            virReportOOMError();
1622 1623
            return -1;
        }
1624
        priv->vcpupids[0] = vm->pid;
1625 1626 1627
        return 0;
    }

1628
    /* What follows is now all KVM specific */
1629

1630
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
1631
    if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) < 0) {
1632
        qemuDomainObjExitMonitorWithDriver(driver, vm);
1633
        return -1;
1634
    }
1635
    qemuDomainObjExitMonitorWithDriver(driver, vm);
1636

1637 1638 1639
    /* Treat failure to get VCPU<->PID mapping as non-fatal */
    if (ncpupids == 0)
        return 0;
1640

1641
    if (ncpupids != vm->def->vcpus) {
1642 1643 1644
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("got wrong number of vCPU pids from QEMU monitor. got %d, wanted %d"),
                        ncpupids, (int)vm->def->vcpus);
1645 1646 1647
        VIR_FREE(cpupids);
        return -1;
    }
1648

1649 1650
    priv->nvcpupids = ncpupids;
    priv->vcpupids = cpupids;
1651 1652 1653
    return 0;
}

1654
static int
1655 1656
qemudInitCpuAffinity(virDomainObjPtr vm)
{
1657
    int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN;
1658
    virNodeInfo nodeinfo;
1659 1660
    unsigned char *cpumap;
    int cpumaplen;
1661
    qemuDomainObjPrivatePtr priv = vm->privateData;
1662

1663
    if (nodeGetInfo(NULL, &nodeinfo) < 0)
1664 1665 1666 1667
        return -1;

    /* setaffinity fails if you set bits for CPUs which
     * aren't present, so we have to limit ourselves */
1668 1669 1670
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
1671

1672 1673
    cpumaplen = VIR_CPU_MAPLEN(maxcpu);
    if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
1674
        virReportOOMError();
1675 1676 1677
        return -1;
    }

D
Daniel P. Berrange 已提交
1678
    if (vm->def->cpumask) {
1679 1680 1681
        /* 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 已提交
1682
            if (vm->def->cpumask[i])
1683
                VIR_USE_CPU(cpumap, i);
D
Daniel P. Berrange 已提交
1684
    } else {
1685 1686 1687 1688
        /* 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 已提交
1689
        for (i = 0 ; i < maxcpu ; i++)
1690
            VIR_USE_CPU(cpumap, i);
D
Daniel P. Berrange 已提交
1691
    }
1692

1693 1694
    /* The XML config only gives a per-VM affinity, so we apply
     * the same mapping to all vCPUs */
1695 1696
    for (i = 0 ; i < priv->nvcpupids ; i++) {
        if (virProcessInfoSetAffinity(priv->vcpupids[i],
1697 1698
                                      cpumap, cpumaplen, maxcpu) < 0) {
            VIR_FREE(cpumap);
1699 1700 1701
            return -1;
        }
    }
1702
    VIR_FREE(cpumap);
1703 1704 1705 1706 1707

    return 0;
}


1708
static int
1709 1710 1711 1712
qemuInitPasswords(virConnectPtr conn,
                  struct qemud_driver *driver,
                  virDomainObjPtr vm,
                  unsigned long long qemuCmdFlags) {
1713
    int ret = 0;
1714
    qemuDomainObjPrivatePtr priv = vm->privateData;
1715

1716 1717 1718
    if ((vm->def->ngraphics == 1) &&
        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        (vm->def->graphics[0]->data.vnc.passwd || driver->vncPassword)) {
1719

1720
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
1721
        ret = qemuMonitorSetVNCPassword(priv->mon,
1722 1723 1724
                                        vm->def->graphics[0]->data.vnc.passwd ?
                                        vm->def->graphics[0]->data.vnc.passwd :
                                        driver->vncPassword);
1725
        qemuDomainObjExitMonitorWithDriver(driver, vm);
1726 1727
    }

1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757
    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);
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            if (ret < 0)
                goto cleanup;
        }
    }

cleanup:
1758
    return ret;
1759 1760 1761
}


1762 1763 1764 1765 1766 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 1792 1793 1794 1795 1796 1797 1798 1799 1800 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
#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
1991
qemuDetectPCIAddresses(virDomainObjPtr vm,
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
                       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) {
2009 2010 2011
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for VirtIO disk %s"),
                            vm->def->disks[i]->dst);
2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
            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) {
2023 2024 2025
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for %s NIC"),
                            vm->def->nets[i]->model);
2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
            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) {
2037 2038 2039
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for controller %s"),
                            virDomainControllerTypeToString(vm->def->controllers[i]->type));
2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
            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) {
2051 2052 2053
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for video adapter %s"),
                            virDomainVideoTypeToString(vm->def->videos[i]->type));
2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
            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) {
2065 2066 2067
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for sound adapter %s"),
                            virDomainSoundModelTypeToString(vm->def->sounds[i]->model));
2068 2069 2070 2071 2072 2073 2074 2075 2076 2077
            return -1;
        }
    }


    if (vm->def->watchdog &&
        qemuGetPCIWatchdogVendorProduct(vm->def->watchdog, &vendor, &product) == 0) {
        if (qemuAssignNextPCIAddress(&(vm->def->watchdog->info),
                                     vendor, product,
                                     addrs,  naddrs) < 0) {
2078 2079 2080
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("cannot find PCI address for watchdog %s"),
                            virDomainWatchdogModelTypeToString(vm->def->watchdog->model));
2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112
            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);

2113
    ret = qemuDetectPCIAddresses(vm, addrs, naddrs);
2114 2115 2116 2117 2118 2119

    VIR_FREE(addrs);

    return ret;
}

2120
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
2121 2122 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 2155
    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;
}

2156 2157 2158 2159 2160 2161 2162 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

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


2194
static pciDeviceList *
2195
qemuGetPciHostDeviceList(virDomainDefPtr def)
2196 2197
{
    pciDeviceList *list;
2198 2199
    int i;

2200
    if (!(list = pciDeviceListNew()))
2201
        return NULL;
2202 2203 2204 2205 2206 2207 2208 2209 2210 2211

    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;

2212
        dev = pciGetDevice(hostdev->source.subsys.u.pci.domain,
2213 2214 2215
                           hostdev->source.subsys.u.pci.bus,
                           hostdev->source.subsys.u.pci.slot,
                           hostdev->source.subsys.u.pci.function);
2216
        if (!dev) {
2217
            pciDeviceListFree(list);
2218 2219
            return NULL;
        }
2220

2221 2222 2223
        if (pciDeviceListAdd(list, dev) < 0) {
            pciFreeDevice(dev);
            pciDeviceListFree(list);
2224
            return NULL;
2225 2226
        }

2227
        pciDeviceSetManaged(dev, hostdev->managed);
2228 2229
    }

2230 2231 2232 2233
    return list;
}

static int
2234 2235 2236 2237
qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
                            virDomainDefPtr def)
{
    pciDeviceList *pcidevs;
2238
    int i;
2239
    int ret = -1;
2240 2241 2242 2243

    if (!def->nhostdevs)
        return 0;

2244
    if (!(pcidevs = qemuGetPciHostDeviceList(def)))
2245 2246
        return -1;

2247 2248
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2249 2250 2251
        pciDeviceListSteal(pcidevs, dev);
        if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
            pciFreeDevice(dev);
2252
            goto cleanup;
2253 2254 2255
        }
    }

2256 2257 2258
    ret = 0;

cleanup:
2259
    pciDeviceListFree(pcidevs);
2260 2261 2262 2263
    return ret;
}

static int
2264
qemuPrepareHostDevices(struct qemud_driver *driver,
2265
                       virDomainDefPtr def)
2266 2267 2268
{
    pciDeviceList *pcidevs;
    int i;
2269
    int ret = -1;
2270 2271 2272 2273

    if (!def->nhostdevs)
        return 0;

2274
    if (!(pcidevs = qemuGetPciHostDeviceList(def)))
2275 2276
        return -1;

2277
    /* We have to use 3 loops here. *All* devices must
2278 2279
     * be detached before we reset any of them, because
     * in some cases you have to reset the whole PCI,
2280 2281
     * which impacts all devices on it. Also, all devices
     * must be reset before being marked as active.
2282 2283 2284 2285 2286 2287 2288
     */

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

2289 2290
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2291
        if (!pciDeviceIsAssignable(dev, !driver->relaxedACS))
2292 2293
            goto cleanup;

2294
        if (pciDeviceGetManaged(dev) &&
2295
            pciDettachDevice(dev) < 0)
2296 2297
            goto cleanup;
    }
2298 2299 2300

    /* Now that all the PCI hostdevs have be dettached, we can safely
     * reset them */
2301 2302
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2303
        if (pciResetDevice(dev, driver->activePciHostdevs) < 0)
2304 2305
            goto cleanup;
    }
2306

2307
    /* Now mark all the devices as active */
2308 2309
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2310 2311 2312
        pciDeviceListSteal(pcidevs, dev);
        if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
            pciFreeDevice(dev);
2313 2314
            goto cleanup;
        }
2315 2316
    }

2317
    ret = 0;
2318

2319
cleanup:
2320
    pciDeviceListFree(pcidevs);
2321
    return ret;
2322 2323
}

2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334
static void
qemudReattachManagedDevice(pciDevice *dev)
{
    int retries = 100;

    if (pciDeviceGetManaged(dev)) {
        while (pciWaitForDeviceCleanup(dev, "kvm_assigned_device")
               && retries) {
            usleep(100*1000);
            retries--;
        }
2335
        if (pciReAttachDevice(dev) < 0) {
2336 2337 2338 2339 2340 2341 2342 2343
            virErrorPtr err = virGetLastError();
            VIR_ERROR(_("Failed to re-attach PCI device: %s"),
                      err ? err->message : "");
            virResetError(err);
        }
    }
}

2344
static void
2345
qemuDomainReAttachHostDevices(struct qemud_driver *driver,
2346
                              virDomainDefPtr def)
2347
{
2348
    pciDeviceList *pcidevs;
2349 2350
    int i;

2351 2352
    if (!def->nhostdevs)
        return;
2353

2354
    if (!(pcidevs = qemuGetPciHostDeviceList(def))) {
2355
        virErrorPtr err = virGetLastError();
2356
        VIR_ERROR(_("Failed to allocate pciDeviceList: %s"),
2357 2358 2359
                  err ? err->message : "");
        virResetError(err);
        return;
2360 2361
    }

2362 2363
    /* Again 3 loops; mark all devices as inactive before reset
     * them and reset all the devices before re-attach */
2364

2365 2366
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2367
        pciDeviceListDel(driver->activePciHostdevs, dev);
2368
    }
2369

2370 2371
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2372
        if (pciResetDevice(dev, driver->activePciHostdevs) < 0) {
2373
            virErrorPtr err = virGetLastError();
2374
            VIR_ERROR(_("Failed to reset PCI device: %s"),
2375 2376 2377
                      err ? err->message : "");
            virResetError(err);
        }
2378
    }
2379

2380 2381
    for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
        pciDevice *dev = pciDeviceListGet(pcidevs, i);
2382
        qemudReattachManagedDevice(dev);
2383
    }
2384

2385
    pciDeviceListFree(pcidevs);
2386 2387
}

2388 2389 2390 2391 2392 2393 2394 2395 2396 2397
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

2398
static int qemuSetupCgroup(struct qemud_driver *driver,
2399 2400 2401 2402
                           virDomainObjPtr vm)
{
    virCgroupPtr cgroup = NULL;
    int rc;
2403
    unsigned int i;
2404 2405 2406 2407
    const char *const *deviceACL =
        driver->cgroupDeviceACL ?
        (const char *const *)driver->cgroupDeviceACL :
        defaultDeviceACL;
2408 2409 2410 2411 2412 2413

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

    rc = virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 1);
    if (rc != 0) {
2414
        virReportSystemError(-rc,
2415 2416 2417 2418 2419
                             _("Unable to create cgroup for %s"),
                             vm->def->name);
        goto cleanup;
    }

2420 2421
    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
        rc = virCgroupDenyAllDevices(cgroup);
2422
        if (rc != 0) {
2423 2424 2425 2426 2427
            if (rc == -EPERM) {
                VIR_WARN0("Group devices ACL is not accessible, disabling whitelisting");
                goto done;
            }

2428
            virReportSystemError(-rc,
2429
                                 _("Unable to deny all devices for %s"), vm->def->name);
2430 2431 2432
            goto cleanup;
        }

2433 2434 2435 2436 2437 2438 2439 2440
        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) {
2441
                virReportSystemError(-rc,
2442 2443 2444 2445 2446
                                     _("Unable to allow device %s for %s"),
                                     vm->def->disks[i]->src, vm->def->name);
                goto cleanup;
            }
        }
2447

2448
        rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR);
2449
        if (rc != 0) {
2450
            virReportSystemError(-rc, "%s",
2451
                                 _("unable to allow /dev/pts/ devices"));
2452 2453 2454
            goto cleanup;
        }

2455 2456 2457
        if (vm->def->nsounds) {
            rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_SND_MAJOR);
            if (rc != 0) {
2458
                virReportSystemError(-rc, "%s",
2459 2460 2461 2462 2463 2464 2465 2466 2467 2468
                                     _("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) {
2469
                virReportSystemError(-rc,
2470 2471 2472 2473
                                     _("unable to allow device %s"),
                                     deviceACL[i]);
                goto cleanup;
            }
2474 2475 2476 2477
        }
    }

done:
2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489
    virCgroupFree(&cgroup);
    return 0;

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


2490
static int qemuRemoveCgroup(struct qemud_driver *driver,
2491 2492
                            virDomainObjPtr vm,
                            int quiet)
2493 2494 2495 2496 2497 2498 2499 2500 2501
{
    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) {
2502
        if (!quiet)
2503 2504 2505
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Unable to find cgroup for %s\n"),
                            vm->def->name);
2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525
        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) {
2526
        virReportSystemError(-rc,
2527 2528 2529 2530 2531 2532 2533
                             _("unable to find cgroup for domain %s"),
                             def->name);
        goto cleanup;
    }

    rc = virCgroupAddTask(cgroup, getpid());
    if (rc != 0) {
2534
        virReportSystemError(-rc,
2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551
                             _("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;
2552 2553 2554
};

static int qemudSecurityHook(void *data) {
2555 2556 2557 2558
    struct qemudHookData *h = data;

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

2560 2561
    if (h->driver->securityDriver &&
        h->driver->securityDriver->domainSetSecurityProcessLabel &&
2562
        h->driver->securityDriver->domainSetSecurityProcessLabel(h->driver->securityDriver, h->vm) < 0)
2563 2564 2565
        return -1;

    return 0;
2566 2567
}

2568
static int
2569
qemuPrepareMonitorChr(struct qemud_driver *driver,
2570
                      virDomainChrDefPtr monConfig,
2571 2572
                      const char *vm)
{
2573
    monConfig->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_MONITOR;
2574

2575 2576
    monConfig->type = VIR_DOMAIN_CHR_TYPE_UNIX;
    monConfig->data.nix.listen = 1;
2577

D
Daniel P. Berrange 已提交
2578
    if (!(monConfig->info.alias = strdup("monitor"))) {
2579
        virReportOOMError();
D
Daniel P. Berrange 已提交
2580 2581 2582
        return -1;
    }

2583
    if (virAsprintf(&monConfig->data.nix.path, "%s/%s.monitor",
2584
                    driver->libDir, vm) < 0) {
2585
        virReportOOMError();
2586 2587 2588 2589 2590 2591
        return -1;
    }

    return 0;
}

2592 2593
static int qemudStartVMDaemon(virConnectPtr conn,
                              struct qemud_driver *driver,
2594
                              virDomainObjPtr vm,
2595 2596
                              const char *migrateFrom,
                              int stdin_fd) {
2597
    const char **argv = NULL, **tmp;
2598
    const char **progenv = NULL;
2599
    int i, ret;
2600
    struct stat sb;
2601 2602
    int *tapfds = NULL;
    int ntapfds = 0;
2603
    unsigned long long qemuCmdFlags;
2604
    fd_set keepfd;
2605
    const char *emulator;
G
Guido Günther 已提交
2606
    pid_t child;
2607
    int pos = -1;
2608
    char ebuf[1024];
2609
    char *pidfile = NULL;
2610
    int logfile;
2611
    qemuDomainObjPrivatePtr priv = vm->privateData;
2612

2613
    struct qemudHookData hookData;
2614 2615 2616 2617
    hookData.conn = conn;
    hookData.vm = vm;
    hookData.driver = driver;

2618
    FD_ZERO(&keepfd);
2619

D
Daniel P. Berrange 已提交
2620
    if (virDomainObjIsActive(vm)) {
2621 2622
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("VM is already active"));
2623 2624 2625
        return -1;
    }

2626 2627
    /* If you are using a SecurityDriver with dynamic labelling,
       then generate a security label for isolation */
2628
    if (driver->securityDriver &&
2629
        driver->securityDriver->domainGenSecurityLabel &&
2630
        driver->securityDriver->domainGenSecurityLabel(vm) < 0)
2631 2632
        return -1;

2633 2634
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityAllLabel &&
2635
        driver->securityDriver->domainSetSecurityAllLabel(vm) < 0)
2636 2637
        goto cleanup;

2638
    /* Ensure no historical cgroup for this VM is lieing around bogus settings */
2639
    qemuRemoveCgroup(driver, vm, 1);
2640

2641 2642 2643
    if ((vm->def->ngraphics == 1) &&
        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics[0]->data.vnc.autoport) {
2644
        int port = qemudNextFreeVNCPort(driver);
2645
        if (port < 0) {
2646 2647
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("Unable to find an unused VNC port"));
2648
            goto cleanup;
2649
        }
2650
        vm->def->graphics[0]->data.vnc.port = port;
2651
    }
2652

L
Laine Stump 已提交
2653
    if (virFileMakePath(driver->logDir) != 0) {
2654
        virReportSystemError(errno,
2655 2656
                             _("cannot create log directory %s"),
                             driver->logDir);
2657
        goto cleanup;
2658 2659
    }

2660
    if ((logfile = qemudLogFD(driver, vm->def->name)) < 0)
2661
        goto cleanup;
2662

2663 2664
    emulator = vm->def->emulator;

2665 2666 2667 2668
    /* 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
     */
2669
    if (stat(emulator, &sb) < 0) {
2670
        virReportSystemError(errno,
2671 2672
                             _("Cannot find QEMU binary %s"),
                             emulator);
2673
        goto cleanup;
2674 2675
    }

2676
    if (qemudExtractVersionInfo(emulator,
2677
                                NULL,
2678
                                &qemuCmdFlags) < 0)
2679
        goto cleanup;
2680

2681
    if (qemuSetupCgroup(driver, vm) < 0)
2682 2683
        goto cleanup;

2684
    if (qemuPrepareHostDevices(driver, vm->def) < 0)
2685
        goto cleanup;
2686

2687
    if (VIR_ALLOC(priv->monConfig) < 0) {
2688
        virReportOOMError();
2689 2690 2691
        goto cleanup;
    }

2692
    if (qemuPrepareMonitorChr(driver, priv->monConfig, vm->def->name) < 0)
2693
        goto cleanup;
2694

D
Daniel P. Berrange 已提交
2695 2696 2697
#if HAVE_YAJL
    if (qemuCmdFlags & QEMUD_CMD_FLAG_MONITOR_JSON)
        priv->monJSON = 1;
2698
    else
D
Daniel P. Berrange 已提交
2699
#endif
2700
        priv->monJSON = 0;
D
Daniel P. Berrange 已提交
2701

D
Daniel P. Berrange 已提交
2702
    if ((ret = virFileDeletePid(driver->stateDir, vm->def->name)) != 0) {
2703
        virReportSystemError(ret,
D
Daniel P. Berrange 已提交
2704 2705 2706 2707 2708
                             _("Cannot remove stale PID file for %s"),
                             vm->def->name);
        goto cleanup;
    }

2709
    if (!(pidfile = virFilePid(driver->stateDir, vm->def->name))) {
2710
        virReportSystemError(errno,
2711 2712 2713
                             "%s", _("Failed to build pidfile path."));
        goto cleanup;
    }
D
Daniel P. Berrange 已提交
2714

2715 2716 2717 2718 2719 2720 2721
    /*
     * Normally PCI addresses are assigned inhe virDomainCreate
     * 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
     */
2722
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
2723
        /* Populate cache with current addresses */
2724 2725 2726 2727 2728 2729 2730
        if (priv->pciaddrs) {
            qemuDomainPCIAddressSetFree(priv->pciaddrs);
            priv->pciaddrs = NULL;
        }
        if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(vm->def)))
            goto cleanup;

2731 2732

        /* Assign any remaining addresses */
2733 2734
        if (qemuAssignDevicePCISlots(vm->def, priv->pciaddrs) < 0)
            goto cleanup;
2735 2736 2737 2738

        priv->persistentAddrs = 1;
    } else {
        priv->persistentAddrs = 0;
2739 2740
    }

2741
    vm->def->id = driver->nextvmid++;
2742
    if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
D
Daniel P. Berrange 已提交
2743
                              priv->monJSON, qemuCmdFlags, &argv, &progenv,
2744 2745
                              &tapfds, &ntapfds, migrateFrom) < 0)
        goto cleanup;
2746

2747 2748
    tmp = progenv;
    while (*tmp) {
2749
        if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
2750
            VIR_WARN(_("Unable to write envv to logfile: %s"),
2751
                     virStrerror(errno, ebuf, sizeof ebuf));
2752
        if (safewrite(logfile, " ", 1) < 0)
2753
            VIR_WARN(_("Unable to write envv to logfile: %s"),
2754
                     virStrerror(errno, ebuf, sizeof ebuf));
2755 2756
        tmp++;
    }
2757 2758
    tmp = argv;
    while (*tmp) {
2759
        if (safewrite(logfile, *tmp, strlen(*tmp)) < 0)
2760
            VIR_WARN(_("Unable to write argv to logfile: %s"),
2761
                     virStrerror(errno, ebuf, sizeof ebuf));
2762
        if (safewrite(logfile, " ", 1) < 0)
2763
            VIR_WARN(_("Unable to write argv to logfile: %s"),
2764
                     virStrerror(errno, ebuf, sizeof ebuf));
2765 2766
        tmp++;
    }
2767
    if (safewrite(logfile, "\n", 1) < 0)
2768
        VIR_WARN(_("Unable to write argv to logfile: %s"),
2769
                 virStrerror(errno, ebuf, sizeof ebuf));
2770

2771
    if ((pos = lseek(logfile, 0, SEEK_END)) < 0)
2772
        VIR_WARN(_("Unable to seek to end of logfile: %s"),
2773
                 virStrerror(errno, ebuf, sizeof ebuf));
2774

2775 2776 2777
    for (i = 0 ; i < ntapfds ; i++)
        FD_SET(tapfds[i], &keepfd);

2778
    ret = virExecDaemonize(argv, progenv, &keepfd, &child,
2779
                           stdin_fd, &logfile, &logfile,
2780
                           VIR_EXEC_NONBLOCK | VIR_EXEC_CLEAR_CAPS,
2781 2782 2783
                           qemudSecurityHook, &hookData,
                           pidfile);
    VIR_FREE(pidfile);
G
Guido Günther 已提交
2784 2785 2786

    /* wait for qemu process to to show up */
    if (ret == 0) {
2787
        if (virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) {
2788 2789
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Domain %s didn't show up\n"), vm->def->name);
2790
            ret = -1;
G
Guido Günther 已提交
2791
        }
2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802
    } 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;
    }
2803 2804

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

2806
    for (i = 0 ; argv[i] ; i++)
2807 2808
        VIR_FREE(argv[i]);
    VIR_FREE(argv);
2809

2810 2811 2812 2813
    for (i = 0 ; progenv[i] ; i++)
        VIR_FREE(progenv[i]);
    VIR_FREE(progenv);

2814 2815 2816
    if (tapfds) {
        for (i = 0 ; i < ntapfds ; i++) {
            close(tapfds[i]);
2817
        }
2818
        VIR_FREE(tapfds);
2819 2820
    }

2821
    if (ret == -1) /* The VM failed to start */
2822 2823
        goto cleanup;

2824
    if (qemudWaitForMonitor(driver, vm, pos) < 0)
2825 2826
        goto abort;

2827
    if (qemuDetectVcpuPIDs(driver, vm) < 0)
2828 2829
        goto abort;

2830
    if (qemudInitCpuAffinity(vm) < 0)
2831 2832
        goto abort;

2833
    if (qemuInitPasswords(conn, driver, vm, qemuCmdFlags) < 0)
2834 2835
        goto abort;

D
Daniel P. Berrange 已提交
2836 2837 2838 2839 2840 2841
    /* 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)) {
        if (qemuInitPCIAddresses(driver, vm) < 0)
            goto abort;
    }
2842

2843
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
2844
    if (qemuMonitorSetBalloon(priv->mon, vm->def->memory) < 0) {
2845
        qemuDomainObjExitMonitorWithDriver(driver, vm);
2846
        goto abort;
2847
    }
2848 2849 2850 2851 2852

    if (migrateFrom == NULL) {
        /* Allow the CPUS to start executing */
        if (qemuMonitorStartCPUs(priv->mon, conn) < 0) {
            if (virGetLastError() == NULL)
2853 2854
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("resume operation failed"));
2855 2856 2857 2858
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            goto abort;
        }
    }
2859
    qemuDomainObjExitMonitorWithDriver(driver, vm);
2860

2861

2862
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
2863
        goto abort;
2864

2865
    return 0;
2866 2867

cleanup:
2868 2869 2870
    /* 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 */
2871
    qemuDomainReAttachHostDevices(driver, vm->def);
2872

2873 2874
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityAllLabel)
2875
        driver->securityDriver->domainRestoreSecurityAllLabel(vm);
2876 2877
    if (driver->securityDriver &&
        driver->securityDriver->domainReleaseSecurityLabel)
2878
        driver->securityDriver->domainReleaseSecurityLabel(vm);
2879
    qemuRemoveCgroup(driver, vm, 0);
2880 2881 2882 2883
    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;
2884 2885
    if (logfile != -1)
        close(logfile);
2886 2887
    vm->def->id = -1;
    return -1;
2888 2889 2890 2891

abort:
    /* We jump here if we failed to initialize the now running VM
     * killing it off and pretend we never started it */
2892
    qemudShutdownVMDaemon(driver, vm);
2893 2894 2895 2896 2897

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

    return -1;
2898 2899 2900
}


2901
static void qemudShutdownVMDaemon(struct qemud_driver *driver,
2902
                                  virDomainObjPtr vm) {
D
Daniel P. Berrange 已提交
2903
    int ret;
2904
    int retries = 0;
2905
    qemuDomainObjPrivatePtr priv = vm->privateData;
2906
    virErrorPtr orig_err;
2907 2908
    virDomainDefPtr def;
    int i;
D
Daniel P. Berrange 已提交
2909

D
Daniel P. Berrange 已提交
2910
    if (!virDomainObjIsActive(vm))
2911
        return;
2912

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

2915 2916 2917 2918
    /* This method is routinely used in clean up paths. Disable error
     * reporting so we don't squash a legit error. */
    orig_err = virSaveLastError();

2919
    if (driver->macFilter) {
2920
        def = vm->def;
2921 2922 2923 2924
        for (i = 0 ; i < def->nnets ; i++) {
            virDomainNetDefPtr net = def->nets[i];
            if (net->ifname == NULL)
                continue;
2925
            if ((errno = networkDisallowMacOnPort(driver, net->ifname,
2926
                                                  net->mac))) {
2927
                virReportSystemError(errno,
2928 2929 2930 2931 2932 2933
             _("failed to remove ebtables rule to allow MAC address on  '%s'"),
                                     net->ifname);
            }
        }
    }

2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944
#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) {
            int dummy;
            delMacvtapByMACAddress(net->mac, &dummy);
        }
    }
#endif

G
Guido Günther 已提交
2945 2946
    if (virKillProcess(vm->pid, 0) == 0 &&
        virKillProcess(vm->pid, SIGTERM) < 0)
2947
        virReportSystemError(errno,
2948 2949
                             _("Failed to send SIGTERM to %s (%d)"),
                             vm->def->name, vm->pid);
2950

2951 2952 2953
    if (priv->mon &&
        qemuMonitorClose(priv->mon) == 0) {
        virDomainObjUnref(vm);
2954
        priv->mon = NULL;
2955
    }
2956

2957 2958 2959 2960 2961
    if (priv->monConfig) {
        if (priv->monConfig->type == VIR_DOMAIN_CHR_TYPE_UNIX)
            unlink(priv->monConfig->data.nix.path);
        virDomainChrDefFree(priv->monConfig);
        priv->monConfig = NULL;
2962 2963
    }

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

2967
    /* Reset Security Labels */
2968
    if (driver->securityDriver &&
2969
        driver->securityDriver->domainRestoreSecurityAllLabel)
2970
        driver->securityDriver->domainRestoreSecurityAllLabel(vm);
2971 2972
    if (driver->securityDriver &&
        driver->securityDriver->domainReleaseSecurityLabel)
2973
        driver->securityDriver->domainReleaseSecurityLabel(vm);
2974

2975 2976 2977 2978 2979 2980 2981
    /* 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 已提交
2982
    virDomainDefClearDeviceAliases(vm->def);
2983 2984 2985 2986 2987
    if (!priv->persistentAddrs) {
        virDomainDefClearPCIAddresses(vm->def);
        qemuDomainPCIAddressSetFree(priv->pciaddrs);
        priv->pciaddrs = NULL;
    }
2988

2989
    qemuDomainReAttachHostDevices(driver, vm->def);
2990

2991
retry:
2992
    if ((ret = qemuRemoveCgroup(driver, vm, 0)) < 0) {
2993 2994 2995 2996 2997 2998 2999 3000
        if (ret == -EBUSY && (retries++ < 5)) {
            usleep(200*1000);
            goto retry;
        }
        VIR_WARN("Failed to remove cgroup for %s",
                 vm->def->name);
    }

3001
    qemudRemoveDomainStatus(driver, vm);
D
Daniel P. Berrange 已提交
3002

3003
    vm->pid = -1;
3004
    vm->def->id = -1;
3005
    vm->state = VIR_DOMAIN_SHUTOFF;
3006 3007
    VIR_FREE(priv->vcpupids);
    priv->nvcpupids = 0;
3008 3009

    if (vm->newDef) {
3010
        virDomainDefFree(vm->def);
3011
        vm->def = vm->newDef;
3012
        vm->def->id = -1;
3013 3014
        vm->newDef = NULL;
    }
3015 3016 3017 3018 3019

    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
3020 3021 3022
}


3023
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
3024
                                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
3025
                                  int flags ATTRIBUTE_UNUSED) {
3026
    if (conn->uri == NULL) {
3027 3028 3029
        if (qemu_driver == NULL)
            return VIR_DRV_OPEN_DECLINED;

3030
        conn->uri = xmlParseURI(qemu_driver->privileged ?
3031 3032
                                "qemu:///system" :
                                "qemu:///session");
3033
        if (!conn->uri) {
3034
            virReportOOMError();
3035 3036
            return VIR_DRV_OPEN_ERROR;
        }
3037 3038 3039 3040 3041 3042 3043 3044 3045 3046
    } 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;

3047
        if (qemu_driver == NULL) {
3048 3049
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("qemu state driver is not active"));
3050 3051 3052
            return VIR_DRV_OPEN_ERROR;
        }

3053
        if (conn->uri->path == NULL) {
3054 3055 3056 3057 3058
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
                            _("no QEMU URI path given, try %s"),
                            qemu_driver->privileged
                            ? "qemu:///system"
                            : "qemu:///session");
3059 3060 3061
                return VIR_DRV_OPEN_ERROR;
        }

3062
        if (qemu_driver->privileged) {
3063 3064
            if (STRNEQ (conn->uri->path, "/system") &&
                STRNEQ (conn->uri->path, "/session")) {
3065 3066 3067
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unexpected QEMU URI path '%s', try qemu:///system"),
                                conn->uri->path);
3068 3069 3070 3071
                return VIR_DRV_OPEN_ERROR;
            }
        } else {
            if (STRNEQ (conn->uri->path, "/session")) {
3072 3073 3074
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unexpected QEMU URI path '%s', try qemu:///session"),
                                conn->uri->path);
3075 3076 3077
                return VIR_DRV_OPEN_ERROR;
            }
        }
3078 3079 3080 3081 3082 3083 3084
    }
    conn->privateData = qemu_driver;

    return VIR_DRV_OPEN_SUCCESS;
}

static int qemudClose(virConnectPtr conn) {
3085
    struct qemud_driver *driver = conn->privateData;
3086 3087

    /* Get rid of callbacks registered for this conn */
3088
    qemuDriverLock(driver);
3089
    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
3090
    qemuDriverUnlock(driver);
3091 3092 3093 3094 3095 3096

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
3097 3098 3099 3100 3101
/* Which features are supported by this driver? */
static int
qemudSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
{
    switch (feature) {
3102 3103 3104 3105 3106
    case VIR_DRV_FEATURE_MIGRATION_V2:
    case VIR_DRV_FEATURE_MIGRATION_P2P:
        return 1;
    default:
        return 0;
D
Daniel Veillard 已提交
3107 3108 3109
    }
}

3110
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
3111
    return "QEMU";
3112 3113
}

3114

3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127
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;
}


3128 3129 3130 3131
static int kvmGetMaxVCPUs(void) {
    int maxvcpus = 1;

    int r, fd;
3132

3133 3134
    fd = open(KVM_DEVICE, O_RDONLY);
    if (fd < 0) {
3135
        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
3136
        return -1;
3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147
    }

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

    close(fd);
    return maxvcpus;
}


3148
static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type) {
3149 3150 3151
    if (!type)
        return 16;

3152
    if (STRCASEEQ(type, "qemu"))
3153 3154
        return 16;

3155
    if (STRCASEEQ(type, "kvm"))
3156
        return kvmGetMaxVCPUs();
3157

3158
    if (STRCASEEQ(type, "kqemu"))
3159
        return 1;
3160

3161 3162
    qemuReportError(VIR_ERR_INVALID_ARG,
                    _("unknown type '%s'"), type);
3163 3164 3165
    return -1;
}

3166

3167
static char *qemudGetCapabilities(virConnectPtr conn) {
3168
    struct qemud_driver *driver = conn->privateData;
3169
    virCapsPtr caps = NULL;
3170
    char *xml = NULL;
3171

3172
    qemuDriverLock(driver);
3173

3174
    if ((caps = qemuCreateCapabilities(qemu_driver->caps,
3175
                                       qemu_driver)) == NULL) {
3176 3177 3178
        virCapabilitiesFree(caps);
        goto cleanup;
    }
3179

3180
    virCapabilitiesFree(qemu_driver->caps);
3181 3182 3183
    qemu_driver->caps = caps;

    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
3184
        virReportOOMError();
3185 3186

cleanup:
3187
    qemuDriverUnlock(driver);
3188

3189
    return xml;
3190 3191 3192
}


3193
static int qemudGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, int pid, int tid) {
D
Daniel P. Berrange 已提交
3194 3195
    char proc[PATH_MAX];
    FILE *pidinfo;
3196
    unsigned long long usertime, systime;
3197 3198
    int cpu;
    int ret;
D
Daniel P. Berrange 已提交
3199

3200 3201 3202 3203 3204 3205
    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 已提交
3206 3207 3208 3209
        return -1;
    }

    if (!(pidinfo = fopen(proc, "r"))) {
3210
        /*printf("cannot read pid info");*/
D
Daniel P. Berrange 已提交
3211
        /* VM probably shut down, so fake 0 */
3212 3213 3214 3215
        if (cpuTime)
            *cpuTime = 0;
        if (lastCpu)
            *lastCpu = 0;
D
Daniel P. Berrange 已提交
3216 3217 3218
        return 0;
    }

3219 3220 3221 3222 3223 3224 3225 3226 3227 3228
    /* 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) {
3229
        fclose(pidinfo);
3230 3231
        VIR_WARN0("cannot parse process status data");
        errno = -EINVAL;
D
Daniel P. Berrange 已提交
3232 3233 3234 3235 3236 3237 3238 3239
        return -1;
    }

    /* We got jiffies
     * We want nanoseconds
     * _SC_CLK_TCK is jiffies per second
     * So calulate thus....
     */
3240 3241 3242 3243 3244
    if (cpuTime)
        *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
    if (lastCpu)
        *lastCpu = cpu;

D
Daniel P. Berrange 已提交
3245

3246 3247
    VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d",
              pid, tid, usertime, systime, cpu);
D
Daniel P. Berrange 已提交
3248 3249 3250 3251 3252 3253 3254

    fclose(pidinfo);

    return 0;
}


3255
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
3256
                                          int id) {
3257 3258 3259 3260
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

3261
    qemuDriverLock(driver);
3262
    vm  = virDomainFindByID(&driver->domains, id);
3263
    qemuDriverUnlock(driver);
3264 3265

    if (!vm) {
3266 3267
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching id %d"), id);
3268
        goto cleanup;
3269 3270
    }

3271
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3272
    if (dom) dom->id = vm->def->id;
3273 3274

cleanup:
3275 3276
    if (vm)
        virDomainObjUnlock(vm);
3277 3278
    return dom;
}
3279

3280
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
3281
                                            const unsigned char *uuid) {
3282 3283 3284
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
3285

3286
    qemuDriverLock(driver);
3287
    vm = virDomainFindByUUID(&driver->domains, uuid);
3288 3289
    qemuDriverUnlock(driver);

3290
    if (!vm) {
3291 3292
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(uuid, uuidstr);
3293 3294
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3295
        goto cleanup;
3296 3297
    }

3298
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3299
    if (dom) dom->id = vm->def->id;
3300 3301

cleanup:
3302 3303
    if (vm)
        virDomainObjUnlock(vm);
3304 3305
    return dom;
}
3306

3307
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
3308
                                            const char *name) {
3309 3310 3311
    struct qemud_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
3312

3313
    qemuDriverLock(driver);
3314
    vm = virDomainFindByName(&driver->domains, name);
3315 3316
    qemuDriverUnlock(driver);

3317
    if (!vm) {
3318 3319
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching name '%s'"), name);
3320
        goto cleanup;
3321 3322
    }

3323
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3324
    if (dom) dom->id = vm->def->id;
3325 3326

cleanup:
3327 3328
    if (vm)
        virDomainObjUnlock(vm);
3329 3330 3331
    return dom;
}

3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342

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) {
3343
        qemuReportError(VIR_ERR_NO_DOMAIN, NULL);
3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363
        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) {
3364
        qemuReportError(VIR_ERR_NO_DOMAIN, NULL);
3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375
        goto cleanup;
    }
    ret = obj->persistent;

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


3376
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
3377 3378 3379
    struct qemud_driver *driver = conn->privateData;
    int ret = -1;

3380
    qemuDriverLock(driver);
3381
    if (qemudExtractVersion(driver) < 0)
3382
        goto cleanup;
3383

3384
    *version = qemu_driver->qemuVersion;
3385 3386 3387
    ret = 0;

cleanup:
3388
    qemuDriverUnlock(driver);
3389
    return ret;
D
Daniel P. Berrange 已提交
3390 3391
}

3392
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
3393
    struct qemud_driver *driver = conn->privateData;
3394
    int n;
3395

3396
    qemuDriverLock(driver);
3397
    n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
3398
    qemuDriverUnlock(driver);
3399

3400
    return n;
D
Daniel P. Berrange 已提交
3401
}
3402

3403
static int qemudNumDomains(virConnectPtr conn) {
3404
    struct qemud_driver *driver = conn->privateData;
3405
    int n;
3406

3407
    qemuDriverLock(driver);
3408
    n = virDomainObjListNumOfDomains(&driver->domains, 1);
3409
    qemuDriverUnlock(driver);
3410

3411
    return n;
D
Daniel P. Berrange 已提交
3412
}
3413

3414
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
3415
                                      unsigned int flags ATTRIBUTE_UNUSED) {
3416
    struct qemud_driver *driver = conn->privateData;
3417
    virDomainDefPtr def;
3418
    virDomainObjPtr vm = NULL;
3419
    virDomainPtr dom = NULL;
3420
    virDomainEventPtr event = NULL;
D
Daniel P. Berrange 已提交
3421

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

3427
    if (virSecurityDriverVerify(def) < 0)
3428 3429
        goto cleanup;

3430 3431
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
3432

3433 3434 3435 3436 3437 3438
    if (qemudCanonicalizeMachine(driver, def) < 0)
        goto cleanup;

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

3439
    if (!(vm = virDomainAssignDef(driver->caps,
3440
                                  &driver->domains,
3441 3442 3443 3444
                                  def)))
        goto cleanup;

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

3446 3447 3448
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup; /* XXXX free the 'vm' we created ? */

3449
    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
3450 3451 3452
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains,
                                    vm);
3453
        vm = NULL;
3454
        goto endjob;
D
Daniel P. Berrange 已提交
3455
    }
3456 3457 3458 3459

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

3461
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
3462
    if (dom) dom->id = vm->def->id;
3463

3464
endjob:
3465 3466 3467
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3468

3469 3470
cleanup:
    virDomainDefFree(def);
3471 3472
    if (vm)
        virDomainObjUnlock(vm);
3473 3474
    if (event)
        qemuDomainEventQueue(driver, event);
3475
    qemuDriverUnlock(driver);
3476
    return dom;
D
Daniel P. Berrange 已提交
3477 3478 3479
}


3480
static int qemudDomainSuspend(virDomainPtr dom) {
3481 3482 3483
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3484
    virDomainEventPtr event = NULL;
3485

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

D
Daniel P. Berrange 已提交
3489
    if (!vm) {
3490 3491
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3492 3493
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3494
        goto cleanup;
D
Daniel P. Berrange 已提交
3495
    }
3496 3497 3498
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
3499
    if (!virDomainObjIsActive(vm)) {
3500 3501
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3502
        goto endjob;
D
Daniel P. Berrange 已提交
3503
    }
3504
    if (vm->state != VIR_DOMAIN_PAUSED) {
3505
        qemuDomainObjPrivatePtr priv = vm->privateData;
3506
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
3507
        if (qemuMonitorStopCPUs(priv->mon) < 0) {
3508 3509
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            goto endjob;
3510
        }
3511
        qemuDomainObjExitMonitorWithDriver(driver, vm);
3512
        vm->state = VIR_DOMAIN_PAUSED;
3513 3514 3515
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
D
Daniel P. Berrange 已提交
3516
    }
3517
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
3518
        goto endjob;
3519 3520
    ret = 0;

3521
endjob:
3522 3523
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3524

3525
cleanup:
3526 3527
    if (vm)
        virDomainObjUnlock(vm);
3528

3529
    if (event)
3530
        qemuDomainEventQueue(driver, event);
3531
    qemuDriverUnlock(driver);
3532
    return ret;
D
Daniel P. Berrange 已提交
3533 3534 3535
}


3536
static int qemudDomainResume(virDomainPtr dom) {
3537 3538 3539
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3540
    virDomainEventPtr event = NULL;
3541

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

D
Daniel P. Berrange 已提交
3545
    if (!vm) {
3546 3547
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3548 3549
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3550
        goto cleanup;
D
Daniel P. Berrange 已提交
3551
    }
3552 3553 3554 3555

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

D
Daniel P. Berrange 已提交
3556
    if (!virDomainObjIsActive(vm)) {
3557 3558
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3559
        goto endjob;
D
Daniel P. Berrange 已提交
3560
    }
3561
    if (vm->state == VIR_DOMAIN_PAUSED) {
3562
        qemuDomainObjPrivatePtr priv = vm->privateData;
3563
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
3564
        if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) {
3565
            qemuDomainObjExitMonitorWithDriver(driver, vm);
3566
            if (virGetLastError() == NULL)
3567 3568
                qemuReportError(VIR_ERR_OPERATION_FAILED,
                                "%s", _("resume operation failed"));
3569
            goto endjob;
3570
        }
3571
        qemuDomainObjExitMonitorWithDriver(driver, vm);
3572
        vm->state = VIR_DOMAIN_RUNNING;
3573 3574 3575
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
D
Daniel P. Berrange 已提交
3576
    }
3577
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
3578
        goto endjob;
3579 3580
    ret = 0;

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

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


3595
static int qemudDomainShutdown(virDomainPtr dom) {
3596 3597 3598
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3599

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

3604
    if (!vm) {
3605 3606
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3607 3608
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3609
        goto cleanup;
3610 3611
    }

3612 3613 3614
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
3615
    if (!virDomainObjIsActive(vm)) {
3616 3617
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3618
        goto endjob;
3619 3620
    }

3621
    qemuDomainObjPrivatePtr priv = vm->privateData;
3622 3623 3624
    qemuDomainObjEnterMonitor(vm);
    ret = qemuMonitorSystemPowerdown(priv->mon);
    qemuDomainObjExitMonitor(vm);
3625

3626
endjob:
3627 3628
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3629

3630
cleanup:
3631 3632
    if (vm)
        virDomainObjUnlock(vm);
3633
    return ret;
3634 3635 3636
}


3637
static int qemudDomainDestroy(virDomainPtr dom) {
3638 3639 3640
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3641
    virDomainEventPtr event = NULL;
3642

3643
    qemuDriverLock(driver);
3644
    vm  = virDomainFindByUUID(&driver->domains, dom->uuid);
D
Daniel P. Berrange 已提交
3645
    if (!vm) {
3646 3647
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3648 3649
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3650
        goto cleanup;
D
Daniel P. Berrange 已提交
3651
    }
3652 3653 3654 3655

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

D
Daniel P. Berrange 已提交
3656
    if (!virDomainObjIsActive(vm)) {
3657 3658
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3659
        goto endjob;
3660
    }
3661

3662
    qemudShutdownVMDaemon(driver, vm);
3663 3664 3665
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
3666
    if (!vm->persistent) {
3667 3668 3669
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains,
                                    vm);
3670 3671
        vm = NULL;
    }
3672 3673
    ret = 0;

3674
endjob:
3675 3676 3677
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3678

3679
cleanup:
3680 3681
    if (vm)
        virDomainObjUnlock(vm);
3682 3683
    if (event)
        qemuDomainEventQueue(driver, event);
3684
    qemuDriverUnlock(driver);
3685
    return ret;
D
Daniel P. Berrange 已提交
3686 3687 3688
}


3689
static char *qemudDomainGetOSType(virDomainPtr dom) {
3690 3691 3692
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *type = NULL;
3693

3694
    qemuDriverLock(driver);
3695
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3696
    qemuDriverUnlock(driver);
3697
    if (!vm) {
3698 3699
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3700 3701
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3702
        goto cleanup;
3703 3704
    }

3705
    if (!(type = strdup(vm->def->os.type)))
3706
        virReportOOMError();
3707 3708

cleanup:
3709 3710
    if (vm)
        virDomainObjUnlock(vm);
3711 3712 3713
    return type;
}

3714 3715
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
3716 3717 3718
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    unsigned long ret = 0;
3719

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

3724
    if (!vm) {
3725 3726
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3727 3728
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3729
        goto cleanup;
3730 3731
    }

3732 3733 3734
    ret = vm->def->maxmem;

cleanup:
3735 3736
    if (vm)
        virDomainObjUnlock(vm);
3737
    return ret;
3738 3739 3740
}

static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
3741 3742 3743
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3744

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

3749
    if (!vm) {
3750 3751
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3752 3753
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3754
        goto cleanup;
3755 3756 3757
    }

    if (newmax < vm->def->memory) {
3758 3759
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("cannot set max memory lower than current memory"));
3760
        goto cleanup;;
3761 3762 3763
    }

    vm->def->maxmem = newmax;
3764 3765 3766
    ret = 0;

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

3772

3773
static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
3774 3775 3776
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3777

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

    if (newmem > vm->def->maxmem) {
3790 3791
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("cannot set memory higher than max memory"));
3792
        goto cleanup;
3793 3794
    }

3795 3796 3797
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
3798
    if (virDomainObjIsActive(vm)) {
3799
        qemuDomainObjPrivatePtr priv = vm->privateData;
3800
        qemuDomainObjEnterMonitor(vm);
3801
        int r = qemuMonitorSetBalloon(priv->mon, newmem);
3802
        qemuDomainObjExitMonitor(vm);
3803
        if (r < 0)
3804
            goto endjob;
3805 3806 3807

        /* Lack of balloon support is a fatal error */
        if (r == 0) {
3808 3809
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            "%s", _("cannot set memory of an active domain"));
3810
            goto endjob;
3811
        }
3812 3813 3814
    } else {
        vm->def->memory = newmem;
    }
3815
    ret = 0;
3816

3817
endjob:
3818 3819
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
3820

3821
cleanup:
3822 3823
    if (vm)
        virDomainObjUnlock(vm);
3824
    return ret;
3825 3826
}

3827
static int qemudDomainGetInfo(virDomainPtr dom,
3828
                              virDomainInfoPtr info) {
3829 3830 3831
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
3832 3833
    int err;
    unsigned long balloon;
3834

3835
    qemuDriverLock(driver);
3836
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3837
    qemuDriverUnlock(driver);
D
Daniel P. Berrange 已提交
3838
    if (!vm) {
3839 3840
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3841 3842
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3843
        goto cleanup;
D
Daniel P. Berrange 已提交
3844 3845
    }

3846
    info->state = vm->state;
D
Daniel P. Berrange 已提交
3847

D
Daniel P. Berrange 已提交
3848
    if (!virDomainObjIsActive(vm)) {
3849
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
3850
    } else {
3851
        if (qemudGetProcessInfo(&(info->cpuTime), NULL, vm->pid, 0) < 0) {
3852
            qemuReportError(VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
3853
            goto cleanup;
D
Daniel P. Berrange 已提交
3854 3855 3856
        }
    }

3857
    info->maxMem = vm->def->maxmem;
3858

D
Daniel P. Berrange 已提交
3859
    if (virDomainObjIsActive(vm)) {
3860
        qemuDomainObjPrivatePtr priv = vm->privateData;
3861 3862 3863
        if (!priv->jobActive) {
            if (qemuDomainObjBeginJob(vm) < 0)
                goto cleanup;
3864

3865 3866 3867 3868
            qemuDomainObjEnterMonitor(vm);
            err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
            qemuDomainObjExitMonitor(vm);
            if (err < 0) {
3869 3870
                if (qemuDomainObjEndJob(vm) == 0)
                    vm = NULL;
3871 3872 3873 3874 3875 3876 3877 3878 3879
                goto cleanup;
            }

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

3880 3881 3882 3883
            if (qemuDomainObjEndJob(vm) == 0) {
                vm = NULL;
                goto cleanup;
            }
3884 3885 3886
        } else {
            info->memory = vm->def->memory;
        }
3887 3888 3889 3890
    } else {
        info->memory = vm->def->memory;
    }

3891
    info->nrVirtCpu = vm->def->vcpus;
3892 3893 3894
    ret = 0;

cleanup:
3895 3896
    if (vm)
        virDomainObjUnlock(vm);
3897
    return ret;
D
Daniel P. Berrange 已提交
3898 3899 3900
}


3901
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave"
3902 3903 3904
#define QEMUD_SAVE_VERSION 2

enum qemud_save_formats {
3905 3906 3907
    QEMUD_SAVE_FORMAT_RAW = 0,
    QEMUD_SAVE_FORMAT_GZIP = 1,
    QEMUD_SAVE_FORMAT_BZIP2 = 2,
3908 3909
    /*
     * Deprecated by xz and never used as part of a release
3910
     * QEMUD_SAVE_FORMAT_LZMA
3911 3912
     */
    QEMUD_SAVE_FORMAT_XZ = 3,
3913
    QEMUD_SAVE_FORMAT_LZOP = 4,
3914 3915 3916
    /* Note: add new members only at the end.
       These values are used in the on-disk format.
       Do not change or re-use numbers. */
3917 3918

    QEMUD_SAVE_FORMAT_LAST
3919
};
3920

3921 3922 3923 3924 3925
VIR_ENUM_DECL(qemudSaveCompression)
VIR_ENUM_IMPL(qemudSaveCompression, QEMUD_SAVE_FORMAT_LAST,
              "raw",
              "gzip",
              "bzip2",
3926 3927
              "xz",
              "lzop")
3928

3929 3930 3931 3932 3933
struct qemud_save_header {
    char magic[sizeof(QEMUD_SAVE_MAGIC)-1];
    int version;
    int xml_len;
    int was_running;
3934 3935
    int compressed;
    int unused[15];
3936 3937
};

3938
static int qemudDomainSave(virDomainPtr dom,
3939 3940
                           const char *path)
{
3941
    struct qemud_driver *driver = dom->conn->privateData;
3942
    virDomainObjPtr vm = NULL;
3943 3944
    int fd = -1;
    char *xml = NULL;
3945
    struct qemud_save_header header;
3946
    int ret = -1;
3947
    int rc;
3948
    virDomainEventPtr event = NULL;
3949 3950 3951 3952 3953

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

3954
    qemuDriverLock(driver);
3955 3956 3957
    if (driver->saveImageFormat == NULL)
        header.compressed = QEMUD_SAVE_FORMAT_RAW;
    else {
3958 3959 3960
        header.compressed =
            qemudSaveCompressionTypeFromString(driver->saveImageFormat);
        if (header.compressed < 0) {
3961 3962 3963
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            "%s", _("Invalid save image format specified "
                                    "in configuration file"));
3964
            goto cleanup;
3965
        }
3966 3967
    }

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

D
Daniel P. Berrange 已提交
3970
    if (!vm) {
3971 3972
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
3973 3974
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
3975
        goto cleanup;
D
Daniel P. Berrange 已提交
3976
    }
3977

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

D
Daniel P. Berrange 已提交
3981
    if (!virDomainObjIsActive(vm)) {
3982 3983
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
3984
        goto endjob;
D
Daniel P. Berrange 已提交
3985
    }
3986 3987 3988

    /* Pause */
    if (vm->state == VIR_DOMAIN_RUNNING) {
3989
        qemuDomainObjPrivatePtr priv = vm->privateData;
3990
        header.was_running = 1;
3991
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
3992
        if (qemuMonitorStopCPUs(priv->mon) < 0) {
3993 3994
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            goto endjob;
3995
        }
3996
        qemuDomainObjExitMonitorWithDriver(driver, vm);
3997
        vm->state = VIR_DOMAIN_PAUSED;
3998 3999 4000
    }

    /* Get XML for the domain */
4001
    xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
4002
    if (!xml) {
4003 4004
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to get domain xml"));
4005
        goto endjob;
4006 4007 4008 4009 4010
    }
    header.xml_len = strlen(xml) + 1;

    /* Write header to file, followed by XML */
    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
4011 4012
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("failed to create '%s'"), path);
4013
        goto endjob;
4014 4015 4016
    }

    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
4017 4018
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to write save header"));
4019
        goto endjob;
4020 4021 4022
    }

    if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
4023
        qemuReportError(VIR_ERR_OPERATION_FAILED,
4024
                         "%s", _("failed to write xml"));
4025
        goto endjob;
4026 4027
    }

4028
    if (close(fd) < 0) {
4029
        virReportSystemError(errno,
4030 4031
                             _("unable to save file %s"),
                             path);
4032
        goto endjob;
4033 4034
    }
    fd = -1;
4035

4036 4037
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSavedStateLabel &&
4038
        driver->securityDriver->domainSetSavedStateLabel(vm, path) == -1)
4039 4040
        goto endjob;

4041 4042
    if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
        const char *args[] = { "cat", NULL };
4043
        qemuDomainObjPrivatePtr priv = vm->privateData;
M
Matthias Bolte 已提交
4044
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
4045
        rc = qemuMonitorMigrateToCommand(priv->mon, 0, args, path);
M
Matthias Bolte 已提交
4046
        qemuDomainObjExitMonitorWithDriver(driver, vm);
4047
    } else {
4048
        const char *prog = qemudSaveCompressionTypeToString(header.compressed);
4049
        qemuDomainObjPrivatePtr priv = vm->privateData;
4050 4051 4052 4053 4054
        const char *args[] = {
            prog,
            "-c",
            NULL
        };
M
Matthias Bolte 已提交
4055
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
4056
        rc = qemuMonitorMigrateToCommand(priv->mon, 0, args, path);
M
Matthias Bolte 已提交
4057
        qemuDomainObjExitMonitorWithDriver(driver, vm);
4058 4059
    }

4060
    if (rc < 0)
4061
        goto endjob;
4062

4063 4064
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSavedStateLabel &&
4065
        driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
4066 4067 4068 4069
        goto endjob;

    ret = 0;

4070
    /* Shut it down */
4071
    qemudShutdownVMDaemon(driver, vm);
4072 4073 4074
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
4075
    if (!vm->persistent) {
4076 4077 4078
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains,
                                    vm);
4079 4080
        vm = NULL;
    }
4081

4082
endjob:
4083 4084 4085
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
4086

4087 4088 4089 4090 4091 4092
cleanup:
    if (fd != -1)
        close(fd);
    VIR_FREE(xml);
    if (ret != 0)
        unlink(path);
4093 4094
    if (vm)
        virDomainObjUnlock(vm);
4095 4096
    if (event)
        qemuDomainEventQueue(driver, event);
4097
    qemuDriverUnlock(driver);
4098
    return ret;
D
Daniel P. Berrange 已提交
4099 4100 4101
}


P
Paolo Bonzini 已提交
4102 4103 4104 4105 4106 4107
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;
4108
    int ret = -1, fd = -1;
4109
    virDomainEventPtr event = NULL;
4110 4111 4112 4113
    const char *args[] = {
        "cat",
        NULL,
    };
P
Paolo Bonzini 已提交
4114 4115 4116 4117 4118 4119 4120 4121

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

    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4122 4123
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
P
Paolo Bonzini 已提交
4124 4125 4126
        goto cleanup;
    }

4127 4128 4129
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
4130
    if (!virDomainObjIsActive(vm)) {
4131 4132
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
4133
        goto endjob;
P
Paolo Bonzini 已提交
4134 4135
    }

4136 4137
    /* Create an empty file with appropriate ownership.  */
    if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
4138 4139
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("failed to create '%s'"), path);
4140 4141 4142 4143
        goto endjob;
    }

    if (close(fd) < 0) {
4144
        virReportSystemError(errno,
4145 4146 4147 4148 4149 4150 4151
                             _("unable to save file %s"),
                             path);
        goto endjob;
    }

    if (driver->securityDriver &&
        driver->securityDriver->domainSetSavedStateLabel &&
4152
        driver->securityDriver->domainSetSavedStateLabel(vm, path) == -1)
4153 4154
        goto endjob;

P
Paolo Bonzini 已提交
4155 4156
    /* Migrate will always stop the VM, so the resume condition is
       independent of whether the stop command is issued.  */
P
Paolo Bonzini 已提交
4157 4158
    resume = (vm->state == VIR_DOMAIN_RUNNING);

4159 4160
    qemuDomainObjPrivatePtr priv = vm->privateData;

P
Paolo Bonzini 已提交
4161
    /* Pause domain for non-live dump */
P
Paolo Bonzini 已提交
4162
    if (!(flags & VIR_DUMP_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
4163 4164 4165
        qemuDomainObjEnterMonitor(vm);
        if (qemuMonitorStopCPUs(priv->mon) < 0) {
            qemuDomainObjExitMonitor(vm);
4166
            goto endjob;
4167 4168
        }
        qemuDomainObjExitMonitor(vm);
P
Paolo Bonzini 已提交
4169 4170 4171
        paused = 1;
    }

4172
    qemuDomainObjEnterMonitor(vm);
4173
    ret = qemuMonitorMigrateToCommand(priv->mon, 0, args, path);
4174
    qemuDomainObjExitMonitor(vm);
4175 4176 4177 4178
    paused |= (ret == 0);

    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSavedStateLabel &&
4179
        driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
4180 4181 4182
        goto endjob;

endjob:
4183
    if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
4184
        qemudShutdownVMDaemon(driver, vm);
4185 4186 4187 4188 4189
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
    }

P
Paolo Bonzini 已提交
4190 4191 4192
    /* 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.  */
4193
    else if (resume && paused) {
4194
        qemuDomainObjEnterMonitor(vm);
4195
        if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) {
4196
            if (virGetLastError() == NULL)
4197 4198
                qemuReportError(VIR_ERR_OPERATION_FAILED,
                                "%s", _("resuming after dump failed"));
P
Paolo Bonzini 已提交
4199
        }
4200
        qemuDomainObjExitMonitor(vm);
P
Paolo Bonzini 已提交
4201
    }
4202

4203 4204
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
4205
    else if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) {
4206 4207 4208 4209
        virDomainRemoveInactive(&driver->domains,
                                vm);
        vm = NULL;
    }
4210 4211

cleanup:
4212 4213
    if (ret != 0)
        unlink(path);
P
Paolo Bonzini 已提交
4214 4215
    if (vm)
        virDomainObjUnlock(vm);
4216 4217
    if (event)
        qemuDomainEventQueue(driver, event);
P
Paolo Bonzini 已提交
4218 4219 4220 4221
    return ret;
}


4222
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
4223 4224
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4225
    int max;
4226
    int ret = -1;
4227
    const char *type;
4228

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

4233
    if (!vm) {
4234 4235
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4236 4237
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4238
        goto cleanup;
4239 4240
    }

4241 4242 4243
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
4244
    if (virDomainObjIsActive(vm)) {
4245 4246
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
                        _("cannot change vcpu count of an active domain"));
4247
        goto endjob;
4248 4249
    }

4250
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
4251 4252 4253
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown virt type in domain definition '%d'"),
                        vm->def->virtType);
4254
        goto endjob;
4255 4256
    }

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

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

    vm->def->vcpus = nvcpus;
4271 4272
    ret = 0;

4273
endjob:
4274 4275
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
4276

4277
cleanup:
4278 4279
    if (vm)
        virDomainObjUnlock(vm);
4280
    return ret;
4281 4282
}

4283 4284 4285 4286 4287 4288

static int
qemudDomainPinVcpu(virDomainPtr dom,
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
4289 4290
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4291
    int maxcpu, hostcpus;
4292
    virNodeInfo nodeinfo;
4293
    int ret = -1;
4294
    qemuDomainObjPrivatePtr priv;
4295

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

4300 4301 4302
    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4303 4304
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4305 4306 4307
        goto cleanup;
    }

D
Daniel P. Berrange 已提交
4308
    if (!virDomainObjIsActive(vm)) {
4309 4310
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s",_("cannot pin vcpus on an inactive domain"));
4311
        goto cleanup;
4312 4313
    }

4314 4315 4316
    priv = vm->privateData;

    if (vcpu > (priv->nvcpupids-1)) {
4317 4318 4319
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("vcpu number out of range %d > %d"),
                        vcpu, priv->nvcpupids);
4320
        goto cleanup;
4321 4322
    }

4323
    if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
4324
        goto cleanup;
4325

4326
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
4327
    maxcpu = maplen * 8;
4328 4329
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
4330

4331 4332
    if (priv->vcpupids != NULL) {
        if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
4333
                                      cpumap, maplen, maxcpu) < 0)
4334
            goto cleanup;
4335
    } else {
4336 4337
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("cpu affinity is not supported"));
4338
        goto cleanup;
4339
    }
4340
    ret = 0;
4341

4342
cleanup:
4343 4344
    if (vm)
        virDomainObjUnlock(vm);
4345
    return ret;
4346 4347 4348 4349 4350 4351 4352 4353
}

static int
qemudDomainGetVcpus(virDomainPtr dom,
                    virVcpuInfoPtr info,
                    int maxinfo,
                    unsigned char *cpumaps,
                    int maplen) {
4354 4355
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4356
    virNodeInfo nodeinfo;
4357
    int i, v, maxcpu, hostcpus;
4358
    int ret = -1;
4359
    qemuDomainObjPrivatePtr priv;
4360

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

4365 4366 4367
    if (!vm) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4368 4369
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4370 4371 4372
        goto cleanup;
    }

D
Daniel P. Berrange 已提交
4373
    if (!virDomainObjIsActive(vm)) {
4374 4375 4376
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s",
                        _("cannot list vcpu pinning for an inactive domain"));
4377
        goto cleanup;
4378 4379
    }

4380 4381
    priv = vm->privateData;

4382
    if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
4383
        goto cleanup;
4384

4385
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
4386
    maxcpu = maplen * 8;
4387 4388
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
4389 4390

    /* Clamp to actual number of vcpus */
4391 4392
    if (maxinfo > priv->nvcpupids)
        maxinfo = priv->nvcpupids;
4393

4394 4395 4396 4397 4398 4399
    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;
4400

4401
                if (priv->vcpupids != NULL &&
4402 4403 4404
                    qemudGetProcessInfo(&(info[i].cpuTime),
                                        &(info[i].cpu),
                                        vm->pid,
4405
                                        priv->vcpupids[i]) < 0) {
4406
                    virReportSystemError(errno, "%s",
4407 4408 4409
                                         _("cannot get vCPU placement & pCPU time"));
                    goto cleanup;
                }
4410
            }
4411 4412
        }

4413 4414
        if (cpumaps != NULL) {
            memset(cpumaps, 0, maplen * maxinfo);
4415
            if (priv->vcpupids != NULL) {
4416 4417 4418
                for (v = 0 ; v < maxinfo ; v++) {
                    unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);

4419
                    if (virProcessInfoGetAffinity(priv->vcpupids[v],
4420
                                                  cpumap, maplen, maxcpu) < 0)
4421
                        goto cleanup;
4422
                }
4423
            } else {
4424 4425
                qemuReportError(VIR_ERR_NO_SUPPORT,
                                "%s", _("cpu affinity is not available"));
4426
                goto cleanup;
4427 4428 4429
            }
        }
    }
4430
    ret = maxinfo;
4431

4432
cleanup:
4433 4434
    if (vm)
        virDomainObjUnlock(vm);
4435
    return ret;
4436 4437 4438
}


4439
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
4440 4441
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
4442
    const char *type;
4443
    int ret = -1;
4444

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

4449
    if (!vm) {
4450 4451
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4452 4453
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4454
        goto cleanup;
4455 4456
    }

4457
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
4458 4459 4460
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown virt type in domain definition '%d'"),
                        vm->def->virtType);
4461
        goto cleanup;
4462 4463
    }

4464
    ret = qemudGetMaxVCPUs(NULL, type);
4465

4466
cleanup:
4467 4468
    if (vm)
        virDomainObjUnlock(vm);
4469 4470 4471
    return ret;
}

4472 4473 4474 4475 4476 4477 4478 4479 4480 4481
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);

4482 4483
    memset(seclabel, 0, sizeof(*seclabel));

4484 4485 4486
    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);
4489 4490 4491 4492
        goto cleanup;
    }

    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
4493 4494 4495
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unknown virt type in domain definition '%d'"),
                        vm->def->virtType);
4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512
        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 已提交
4513
    if (virDomainObjIsActive(vm)) {
4514
        if (driver->securityDriver && driver->securityDriver->domainGetSecurityProcessLabel) {
4515
            if (driver->securityDriver->domainGetSecurityProcessLabel(vm, seclabel) == -1) {
4516 4517
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("Failed to get security label"));
4518 4519 4520 4521 4522 4523 4524 4525 4526 4527
                goto cleanup;
            }
        }
    }

    ret = 0;

cleanup:
    if (vm)
        virDomainObjUnlock(vm);
4528
    qemuDriverUnlock(driver);
4529 4530 4531
    return ret;
}

4532 4533
static int qemudNodeGetSecurityModel(virConnectPtr conn,
                                     virSecurityModelPtr secmodel)
4534 4535 4536
{
    struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
    char *p;
4537
    int ret = 0;
4538

4539 4540
    qemuDriverLock(driver);
    if (!driver->securityDriver) {
4541
        memset(secmodel, 0, sizeof (*secmodel));
4542 4543
        goto cleanup;
    }
4544

4545 4546
    p = driver->caps->host.secModel.model;
    if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
4547 4548 4549
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("security model string exceeds max %d bytes"),
                        VIR_SECURITY_MODEL_BUFLEN-1);
4550 4551
        ret = -1;
        goto cleanup;
4552 4553 4554 4555 4556
    }
    strcpy(secmodel->model, p);

    p = driver->caps->host.secModel.doi;
    if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
4557 4558 4559
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("security DOI string exceeds max %d bytes"),
                        VIR_SECURITY_DOI_BUFLEN-1);
4560 4561
        ret = -1;
        goto cleanup;
4562 4563
    }
    strcpy(secmodel->doi, p);
4564 4565 4566 4567

cleanup:
    qemuDriverUnlock(driver);
    return ret;
4568 4569 4570
}

/* TODO: check seclabel restore */
4571
static int qemudDomainRestore(virConnectPtr conn,
4572 4573 4574
                              const char *path) {
    struct qemud_driver *driver = conn->privateData;
    virDomainDefPtr def = NULL;
4575
    virDomainObjPtr vm = NULL;
4576 4577 4578
    int fd = -1;
    int ret = -1;
    char *xml = NULL;
4579
    struct qemud_save_header header;
4580
    virDomainEventPtr event = NULL;
4581 4582 4583
    int intermediatefd = -1;
    pid_t intermediate_pid = -1;
    int childstat;
4584

4585
    qemuDriverLock(driver);
4586 4587
    /* Verify the header and read the XML */
    if ((fd = open(path, O_RDONLY)) < 0) {
4588 4589
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("cannot read domain image"));
4590
        goto cleanup;
4591 4592 4593
    }

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
4594 4595
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to read qemu header"));
4596
        goto cleanup;
4597 4598 4599
    }

    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
4600 4601
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("image magic is incorrect"));
4602
        goto cleanup;
4603 4604 4605
    }

    if (header.version > QEMUD_SAVE_VERSION) {
4606 4607 4608
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("image version is not supported (%d > %d)"),
                        header.version, QEMUD_SAVE_VERSION);
4609
        goto cleanup;
4610 4611
    }

4612
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
4613
        virReportOOMError();
4614
        goto cleanup;
4615 4616 4617
    }

    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
4618 4619
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to read XML"));
4620
        goto cleanup;
4621 4622 4623
    }

    /* Create a domain from this XML */
4624
    if (!(def = virDomainDefParseString(driver->caps, xml,
4625
                                        VIR_DOMAIN_XML_INACTIVE))) {
4626 4627
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to parse XML"));
4628
        goto cleanup;
4629 4630
    }

4631 4632
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
4633

4634
    if (!(vm = virDomainAssignDef(driver->caps,
4635 4636
                                  &driver->domains,
                                  def))) {
4637 4638
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to assign new VM"));
4639
        goto cleanup;
4640
    }
4641
    def = NULL;
4642

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

4646 4647
    if (header.version == 2) {
        const char *intermediate_argv[3] = { NULL, "-dc", NULL };
4648 4649
        const char *prog = qemudSaveCompressionTypeToString(header.compressed);
        if (prog == NULL) {
4650 4651 4652
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("Invalid compressed save format %d"),
                            header.compressed);
4653
            goto endjob;
4654
        }
4655

4656
        if (header.compressed != QEMUD_SAVE_FORMAT_RAW) {
4657
            intermediate_argv[0] = prog;
4658 4659
            intermediatefd = fd;
            fd = -1;
4660
            if (virExec(intermediate_argv, NULL, NULL,
4661
                        &intermediate_pid, intermediatefd, &fd, NULL, 0) < 0) {
4662 4663 4664
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("Failed to start decompression binary %s"),
                                intermediate_argv[0]);
4665
                goto endjob;
4666 4667 4668
            }
        }
    }
4669
    /* Set the migration source and start it up. */
4670
    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
4671 4672 4673 4674 4675 4676 4677
    if (intermediate_pid != -1) {
        /* Wait for intermediate process to exit */
        while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
               errno == EINTR);
    }
    if (intermediatefd != -1)
        close(intermediatefd);
4678
    close(fd);
4679
    fd = -1;
4680
    if (ret < 0) {
4681
        if (!vm->persistent) {
4682 4683 4684
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains,
                                        vm);
4685 4686
            vm = NULL;
        }
4687
        goto endjob;
4688 4689
    }

4690 4691 4692
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
4693

4694 4695
    /* If it was running before, resume it now. */
    if (header.was_running) {
4696
        qemuDomainObjPrivatePtr priv = vm->privateData;
4697
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
4698
        if (qemuMonitorStartCPUs(priv->mon, conn) < 0) {
4699
            if (virGetLastError() == NULL)
4700 4701
                qemuReportError(VIR_ERR_OPERATION_FAILED,
                                "%s", _("failed to resume domain"));
4702 4703
            qemuDomainObjExitMonitorWithDriver(driver,vm);
            goto endjob;
4704
        }
4705
        qemuDomainObjExitMonitorWithDriver(driver, vm);
4706
        vm->state = VIR_DOMAIN_RUNNING;
4707
        virDomainSaveStatus(driver->caps, driver->stateDir, vm);
4708
    }
4709
    ret = 0;
4710

4711
endjob:
4712 4713 4714
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
4715

4716 4717 4718 4719 4720
cleanup:
    virDomainDefFree(def);
    VIR_FREE(xml);
    if (fd != -1)
        close(fd);
4721 4722
    if (vm)
        virDomainObjUnlock(vm);
4723 4724
    if (event)
        qemuDomainEventQueue(driver, event);
4725
    qemuDriverUnlock(driver);
4726
    return ret;
D
Daniel P. Berrange 已提交
4727 4728 4729
}


4730
static char *qemudDomainDumpXML(virDomainPtr dom,
4731
                                int flags) {
4732 4733 4734
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;
4735 4736
    unsigned long balloon;
    int err;
4737

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

D
Daniel P. Berrange 已提交
4742
    if (!vm) {
4743 4744
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4745 4746
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4747
        goto cleanup;
D
Daniel P. Berrange 已提交
4748 4749
    }

4750
    /* Refresh current memory based on balloon info */
D
Daniel P. Berrange 已提交
4751
    if (virDomainObjIsActive(vm)) {
4752
        qemuDomainObjPrivatePtr priv = vm->privateData;
4753 4754 4755 4756 4757 4758 4759 4760 4761
        /* 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);
4762 4763 4764 4765
            if (qemuDomainObjEndJob(vm) == 0) {
                vm = NULL;
                goto cleanup;
            }
4766 4767 4768 4769 4770 4771
            if (err < 0)
                goto cleanup;
            if (err > 0)
                vm->def->memory = balloon;
            /* err == 0 indicates no balloon support, so ignore it */
        }
4772
    }
4773

4774
    ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
4775 4776 4777 4778
                             vm->newDef : vm->def,
                             flags);

cleanup:
4779 4780
    if (vm)
        virDomainObjUnlock(vm);
4781
    return ret;
D
Daniel P. Berrange 已提交
4782 4783 4784
}


4785 4786 4787 4788
static char *qemuDomainXMLFromNative(virConnectPtr conn,
                                     const char *format,
                                     const char *config,
                                     unsigned int flags ATTRIBUTE_UNUSED) {
4789
    struct qemud_driver *driver = conn->privateData;
4790 4791 4792 4793
    virDomainDefPtr def = NULL;
    char *xml = NULL;

    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
4794 4795
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("unsupported config type %s"), format);
4796 4797 4798
        goto cleanup;
    }

4799
    qemuDriverLock(driver);
4800
    def = qemuParseCommandLineString(driver->caps, config);
4801
    qemuDriverUnlock(driver);
4802 4803 4804
    if (!def)
        goto cleanup;

4805
    xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
4806 4807 4808 4809 4810 4811

cleanup:
    virDomainDefFree(def);
    return xml;
}

4812 4813 4814 4815 4816 4817
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;
4818
    virDomainChrDef monConfig;
4819
    const char *emulator;
4820
    unsigned long long qemuCmdFlags;
4821 4822 4823 4824 4825 4826 4827 4828
    struct stat sb;
    const char **retargv = NULL;
    const char **retenv = NULL;
    const char **tmp;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *ret = NULL;
    int i;

4829 4830
    qemuDriverLock(driver);

4831
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
4832 4833
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("unsupported config type %s"), format);
4834 4835 4836
        goto cleanup;
    }

4837
    def = virDomainDefParseString(driver->caps, xmlData, 0);
4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881
    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) {
4882
        virReportSystemError(errno,
4883 4884 4885 4886 4887 4888 4889 4890
                             _("Cannot find QEMU binary %s"),
                             emulator);
        goto cleanup;
    }

    if (qemudExtractVersionInfo(emulator,
                                NULL,
                                &qemuCmdFlags) < 0) {
4891 4892 4893
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot determine QEMU argv syntax %s"),
                        emulator);
4894 4895 4896
        goto cleanup;
    }

4897
    if (qemuPrepareMonitorChr(driver, &monConfig, def->name) < 0)
4898
        goto cleanup;
4899 4900

    if (qemudBuildCommandLine(conn, driver, def,
D
Daniel P. Berrange 已提交
4901
                              &monConfig, 0, qemuCmdFlags,
4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920
                              &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++;
    }

4921 4922
    if (virBufferError(&buf)) {
        virBufferFreeAndReset(&buf);
4923
        virReportOOMError();
4924
        goto cleanup;
4925
    }
4926 4927 4928 4929

    ret = virBufferContentAndReset(&buf);

cleanup:
4930
    qemuDriverUnlock(driver);
4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943
    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;
}


4944
static int qemudListDefinedDomains(virConnectPtr conn,
4945
                            char **const names, int nnames) {
4946
    struct qemud_driver *driver = conn->privateData;
4947
    int n;
4948

4949
    qemuDriverLock(driver);
4950
    n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
4951
    qemuDriverUnlock(driver);
4952
    return n;
D
Daniel P. Berrange 已提交
4953 4954
}

4955
static int qemudNumDefinedDomains(virConnectPtr conn) {
4956
    struct qemud_driver *driver = conn->privateData;
4957
    int n;
4958

4959
    qemuDriverLock(driver);
4960
    n = virDomainObjListNumOfDomains(&driver->domains, 0);
4961
    qemuDriverUnlock(driver);
4962

4963
    return n;
D
Daniel P. Berrange 已提交
4964 4965 4966
}


4967
static int qemudDomainStart(virDomainPtr dom) {
4968 4969 4970
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
4971
    virDomainEventPtr event = NULL;
4972

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

4976
    if (!vm) {
4977 4978
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
4979 4980
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
4981
        goto cleanup;
4982 4983
    }

4984 4985 4986 4987
    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
        goto cleanup;

    if (virDomainObjIsActive(vm)) {
4988 4989
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is already running"));
4990 4991 4992
        goto endjob;
    }

4993
    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
4994
    if (ret != -1)
4995 4996 4997
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STARTED,
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED);
4998

4999
endjob:
5000 5001
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
5002

5003
cleanup:
5004 5005
    if (vm)
        virDomainObjUnlock(vm);
5006
    if (event)
5007
        qemuDomainEventQueue(driver, event);
5008
    qemuDriverUnlock(driver);
5009
    return ret;
D
Daniel P. Berrange 已提交
5010 5011
}

5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026
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;

5027
        if (STRNEQ(def->os.machine, machine->name))
5028 5029 5030
            continue;

        if (!(*canonical = strdup(machine->canonical))) {
5031
            virReportOOMError();
5032 5033 5034 5035 5036 5037 5038 5039 5040
            return -1;
        }

        break;
    }

    return 0;
}

5041 5042 5043 5044 5045 5046 5047
static int
qemudCanonicalizeMachineDirect(virDomainDefPtr def, char **canonical)
{
    virCapsGuestMachinePtr *machines = NULL;
    int i, nmachines = 0;

    if (qemudProbeMachineTypes(def->emulator, &machines, &nmachines) < 0) {
5048
        virReportOOMError();
5049 5050 5051 5052 5053 5054 5055
        return -1;
    }

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

5056
        if (STRNEQ(def->os.machine, machines[i]->name))
5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068
            continue;

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

    virCapabilitiesFreeMachines(machines, nmachines);

    return 0;
}

5069 5070
int
qemudCanonicalizeMachine(struct qemud_driver *driver, virDomainDefPtr def)
5071 5072 5073 5074 5075 5076
{
    char *canonical = NULL;
    int i;

    for (i = 0; i < driver->caps->nguests; i++) {
        virCapsGuestPtr guest = driver->caps->guests[i];
5077
        virCapsGuestDomainInfoPtr info;
5078 5079 5080
        int j;

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

5083 5084 5085 5086 5087 5088 5089 5090 5091
            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;
5092 5093
        }

5094 5095 5096 5097
        info = &guest->arch.defaultInfo;

        if (info->emulator && STREQ(info->emulator, def->emulator)) {
            if (qemudCanonicalizeMachineFromInfo(def, info, &canonical) < 0)
5098 5099 5100 5101
                return -1;
            goto out;
        }
    }
5102 5103 5104 5105

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

5106 5107 5108 5109 5110 5111 5112
out:
    if (canonical) {
        VIR_FREE(def->os.machine);
        def->os.machine = canonical;
    }
    return 0;
}
D
Daniel P. Berrange 已提交
5113

5114
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
5115
    struct qemud_driver *driver = conn->privateData;
5116
    virDomainDefPtr def;
5117
    virDomainObjPtr vm = NULL;
5118
    virDomainPtr dom = NULL;
5119
    virDomainEventPtr event = NULL;
5120
    int dupVM;
5121

5122
    qemuDriverLock(driver);
5123
    if (!(def = virDomainDefParseString(driver->caps, xml,
5124
                                        VIR_DOMAIN_XML_INACTIVE)))
5125
        goto cleanup;
5126

5127
    if (virSecurityDriverVerify(def) < 0)
5128 5129
        goto cleanup;

5130 5131
    if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
        goto cleanup;
5132

5133
    if (qemudCanonicalizeMachine(driver, def) < 0)
5134 5135
        goto cleanup;

5136 5137 5138
    if (qemuAssignPCIAddresses(def) < 0)
        goto cleanup;

5139
    if (!(vm = virDomainAssignDef(driver->caps,
5140 5141
                                  &driver->domains,
                                  def))) {
5142
        goto cleanup;
5143
    }
5144
    def = NULL;
5145
    vm->persistent = 1;
5146

5147
    if (virDomainSaveConfig(driver->configDir,
5148
                            vm->newDef ? vm->newDef : vm->def) < 0) {
5149 5150
        virDomainRemoveInactive(&driver->domains,
                                vm);
5151
        vm = NULL;
5152
        goto cleanup;
5153 5154
    }

5155 5156
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
5157
                                     !dupVM ?
5158 5159
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
5160

5161
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
5162
    if (dom) dom->id = vm->def->id;
5163 5164

cleanup:
5165
    virDomainDefFree(def);
5166 5167
    if (vm)
        virDomainObjUnlock(vm);
5168 5169
    if (event)
        qemuDomainEventQueue(driver, event);
5170
    qemuDriverUnlock(driver);
5171
    return dom;
D
Daniel P. Berrange 已提交
5172 5173
}

5174
static int qemudDomainUndefine(virDomainPtr dom) {
5175 5176
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
5177
    virDomainEventPtr event = NULL;
5178
    int ret = -1;
D
Daniel P. Berrange 已提交
5179

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

D
Daniel P. Berrange 已提交
5183
    if (!vm) {
5184 5185
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
5186 5187
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
5188
        goto cleanup;
D
Daniel P. Berrange 已提交
5189 5190
    }

D
Daniel P. Berrange 已提交
5191
    if (virDomainObjIsActive(vm)) {
5192 5193
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot delete active domain"));
5194
        goto cleanup;
D
Daniel P. Berrange 已提交
5195 5196
    }

5197
    if (!vm->persistent) {
5198 5199
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("cannot undefine transient domain"));
5200
        goto cleanup;
5201 5202
    }

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

5206 5207 5208
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
5209

5210 5211
    virDomainRemoveInactive(&driver->domains,
                            vm);
5212
    vm = NULL;
5213
    ret = 0;
D
Daniel P. Berrange 已提交
5214

5215
cleanup:
5216 5217
    if (vm)
        virDomainObjUnlock(vm);
5218 5219
    if (event)
        qemuDomainEventQueue(driver, event);
5220
    qemuDriverUnlock(driver);
5221
    return ret;
D
Daniel P. Berrange 已提交
5222 5223
}

5224

5225
static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
5226
                                           virDomainObjPtr vm,
5227
                                           virDomainDiskDefPtr disk)
5228
{
5229
    virDomainDiskDefPtr origdisk = NULL;
5230
    int i;
5231
    int ret;
5232

5233
    origdisk = NULL;
5234
    for (i = 0 ; i < vm->def->ndisks ; i++) {
5235 5236
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
5237
            origdisk = vm->def->disks[i];
5238
            break;
5239
        }
5240 5241 5242
    }

    if (!origdisk) {
5243 5244 5245 5246
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("No device with bus '%s' and target '%s'"),
                        virDomainDiskBusTypeToString(disk->bus),
                        disk->dst);
5247 5248 5249
        return -1;
    }

5250
    if (!origdisk->info.alias) {
5251 5252
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("missing disk device alias name for %s"), origdisk->dst);
5253 5254
        return -1;
    }
5255

5256 5257
    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
        origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
5258 5259 5260
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Removable media not supported for %s device"),
                        virDomainDiskDeviceTypeToString(disk->device));
5261
        return -1;
5262
    }
5263

5264 5265
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
5266
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
5267 5268
        return -1;

5269
    qemuDomainObjPrivatePtr priv = vm->privateData;
5270
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5271
    if (disk->src) {
5272
        const char *format = NULL;
5273 5274 5275
        if (disk->type != VIR_DOMAIN_DISK_TYPE_DIR) {
            if (disk->driverType)
                format = disk->driverType;
5276 5277 5278
            else if (origdisk->driverType)
                format = origdisk->driverType;
        }
5279 5280
        ret = qemuMonitorChangeMedia(priv->mon,
                                     origdisk->info.alias,
5281
                                     disk->src, format);
5282
    } else {
5283
        ret = qemuMonitorEjectMedia(priv->mon, origdisk->info.alias);
5284
    }
5285
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5286

5287 5288 5289 5290 5291
    if (ret < 0)
        goto error;

    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5292
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, origdisk) < 0)
5293 5294 5295
        VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src);

    VIR_FREE(origdisk->src);
5296 5297 5298 5299 5300
    origdisk->src = disk->src;
    disk->src = NULL;
    origdisk->type = disk->type;

    virDomainDiskDefFree(disk);
5301

5302
    return ret;
5303 5304 5305 5306

error:
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5307
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
5308
        VIR_WARN("Unable to restore security label on new media %s", disk->src);
5309
    return -1;
5310 5311
}

5312

5313
static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver,
5314
                                          virDomainObjPtr vm,
5315 5316
                                          virDomainDiskDefPtr disk,
                                          int qemuCmdFlags)
5317
{
5318
    int i, ret;
5319
    const char* type = virDomainDiskBusTypeToString(disk->bus);
5320
    qemuDomainObjPrivatePtr priv = vm->privateData;
5321 5322
    char *devstr = NULL;
    char *drivestr = NULL;
5323 5324

    for (i = 0 ; i < vm->def->ndisks ; i++) {
5325
        if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
5326 5327
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s already exists"), disk->dst);
5328 5329 5330 5331
            return -1;
        }
    }

5332 5333
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
5334
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
5335 5336
        return -1;

5337
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
5338 5339
        if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0)
            goto error;
5340 5341
        if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0)
            goto error;
5342

5343 5344 5345
        if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
            goto error;

5346
        if (!(devstr = qemuBuildDriveDevStr(disk)))
5347 5348 5349
            goto error;
    }

5350
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
5351
        virReportOOMError();
5352
        goto error;
5353 5354
    }

5355
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371
    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));
        }
    }
5372
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5373

5374 5375
    if (ret < 0)
        goto error;
5376

5377
    virDomainDiskInsertPreAlloced(vm->def, disk);
5378

5379 5380 5381
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

5382 5383 5384
    return 0;

error:
5385 5386 5387
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

5388 5389 5390 5391 5392
    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);

5393 5394
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5395
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
5396
        VIR_WARN("Unable to restore security label on %s", disk->src);
5397 5398

    return -1;
5399
}
5400

5401

5402
static int qemudDomainAttachPciControllerDevice(struct qemud_driver *driver,
5403
                                                virDomainObjPtr vm,
5404 5405
                                                virDomainControllerDefPtr controller,
                                                int qemuCmdFlags)
5406
{
5407 5408
    int i;
    int ret = -1;
5409
    const char* type = virDomainControllerTypeToString(controller->type);
5410
    char *devstr = NULL;
5411 5412 5413
    qemuDomainObjPrivatePtr priv = vm->privateData;

    for (i = 0 ; i < vm->def->ncontrollers ; i++) {
5414 5415
        if ((vm->def->controllers[i]->type == controller->type) &&
            (vm->def->controllers[i]->idx == controller->idx)) {
5416 5417 5418
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s:%d already exists"),
                            type, controller->idx);
5419 5420 5421 5422
            return -1;
        }
    }

5423 5424 5425 5426 5427 5428
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0)
            goto cleanup;
        if (qemuAssignDeviceControllerAlias(controller) < 0)
            goto cleanup;
    }
5429

5430
    if (!(devstr = qemuBuildControllerDevStr(controller))) {
5431
        virReportOOMError();
5432 5433 5434
        goto cleanup;
    }

5435
    if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers+1) < 0) {
5436
        virReportOOMError();
5437
        goto cleanup;
5438 5439 5440
    }

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5441 5442 5443 5444 5445 5446 5447
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        ret = qemuMonitorAddDevice(priv->mon, devstr);
    } else {
        ret = qemuMonitorAttachPCIDiskController(priv->mon,
                                                 type,
                                                 &controller->info.addr.pci);
    }
5448 5449 5450
    qemuDomainObjExitMonitorWithDriver(driver, vm);

    if (ret == 0) {
5451 5452
        controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
        virDomainControllerInsertPreAlloced(vm->def, controller);
5453 5454
    }

5455
cleanup:
5456 5457 5458 5459 5460 5461
    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");

5462
    VIR_FREE(devstr);
5463 5464 5465
    return ret;
}

5466

5467
static virDomainControllerDefPtr
5468
qemuDomainFindOrCreateSCSIDiskController(struct qemud_driver *driver,
5469
                                         virDomainObjPtr vm,
5470 5471
                                         int controller,
                                         int qemuCmdFlags)
5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487
{
    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;
    }

    /* No SCSI controller present, for back compatability we
     * now hotplug a controller */
    if (VIR_ALLOC(cont) < 0) {
5488
        virReportOOMError();
5489 5490 5491 5492 5493 5494
        return NULL;
    }
    cont->type = VIR_DOMAIN_CONTROLLER_TYPE_SCSI;
    cont->idx = 0;

    VIR_INFO0("No SCSI controller present, hotplugging one");
5495
    if (qemudDomainAttachPciControllerDevice(driver,
5496
                                             vm, cont, qemuCmdFlags) < 0) {
5497 5498 5499 5500 5501 5502
        VIR_FREE(cont);
        return NULL;
    }
    return cont;
}

5503

5504
static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver,
5505
                                     virDomainObjPtr vm,
5506
                                     virDomainDiskDefPtr disk,
5507 5508 5509 5510 5511 5512
                                     int qemuCmdFlags)
{
    int i;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virDomainControllerDefPtr cont;
    char *drivestr = NULL;
5513
    char *devstr = NULL;
5514 5515 5516
    int ret = -1;

    for (i = 0 ; i < vm->def->ndisks ; i++) {
5517
        if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
5518 5519
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s already exists"), disk->dst);
5520
            return -1;
5521 5522 5523
        }
    }

5524 5525 5526

    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
5527
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
5528 5529
        return -1;

5530
    /* We should have an address already, so make sure */
5531
    if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
5532 5533 5534
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected disk address type %s"),
                        virDomainDeviceAddressTypeToString(disk->info.type));
5535
        goto error;
5536 5537
    }

5538 5539 5540
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0)
            goto error;
5541
        if (!(devstr = qemuBuildDriveDevStr(disk)))
5542 5543 5544 5545 5546 5547
            goto error;
    }

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

5548
    for (i = 0 ; i <= disk->info.addr.drive.controller ; i++) {
5549
        cont = qemuDomainFindOrCreateSCSIDiskController(driver, vm, i, qemuCmdFlags);
5550
        if (!cont)
5551
            goto error;
5552 5553 5554
    }

    if (cont->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
5555 5556
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("SCSI controller %d was missing its PCI address"), cont->idx);
5557
        goto error;
5558 5559 5560
    }

    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
5561
        virReportOOMError();
5562
        goto error;
5563 5564 5565
    }

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585
    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));
        }
    }
5586 5587
    qemuDomainObjExitMonitorWithDriver(driver, vm);

5588 5589
    if (ret < 0)
        goto error;
5590

5591
    virDomainDiskInsertPreAlloced(vm->def, disk);
5592 5593

    VIR_FREE(devstr);
5594
    VIR_FREE(drivestr);
5595 5596 5597 5598

    return 0;

error:
5599
    VIR_FREE(devstr);
5600
    VIR_FREE(drivestr);
5601

5602 5603
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5604
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
5605
        VIR_WARN("Unable to restore security label on %s", disk->src);
5606 5607

    return -1;
5608 5609
}

5610

5611
static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
5612
                                                 virDomainObjPtr vm,
5613 5614
                                                 virDomainDiskDefPtr disk,
                                                 int qemuCmdFlags)
5615
{
5616
    qemuDomainObjPrivatePtr priv = vm->privateData;
5617
    int i, ret;
5618 5619
    char *drivestr = NULL;
    char *devstr = NULL;
5620

5621
    for (i = 0 ; i < vm->def->ndisks ; i++) {
5622
        if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
5623 5624
            qemuReportError(VIR_ERR_OPERATION_FAILED,
                            _("target %s already exists"), disk->dst);
5625 5626 5627 5628
            return -1;
        }
    }

5629 5630
    if (driver->securityDriver &&
        driver->securityDriver->domainSetSecurityImageLabel &&
5631
        driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
5632 5633
        return -1;

5634
    if (!disk->src) {
5635 5636
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("disk source path is missing"));
5637
        goto error;
5638 5639
    }

5640
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
5641 5642
        if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0)
            goto error;
5643 5644
        if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
            goto error;
5645
        if (!(devstr = qemuBuildDriveDevStr(disk)))
5646 5647 5648
            goto error;
    }

5649
    if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
5650
        virReportOOMError();
5651
        goto error;
5652 5653
    }

5654
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5655 5656 5657 5658 5659 5660 5661 5662 5663 5664
    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);
    }
5665
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5666

5667 5668 5669
    if (ret < 0)
        goto error;

5670
    virDomainDiskInsertPreAlloced(vm->def, disk);
5671

5672 5673 5674
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

5675 5676 5677
    return 0;

error:
5678 5679 5680
    VIR_FREE(devstr);
    VIR_FREE(drivestr);

5681 5682
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
5683
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
5684
        VIR_WARN("Unable to restore security label on %s", disk->src);
5685 5686

    return -1;
5687 5688
}

5689

5690
/* XXX conn required for network -> bridge resolution */
M
Mark McLoughlin 已提交
5691
static int qemudDomainAttachNetDevice(virConnectPtr conn,
5692
                                      struct qemud_driver *driver,
M
Mark McLoughlin 已提交
5693
                                      virDomainObjPtr vm,
5694
                                      virDomainNetDefPtr net,
5695
                                      unsigned long long qemuCmdFlags)
M
Mark McLoughlin 已提交
5696
{
5697
    qemuDomainObjPrivatePtr priv = vm->privateData;
5698
    char *tapfd_name = NULL;
5699
    int tapfd = -1;
5700
    char *nicstr = NULL;
5701
    char *netstr = NULL;
5702
    int ret = -1;
5703
    virDomainDevicePCIAddress guestAddr;
5704
    int vlan;
M
Mark McLoughlin 已提交
5705 5706

    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_HOST_NET_ADD)) {
5707 5708
        qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
                        _("installed qemu version does not support host_net_add"));
M
Mark McLoughlin 已提交
5709 5710 5711 5712 5713
        return -1;
    }

    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
        net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
5714
        if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
5715 5716 5717 5718
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("network device type '%s' cannot be attached: "
                              "qemu is not using a unix socket monitor"),
                            virDomainNetTypeToString(net->type));
5719 5720 5721 5722 5723
            return -1;
        }

        if ((tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags)) < 0)
            return -1;
5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736
    } 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;
        }

        if ((tapfd = qemudPhysIfaceConnect(conn, net,
                                           net->data.direct.linkdev,
                                           net->data.direct.mode)) < 0)
            return -1;
M
Mark McLoughlin 已提交
5737 5738
    }

5739 5740
    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0)
        goto no_memory;
M
Mark McLoughlin 已提交
5741

5742 5743 5744 5745 5746
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_NET_NAME) ||
        (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
        if (qemuAssignDeviceNetAlias(vm->def, net, -1) < 0)
            goto cleanup;
    }
M
Mark McLoughlin 已提交
5747

5748 5749 5750 5751
    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
        qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0)
        goto cleanup;

5752
    vlan = qemuDomainNetVLAN(net);
M
Mark McLoughlin 已提交
5753

5754
    if (vlan < 0) {
5755 5756
        qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
                        _("Unable to attach network devices without vlan"));
5757 5758 5759
        goto cleanup;
    }

5760
    if (tapfd != -1) {
5761
        if (virAsprintf(&tapfd_name, "fd-%s", net->info.alias) < 0)
5762 5763
            goto no_memory;

5764
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
5765
        if (qemuMonitorSendFileHandle(priv->mon, tapfd_name, tapfd) < 0) {
5766
            qemuDomainObjExitMonitorWithDriver(driver, vm);
5767
            goto cleanup;
5768
        }
5769
        qemuDomainObjExitMonitorWithDriver(driver, vm);
5770 5771
    }

5772
    if (!(netstr = qemuBuildHostNetStr(net, ' ',
5773
                                       vlan, tapfd_name)))
5774
        goto try_tapfd_close;
M
Mark McLoughlin 已提交
5775

5776
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5777
    if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) {
5778
        qemuDomainObjExitMonitorWithDriver(driver, vm);
5779
        goto try_tapfd_close;
5780
    }
5781
    qemuDomainObjExitMonitorWithDriver(driver, vm);
M
Mark McLoughlin 已提交
5782

5783 5784 5785
    if (tapfd != -1)
        close(tapfd);
    tapfd = -1;
M
Mark McLoughlin 已提交
5786

5787
    if (!(nicstr = qemuBuildNicStr(net, NULL, vlan)))
5788
        goto try_remove;
M
Mark McLoughlin 已提交
5789

5790
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5791
    if (qemuMonitorAddPCINetwork(priv->mon, nicstr,
5792
                                 &guestAddr) < 0) {
5793
        qemuDomainObjExitMonitorWithDriver(driver, vm);
5794
        goto try_remove;
5795
    }
5796
    net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
5797
    memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr));
5798
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5799

5800
    ret = 0;
M
Mark McLoughlin 已提交
5801 5802 5803

    vm->def->nets[vm->def->nnets++] = net;

5804
cleanup:
5805 5806 5807 5808 5809 5810
    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");

5811 5812 5813 5814 5815
    VIR_FREE(nicstr);
    VIR_FREE(netstr);
    VIR_FREE(tapfd_name);
    if (tapfd != -1)
        close(tapfd);
5816

5817
    return ret;
5818

5819
try_remove:
5820
    if (vlan < 0) {
5821
        VIR_WARN0(_("Unable to remove network backend"));
5822 5823 5824 5825
    } else {
        char *hostnet_name;
        if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0)
            goto no_memory;
5826
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
5827
        if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0)
5828
            VIR_WARN(_("Failed to remove network backend for vlan %d, net %s"),
5829
                     vlan, hostnet_name);
5830
        qemuDomainObjExitMonitorWithDriver(driver, vm);
5831
        VIR_FREE(hostnet_name);
5832
    }
5833
    goto cleanup;
5834

5835
try_tapfd_close:
5836
    if (tapfd_name) {
5837
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
5838
        if (qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0)
5839
            VIR_WARN(_("Failed to close tapfd with '%s'"), tapfd_name);
5840
        qemuDomainObjExitMonitorWithDriver(driver, vm);
5841
    }
5842

5843 5844
    goto cleanup;

5845
no_memory:
5846
    virReportOOMError();
5847
    goto cleanup;
M
Mark McLoughlin 已提交
5848 5849
}

5850

5851
static int qemudDomainAttachHostPciDevice(struct qemud_driver *driver,
5852
                                          virDomainObjPtr vm,
5853 5854
                                          virDomainHostdevDefPtr hostdev,
                                          int qemuCmdFlags)
5855
{
5856
    qemuDomainObjPrivatePtr priv = vm->privateData;
5857
    pciDevice *pci;
5858
    int ret;
5859
    virDomainDevicePCIAddress guestAddr;
5860
    char *devstr = NULL;
5861 5862

    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
5863
        virReportOOMError();
5864 5865 5866
        return -1;
    }

5867
    pci = pciGetDevice(hostdev->source.subsys.u.pci.domain,
5868 5869 5870
                       hostdev->source.subsys.u.pci.bus,
                       hostdev->source.subsys.u.pci.slot,
                       hostdev->source.subsys.u.pci.function);
5871
    if (!pci)
5872
        return -1;
5873

5874 5875 5876 5877
    if (!pciDeviceIsAssignable(pci, !driver->relaxedACS) ||
        (hostdev->managed && pciDettachDevice(pci) < 0) ||
        pciResetDevice(pci, driver->activePciHostdevs) < 0) {
        pciFreeDevice(pci);
5878 5879 5880
        return -1;
    }

5881 5882
    if (pciDeviceListAdd(driver->activePciHostdevs, pci) < 0) {
        pciFreeDevice(pci);
5883
        return -1;
5884 5885
    }

5886 5887 5888 5889 5890 5891 5892
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
        if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &hostdev->info) < 0)
            goto error;

        if (!(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
            goto error;
    }
5893

5894
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5895 5896 5897 5898 5899 5900
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
        ret = qemuMonitorAddDevice(priv->mon, devstr);
    else
        ret = qemuMonitorAddPCIHostDevice(priv->mon,
                                          &hostdev->source.subsys.u.pci,
                                          &guestAddr);
5901
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5902
    if (ret < 0)
5903
        goto error;
5904
    hostdev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
5905
    memcpy(&hostdev->info.addr.pci, &guestAddr, sizeof(guestAddr));
5906 5907 5908

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;

5909 5910
    VIR_FREE(devstr);

5911
    return 0;
5912 5913

error:
5914 5915 5916 5917 5918
    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");

5919
    VIR_FREE(devstr);
5920
    pciDeviceListDel(driver->activePciHostdevs, pci);
5921 5922

    return -1;
5923 5924
}

5925

5926
static int qemudDomainAttachHostUsbDevice(struct qemud_driver *driver,
M
Mark McLoughlin 已提交
5927
                                          virDomainObjPtr vm,
5928 5929
                                          virDomainHostdevDefPtr hostdev,
                                          int qemuCmdFlags)
5930 5931
{
    int ret;
5932
    qemuDomainObjPrivatePtr priv = vm->privateData;
5933 5934 5935 5936 5937
    char *devstr = NULL;

    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
        !(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
        goto error;
5938

5939
    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
5940
        virReportOOMError();
5941
        goto error;
5942
    }
5943

5944
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
5945 5946 5947
    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
        ret = qemuMonitorAddDevice(priv->mon, devstr);
    else
5948
        ret = qemuMonitorAddUSBDeviceExact(priv->mon,
5949 5950
                                           hostdev->source.subsys.u.usb.bus,
                                           hostdev->source.subsys.u.usb.device);
5951
    qemuDomainObjExitMonitorWithDriver(driver, vm);
5952 5953 5954 5955
    if (ret < 0)
        goto error;

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
5956

5957
    VIR_FREE(devstr);
5958

5959 5960 5961 5962 5963
    return 0;

error:
    VIR_FREE(devstr);
    return -1;
5964 5965
}

5966

5967
static int qemudDomainAttachHostDevice(struct qemud_driver *driver,
M
Mark McLoughlin 已提交
5968
                                       virDomainObjPtr vm,
5969 5970
                                       virDomainHostdevDefPtr hostdev,
                                       int qemuCmdFlags)
M
Mark McLoughlin 已提交
5971 5972
{
    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
5973 5974 5975
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev mode '%s' not supported"),
                        virDomainHostdevModeTypeToString(hostdev->mode));
M
Mark McLoughlin 已提交
5976 5977 5978
        return -1;
    }

5979
    if (driver->securityDriver &&
5980
        driver->securityDriver->domainSetSecurityHostdevLabel &&
5981
        driver->securityDriver->domainSetSecurityHostdevLabel(vm, hostdev) < 0)
5982
        return -1;
M
Mark McLoughlin 已提交
5983 5984

    switch (hostdev->source.subsys.type) {
5985
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
5986
        if (qemudDomainAttachHostPciDevice(driver, vm,
5987
                                           hostdev, qemuCmdFlags) < 0)
5988 5989 5990
            goto error;
        break;

M
Mark McLoughlin 已提交
5991
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
5992
        if (qemudDomainAttachHostUsbDevice(driver, vm,
5993
                                           hostdev, qemuCmdFlags) < 0)
5994 5995 5996
            goto error;
        break;

M
Mark McLoughlin 已提交
5997
    default:
5998 5999 6000
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev subsys type '%s' not supported"),
                        virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
6001
        goto error;
M
Mark McLoughlin 已提交
6002
    }
6003 6004 6005 6006 6007 6008

    return 0;

error:
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityHostdevLabel &&
6009
        driver->securityDriver->domainRestoreSecurityHostdevLabel(vm, hostdev) < 0)
6010 6011 6012
        VIR_WARN0("Unable to restore host device labelling on hotplug fail");

    return -1;
M
Mark McLoughlin 已提交
6013 6014
}

6015

6016
static int qemudDomainAttachDevice(virDomainPtr dom,
6017 6018
                                   const char *xml)
{
6019 6020 6021
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
6022
    unsigned long long qemuCmdFlags;
6023
    virCgroupPtr cgroup = NULL;
6024
    int ret = -1;
6025

6026
    qemuDriverLock(driver);
6027
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6028
    if (!vm) {
6029 6030
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
6031 6032
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6033
        goto cleanup;
6034 6035
    }

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

D
Daniel P. Berrange 已提交
6039
    if (!virDomainObjIsActive(vm)) {
6040 6041
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot attach device on inactive domain"));
6042
        goto endjob;
6043 6044
    }

6045
    dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
6046
                                  VIR_DOMAIN_XML_INACTIVE);
6047
    if (dev == NULL)
6048
        goto endjob;
6049

6050 6051 6052
    if (qemudExtractVersionInfo(vm->def->emulator,
                                NULL,
                                &qemuCmdFlags) < 0)
6053
        goto endjob;
6054

6055
    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
6056
        if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
6057
            if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) {
6058 6059 6060
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("Unable to find cgroup for %s\n"),
                                vm->def->name);
6061
                goto endjob;
6062 6063 6064 6065 6066
            }
            if (dev->data.disk->src != NULL &&
                dev->data.disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
                virCgroupAllowDevicePath(cgroup,
                                         dev->data.disk->src) < 0) {
6067 6068 6069
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                _("unable to allow device %s"),
                                dev->data.disk->src);
6070
                goto endjob;
6071 6072 6073
            }
        }

6074
        switch (dev->data.disk->device) {
6075 6076
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
        case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
6077
            ret = qemudDomainChangeEjectableMedia(driver, vm, dev->data.disk);
6078 6079
            if (ret == 0)
                dev->data.disk = NULL;
6080
            break;
6081

6082 6083
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
6084
                ret = qemudDomainAttachUsbMassstorageDevice(driver, vm,
6085
                                                            dev->data.disk, qemuCmdFlags);
6086 6087
                if (ret == 0)
                    dev->data.disk = NULL;
6088
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
6089
                ret = qemudDomainAttachPciDiskDevice(driver, vm,
6090
                                                     dev->data.disk, qemuCmdFlags);
6091 6092
                if (ret == 0)
                    dev->data.disk = NULL;
6093
            } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
6094
                ret = qemudDomainAttachSCSIDisk(driver, vm,
6095
                                                dev->data.disk, qemuCmdFlags);
6096 6097
                if (ret == 0)
                    dev->data.disk = NULL;
6098
            } else {
6099 6100 6101
                qemuReportError(VIR_ERR_NO_SUPPORT,
                                _("disk bus '%s' cannot be hotplugged."),
                                virDomainDiskBusTypeToString(dev->data.disk->bus));
6102
                /* fallthrough */
6103 6104
            }
            break;
6105

6106
        default:
6107 6108 6109
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("disk device type '%s' cannot be hotplugged"),
                            virDomainDiskDeviceTypeToString(dev->data.disk->device));
6110 6111
            /* Fallthrough */
        }
6112
        if (ret != 0 && cgroup) {
6113 6114
            virCgroupDenyDevicePath(cgroup,
                                    dev->data.disk->src);
6115
        }
6116 6117
    } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) {
        if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
6118
            ret = qemudDomainAttachPciControllerDevice(driver, vm,
6119
                                                       dev->data.controller, qemuCmdFlags);
6120
        } else {
6121 6122 6123
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("disk controller bus '%s' cannot be hotplugged."),
                            virDomainControllerTypeToString(dev->data.controller->type));
6124 6125
            /* fallthrough */
        }
M
Mark McLoughlin 已提交
6126
    } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
6127 6128
        ret = qemudDomainAttachNetDevice(dom->conn, driver, vm,
                                         dev->data.net, qemuCmdFlags);
6129 6130
        if (ret == 0)
            dev->data.net = NULL;
M
Mark McLoughlin 已提交
6131
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
6132
        ret = qemudDomainAttachHostDevice(driver, vm,
6133
                                          dev->data.hostdev, qemuCmdFlags);
6134 6135
        if (ret == 0)
            dev->data.hostdev = NULL;
6136
    } else {
6137 6138 6139
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("device type '%s' cannot be attached"),
                        virDomainDeviceTypeToString(dev->type));
6140
        goto endjob;
6141 6142
    }

6143
    if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
6144 6145
        ret = -1;

6146
endjob:
6147 6148
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
6149

6150
cleanup:
6151 6152 6153
    if (cgroup)
        virCgroupFree(&cgroup);

6154
    virDomainDeviceDefFree(dev);
6155 6156
    if (vm)
        virDomainObjUnlock(vm);
6157
    qemuDriverUnlock(driver);
6158 6159 6160
    return ret;
}

6161 6162 6163 6164
static int qemudDomainAttachDeviceFlags(virDomainPtr dom,
                                        const char *xml,
                                        unsigned int flags) {
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
6165 6166
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify the persistent configuration of a domain"));
6167 6168 6169 6170 6171 6172
        return -1;
    }

    return qemudDomainAttachDevice(dom, xml);
}

6173
static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
6174 6175
                                          virDomainObjPtr vm,
                                          virDomainDeviceDefPtr dev)
6176 6177 6178
{
    int i, ret = -1;
    virDomainDiskDefPtr detach = NULL;
6179
    qemuDomainObjPrivatePtr priv = vm->privateData;
6180 6181 6182 6183 6184 6185 6186 6187 6188

    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) {
6189 6190
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("disk %s not found"), dev->data.disk->dst);
6191
        goto cleanup;
6192 6193
    }

6194 6195
    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
6196 6197
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                        _("device cannot be detached without a PCI address"));
6198
        goto cleanup;
6199 6200
    }

6201
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6202
    if (qemuMonitorRemovePCIDevice(priv->mon,
6203
                                   &detach->info.addr.pci) < 0) {
6204
        qemuDomainObjExitMonitor(vm);
6205
        goto cleanup;
6206
    }
6207
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6208

6209 6210 6211 6212 6213 6214 6215 6216 6217 6218
    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 {
6219
        VIR_FREE(vm->def->disks);
6220
        vm->def->ndisks = 0;
6221
    }
6222
    virDomainDiskDefFree(detach);
6223

6224 6225
    if (driver->securityDriver &&
        driver->securityDriver->domainRestoreSecurityImageLabel &&
6226
        driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0)
6227 6228
        VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);

6229
    ret = 0;
6230 6231

cleanup:
6232 6233 6234
    return ret;
}

6235
static int qemudDomainDetachPciControllerDevice(struct qemud_driver *driver,
6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251
                                                virDomainObjPtr vm,
                                                virDomainDeviceDefPtr dev)
{
    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) {
6252 6253 6254 6255
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("disk controller %s:%d not found"),
                        virDomainControllerTypeToString(dev->data.controller->type),
                        dev->data.controller->idx);
6256 6257 6258 6259 6260
        goto cleanup;
    }

    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
6261 6262
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                        _("device cannot be detached without a PCI address"));
6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294
        goto cleanup;
    }

    qemuDomainObjEnterMonitorWithDriver(driver, vm);
    if (qemuMonitorRemovePCIDevice(priv->mon,
                                   &detach->info.addr.pci) < 0) {
        qemuDomainObjExitMonitor(vm);
        goto cleanup;
    }
    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;
    }
    virDomainControllerDefFree(detach);

    ret = 0;

cleanup:
    return ret;
}

6295
static int
6296
qemudDomainDetachNetDevice(struct qemud_driver *driver,
6297 6298 6299 6300 6301
                           virDomainObjPtr vm,
                           virDomainDeviceDefPtr dev)
{
    int i, ret = -1;
    virDomainNetDefPtr detach = NULL;
6302
    qemuDomainObjPrivatePtr priv = vm->privateData;
6303 6304
    int vlan;
    char *hostnet_name = NULL;
6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315

    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) {
6316 6317 6318 6319 6320
        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]);
6321 6322 6323
        goto cleanup;
    }

6324 6325
    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
6326 6327
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("device cannot be detached without a PCI address"));
6328 6329 6330
        goto cleanup;
    }

6331
    if ((vlan = qemuDomainNetVLAN(detach)) < 0) {
6332 6333
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("unable to determine original VLAN"));
6334 6335 6336 6337
        goto cleanup;
    }

    if (virAsprintf(&hostnet_name, "host%s", detach->info.alias) < 0) {
6338
        virReportOOMError();
6339 6340 6341
        goto cleanup;
    }

6342
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6343
    if (qemuMonitorRemovePCIDevice(priv->mon,
6344
                                   &detach->info.addr.pci) < 0) {
6345
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6346
        goto cleanup;
6347
    }
6348

6349
    if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) {
6350
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6351
        goto cleanup;
6352
    }
6353
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6354

6355 6356 6357 6358 6359 6360 6361
#if WITH_MACVTAP
    if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
        int dummy;
        delMacvtapByMACAddress(detach->mac, &dummy);
    }
#endif

6362
    if ((driver->macFilter) && (detach->ifname != NULL)) {
6363
        if ((errno = networkDisallowMacOnPort(driver,
6364 6365
                                              detach->ifname,
                                              detach->mac))) {
6366
            virReportSystemError(errno,
6367 6368 6369 6370 6371
             _("failed to remove ebtables rule on  '%s'"),
                                 detach->ifname);
        }
    }

6372 6373 6374 6375 6376 6377 6378 6379 6380 6381
    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 {
6382
        VIR_FREE(vm->def->nets);
6383
        vm->def->nnets = 0;
6384
    }
6385
    virDomainNetDefFree(detach);
6386

6387 6388 6389
    ret = 0;

cleanup:
6390
    VIR_FREE(hostnet_name);
6391 6392 6393
    return ret;
}

6394
static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver,
6395 6396 6397
                                          virDomainObjPtr vm,
                                          virDomainDeviceDefPtr dev)
{
6398
    virDomainHostdevDefPtr detach = NULL;
6399
    qemuDomainObjPrivatePtr priv = vm->privateData;
6400
    int i, ret;
6401
    pciDevice *pci;
6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418

    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
        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) {
6419 6420 6421 6422 6423 6424
        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);
6425 6426 6427
        return -1;
    }

6428 6429
    if (!virDomainDeviceAddressIsValid(&detach->info,
                                       VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
6430 6431
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("device cannot be detached without a PCI address"));
6432 6433 6434
        return -1;
    }

6435
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
6436
    if (qemuMonitorRemovePCIDevice(priv->mon,
6437
                                   &detach->info.addr.pci) < 0) {
6438
        qemuDomainObjExitMonitorWithDriver(driver, vm);
6439
        return -1;
6440
    }
6441
    qemuDomainObjExitMonitorWithDriver(driver, vm);
6442 6443 6444

    ret = 0;

6445
    pci = pciGetDevice(detach->source.subsys.u.pci.domain,
6446 6447 6448 6449 6450 6451
                       detach->source.subsys.u.pci.bus,
                       detach->source.subsys.u.pci.slot,
                       detach->source.subsys.u.pci.function);
    if (!pci)
        ret = -1;
    else {
6452
        pciDeviceSetManaged(pci, detach->managed);
6453 6454
        pciDeviceListDel(driver->activePciHostdevs, pci);
        if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
6455
            ret = -1;
6456
        qemudReattachManagedDevice(pci);
6457
        pciFreeDevice(pci);
6458 6459
    }

6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471
    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;
6472
    }
6473
    virDomainHostdevDefFree(detach);
6474 6475 6476 6477

    return ret;
}

6478
static int qemudDomainDetachHostDevice(struct qemud_driver *driver,
6479 6480 6481 6482 6483 6484 6485
                                       virDomainObjPtr vm,
                                       virDomainDeviceDefPtr dev)
{
    virDomainHostdevDefPtr hostdev = dev->data.hostdev;
    int ret;

    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
6486 6487 6488
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev mode '%s' not supported"),
                        virDomainHostdevModeTypeToString(hostdev->mode));
6489 6490 6491 6492 6493
        return -1;
    }

    switch (hostdev->source.subsys.type) {
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
6494
        ret = qemudDomainDetachHostPciDevice(driver, vm, dev);
6495
        break;
6496
    default:
6497 6498 6499
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        _("hostdev subsys type '%s' not supported"),
                        virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
6500 6501 6502
        return -1;
    }

6503
    if (driver->securityDriver &&
6504
        driver->securityDriver->domainRestoreSecurityHostdevLabel &&
6505
        driver->securityDriver->domainRestoreSecurityHostdevLabel(vm, dev->data.hostdev) < 0)
6506
        VIR_WARN0("Failed to restore host device labelling");
6507

6508 6509 6510
    return ret;
}

6511 6512
static int qemudDomainDetachDevice(virDomainPtr dom,
                                   const char *xml) {
6513 6514 6515 6516
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;
6517

6518
    qemuDriverLock(driver);
6519
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6520
    if (!vm) {
6521 6522
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
6523 6524
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6525
        goto cleanup;
6526 6527
    }

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

D
Daniel P. Berrange 已提交
6531
    if (!virDomainObjIsActive(vm)) {
6532 6533
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot detach device on inactive domain"));
6534
        goto endjob;
6535 6536
    }

6537
    dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
6538
                                  VIR_DOMAIN_XML_INACTIVE);
6539
    if (dev == NULL)
6540
        goto endjob;
6541

6542 6543 6544

    if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
        dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
6545
        dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
6546
        ret = qemudDomainDetachPciDiskDevice(driver, vm, dev);
6547
    } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
6548
        ret = qemudDomainDetachNetDevice(driver, vm, dev);
6549 6550
    } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) {
        if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
6551
            ret = qemudDomainDetachPciControllerDevice(driver, vm, dev);
6552
        } else {
6553 6554 6555
            qemuReportError(VIR_ERR_NO_SUPPORT,
                            _("disk controller bus '%s' cannot be hotunplugged."),
                            virDomainControllerTypeToString(dev->data.controller->type));
6556 6557
            /* fallthrough */
        }
6558
    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
6559
        ret = qemudDomainDetachHostDevice(driver, vm, dev);
6560
    } else {
6561 6562
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("This type of device cannot be hot unplugged"));
6563
    }
6564

6565
    if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
6566 6567
        ret = -1;

6568
endjob:
6569 6570
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
6571

6572 6573
cleanup:
    virDomainDeviceDefFree(dev);
6574 6575
    if (vm)
        virDomainObjUnlock(vm);
6576
    qemuDriverUnlock(driver);
6577 6578 6579
    return ret;
}

6580 6581 6582 6583
static int qemudDomainDetachDeviceFlags(virDomainPtr dom,
                                        const char *xml,
                                        unsigned int flags) {
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
6584 6585
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify the persistent configuration of a domain"));
6586 6587 6588 6589 6590 6591
        return -1;
    }

    return qemudDomainDetachDevice(dom, xml);
}

6592
static int qemudDomainGetAutostart(virDomainPtr dom,
6593
                                   int *autostart) {
6594 6595 6596
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
6597

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

6602
    if (!vm) {
6603 6604
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
6605 6606
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6607
        goto cleanup;
6608 6609 6610
    }

    *autostart = vm->autostart;
6611
    ret = 0;
6612

6613
cleanup:
6614 6615
    if (vm)
        virDomainObjUnlock(vm);
6616
    return ret;
6617 6618
}

6619
static int qemudDomainSetAutostart(virDomainPtr dom,
6620
                                   int autostart) {
6621 6622
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
6623 6624
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
6625

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

6629
    if (!vm) {
6630 6631
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
6632 6633
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6634
        goto cleanup;
6635 6636
    }

6637
    if (!vm->persistent) {
6638 6639
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("cannot set autostart for transient domain"));
6640
        goto cleanup;
6641 6642
    }

6643 6644
    autostart = (autostart != 0);

6645
    if (vm->autostart != autostart) {
6646
        if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
6647
            goto cleanup;
6648
        if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
6649
            goto cleanup;
6650

6651 6652
        if (autostart) {
            int err;
6653

6654
            if ((err = virFileMakePath(driver->autostartDir))) {
6655
                virReportSystemError(err,
6656 6657
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
6658 6659
                goto cleanup;
            }
6660

6661
            if (symlink(configFile, autostartLink) < 0) {
6662
                virReportSystemError(errno,
6663 6664
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
6665 6666 6667 6668
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
6669
                virReportSystemError(errno,
6670 6671
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
6672 6673
                goto cleanup;
            }
6674 6675
        }

6676
        vm->autostart = autostart;
6677
    }
6678
    ret = 0;
6679

6680 6681 6682
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
6683 6684
    if (vm)
        virDomainObjUnlock(vm);
6685
    qemuDriverUnlock(driver);
6686
    return ret;
6687 6688
}

6689 6690 6691 6692 6693

static char *qemuGetSchedulerType(virDomainPtr dom,
                                  int *nparams)
{
    struct qemud_driver *driver = dom->conn->privateData;
6694
    char *ret = NULL;
6695

6696
    qemuDriverLock(driver);
6697
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
6698 6699
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        __FUNCTION__);
6700
        goto cleanup;
6701 6702 6703 6704 6705 6706 6707
    }

    if (nparams)
        *nparams = 1;

    ret = strdup("posix");
    if (!ret)
6708
        virReportOOMError();
6709 6710 6711

cleanup:
    qemuDriverUnlock(driver);
6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724
    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;

6725
    qemuDriverLock(driver);
6726
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
6727 6728
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        __FUNCTION__);
6729
        goto cleanup;
6730 6731 6732 6733 6734
    }

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

    if (vm == NULL) {
6735 6736
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("No such domain %s"), dom->uuid);
6737 6738 6739 6740
        goto cleanup;
    }

    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
6741 6742
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
6743 6744 6745 6746 6747 6748 6749 6750 6751
        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) {
6752 6753
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
                                _("invalid type for cpu_shares tunable, expected a 'ullong'"));
6754 6755 6756 6757 6758
                goto cleanup;
            }

            rc = virCgroupSetCpuShares(group, params[i].value.ul);
            if (rc != 0) {
6759
                virReportSystemError(-rc, "%s",
6760 6761 6762 6763
                                     _("unable to set cpu shares tunable"));
                goto cleanup;
            }
        } else {
6764 6765
            qemuReportError(VIR_ERR_INVALID_ARG,
                            _("Invalid parameter `%s'"), param->field);
6766 6767 6768 6769 6770 6771 6772 6773 6774
            goto cleanup;
        }
    }
    ret = 0;

cleanup:
    virCgroupFree(&group);
    if (vm)
        virDomainObjUnlock(vm);
6775
    qemuDriverUnlock(driver);
6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789
    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;

6790
    qemuDriverLock(driver);
6791
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
6792 6793
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        __FUNCTION__);
6794
        goto cleanup;
6795 6796 6797
    }

    if ((*nparams) != 1) {
6798 6799
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("Invalid parameter count"));
6800
        goto cleanup;
6801 6802 6803 6804 6805
    }

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

    if (vm == NULL) {
6806 6807
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("No such domain %s"), dom->uuid);
6808 6809 6810 6811
        goto cleanup;
    }

    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
6812 6813
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot find cgroup for domain %s"), vm->def->name);
6814 6815 6816 6817 6818
        goto cleanup;
    }

    rc = virCgroupGetCpuShares(group, &val);
    if (rc != 0) {
6819
        virReportSystemError(-rc, "%s",
6820 6821 6822 6823 6824
                             _("unable to get cpu shares tunable"));
        goto cleanup;
    }
    params[0].value.ul = val;
    params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
C
Chris Lalancette 已提交
6825
    if (virStrcpyStatic(params[0].field, "cpu_shares") == NULL) {
6826 6827
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Field cpu_shares too long for destination"));
C
Chris Lalancette 已提交
6828 6829
        goto cleanup;
    }
6830 6831 6832 6833 6834 6835 6836

    ret = 0;

cleanup:
    virCgroupFree(&group);
    if (vm)
        virDomainObjUnlock(vm);
6837
    qemuDriverUnlock(driver);
6838 6839 6840 6841
    return ret;
}


6842 6843 6844 6845 6846 6847 6848 6849 6850
/* 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)
{
6851
    struct qemud_driver *driver = dom->conn->privateData;
6852
    int i, ret = -1;
6853
    virDomainObjPtr vm;
6854
    virDomainDiskDefPtr disk = NULL;
6855

6856
    qemuDriverLock(driver);
6857
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6858
    qemuDriverUnlock(driver);
6859
    if (!vm) {
6860 6861
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
6862 6863
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6864
        goto cleanup;
6865
    }
6866 6867 6868 6869

    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
6870
    if (!virDomainObjIsActive (vm)) {
6871 6872
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
6873
        goto endjob;
6874 6875
    }

6876 6877 6878 6879 6880 6881 6882 6883
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (STREQ(path, vm->def->disks[i]->dst)) {
            disk = vm->def->disks[i];
            break;
        }
    }

    if (!disk) {
6884 6885
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("invalid path: %s"), path);
6886
        goto endjob;
6887 6888
    }

6889
    if (!disk->info.alias) {
6890 6891
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("missing disk device alias name for %s"), disk->dst);
6892
        goto endjob;
6893
    }
6894

6895
    qemuDomainObjPrivatePtr priv = vm->privateData;
6896 6897
    qemuDomainObjEnterMonitor(vm);
    ret = qemuMonitorGetBlockStatsInfo(priv->mon,
6898
                                       disk->info.alias,
6899 6900 6901 6902 6903 6904
                                       &stats->rd_req,
                                       &stats->rd_bytes,
                                       &stats->wr_req,
                                       &stats->wr_bytes,
                                       &stats->errs);
    qemuDomainObjExitMonitor(vm);
6905

6906
endjob:
6907 6908
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
6909

6910
cleanup:
6911 6912
    if (vm)
        virDomainObjUnlock(vm);
6913
    return ret;
6914 6915
}

6916
#ifdef __linux__
6917 6918 6919 6920 6921
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path,
                           struct _virDomainInterfaceStats *stats)
{
6922 6923
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
6924
    int i;
6925
    int ret = -1;
6926

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

6931
    if (!vm) {
6932 6933
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
6934 6935
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6936
        goto cleanup;
6937 6938
    }

D
Daniel P. Berrange 已提交
6939
    if (!virDomainObjIsActive(vm)) {
6940 6941
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
6942
        goto cleanup;
6943 6944 6945
    }

    /* Check the path is one of the domain's network interfaces. */
6946 6947
    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (vm->def->nets[i]->ifname &&
6948 6949 6950 6951
            STREQ (vm->def->nets[i]->ifname, path)) {
            ret = 0;
            break;
        }
6952 6953
    }

6954
    if (ret == 0)
6955
        ret = linuxDomainInterfaceStats(path, stats);
6956
    else
6957 6958
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("invalid path, '%s' is not a known interface"), path);
6959

6960
cleanup:
6961 6962
    if (vm)
        virDomainObjUnlock(vm);
6963 6964
    return ret;
}
6965
#else
6966 6967 6968 6969
static int
qemudDomainInterfaceStats (virDomainPtr dom,
                           const char *path ATTRIBUTE_UNUSED,
                           struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
6970 6971
    qemuReportError(VIR_ERR_NO_SUPPORT,
                    "%s", __FUNCTION__);
6972 6973
    return -1;
}
6974
#endif
6975

6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991
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);
6992 6993
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
6994 6995 6996 6997 6998 6999 7000 7001 7002
        goto cleanup;
    }

    if (virDomainObjIsActive(vm)) {
        qemuDomainObjPrivatePtr priv = vm->privateData;
        qemuDomainObjEnterMonitor(vm);
        ret = qemuMonitorTextGetMemoryStats(priv->mon, stats, nr_stats);
        qemuDomainObjExitMonitor(vm);
    } else {
7003 7004
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
7005 7006 7007 7008 7009 7010 7011 7012
    }

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

7013 7014 7015 7016 7017 7018 7019
static int
qemudDomainBlockPeek (virDomainPtr dom,
                      const char *path,
                      unsigned long long offset, size_t size,
                      void *buffer,
                      unsigned int flags ATTRIBUTE_UNUSED)
{
7020 7021 7022
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int fd = -1, ret = -1, i;
7023

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

7028
    if (!vm) {
7029 7030
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7031 7032
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7033
        goto cleanup;
7034 7035 7036
    }

    if (!path || path[0] == '\0') {
7037 7038
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("NULL or empty path"));
7039
        goto cleanup;
7040 7041 7042
    }

    /* Check the path belongs to this domain. */
7043 7044
    for (i = 0 ; i < vm->def->ndisks ; i++) {
        if (vm->def->disks[i]->src != NULL &&
7045 7046 7047 7048
            STREQ (vm->def->disks[i]->src, path)) {
            ret = 0;
            break;
        }
7049 7050
    }

7051 7052 7053 7054 7055
    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) {
7056 7057
            virReportSystemError(errno,
                                 _("%s: failed to open"), path);
7058 7059
            goto cleanup;
        }
7060

7061 7062 7063 7064 7065 7066
        /* 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) {
7067 7068
            virReportSystemError(errno,
                                 _("%s: failed to seek or read"), path);
7069 7070 7071 7072 7073
            goto cleanup;
        }

        ret = 0;
    } else {
7074 7075
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("invalid path"));
7076 7077
    }

7078 7079 7080
cleanup:
    if (fd >= 0)
        close (fd);
7081 7082
    if (vm)
        virDomainObjUnlock(vm);
7083 7084 7085
    return ret;
}

R
Richard W.M. Jones 已提交
7086 7087 7088 7089 7090 7091
static int
qemudDomainMemoryPeek (virDomainPtr dom,
                       unsigned long long offset, size_t size,
                       void *buffer,
                       unsigned int flags)
{
7092 7093
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
7094
    char *tmp = NULL;
R
Richard W.M. Jones 已提交
7095 7096
    int fd = -1, ret = -1;

7097
    qemuDriverLock(driver);
7098
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7099
    qemuDriverUnlock(driver);
R
Richard W.M. Jones 已提交
7100 7101

    if (!vm) {
7102 7103
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
7104 7105
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
7106 7107 7108
        goto cleanup;
    }

7109
    if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
7110 7111
        qemuReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
7112
        goto cleanup;
R
Richard W.M. Jones 已提交
7113 7114
    }

7115 7116 7117
    if (qemuDomainObjBeginJob(vm) < 0)
        goto cleanup;

D
Daniel P. Berrange 已提交
7118
    if (!virDomainObjIsActive(vm)) {
7119 7120
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
7121
        goto endjob;
R
Richard W.M. Jones 已提交
7122 7123
    }

7124
    if (virAsprintf(&tmp, driver->cacheDir,  "/qemu.mem.XXXXXX") < 0) {
7125
        virReportOOMError();
7126
        goto endjob;
7127 7128
    }

R
Richard W.M. Jones 已提交
7129 7130
    /* Create a temporary filename. */
    if ((fd = mkstemp (tmp)) == -1) {
7131 7132
        virReportSystemError(errno,
                             _("mkstemp(\"%s\") failed"), tmp);
7133
        goto endjob;
R
Richard W.M. Jones 已提交
7134 7135
    }

7136
    qemuDomainObjPrivatePtr priv = vm->privateData;
7137
    qemuDomainObjEnterMonitor(vm);
7138
    if (flags == VIR_MEMORY_VIRTUAL) {
7139 7140
        if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
            qemuDomainObjExitMonitor(vm);
7141
            goto endjob;
7142
        }
7143
    } else {
7144 7145
        if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
            qemuDomainObjExitMonitor(vm);
7146
            goto endjob;
7147
        }
R
Richard W.M. Jones 已提交
7148
    }
7149
    qemuDomainObjExitMonitor(vm);
R
Richard W.M. Jones 已提交
7150 7151 7152

    /* Read the memory file into buffer. */
    if (saferead (fd, buffer, size) == (ssize_t) -1) {
7153 7154 7155
        virReportSystemError(errno,
                             _("failed to read temporary file "
                               "created with template %s"), tmp);
7156
        goto endjob;
R
Richard W.M. Jones 已提交
7157 7158 7159
    }

    ret = 0;
7160

7161
endjob:
7162 7163
    if (qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
7164

7165
cleanup:
7166
    VIR_FREE(tmp);
R
Richard W.M. Jones 已提交
7167 7168
    if (fd >= 0) close (fd);
    unlink (tmp);
7169 7170
    if (vm)
        virDomainObjUnlock(vm);
R
Richard W.M. Jones 已提交
7171 7172 7173
    return ret;
}

7174

7175 7176
static int
qemudDomainEventRegister (virConnectPtr conn,
7177
                          virConnectDomainEventCallback callback,
7178 7179
                          void *opaque,
                          virFreeCallback freecb)
7180
{
7181 7182 7183
    struct qemud_driver *driver = conn->privateData;
    int ret;

7184
    qemuDriverLock(driver);
7185 7186
    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                        callback, opaque, freecb);
7187
    qemuDriverUnlock(driver);
7188

7189
    return ret;
7190 7191 7192 7193
}

static int
qemudDomainEventDeregister (virConnectPtr conn,
7194
                            virConnectDomainEventCallback callback)
7195
{
7196 7197 7198
    struct qemud_driver *driver = conn->privateData;
    int ret;

7199
    qemuDriverLock(driver);
7200 7201 7202 7203 7204 7205
    if (driver->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                               callback);
7206
    qemuDriverUnlock(driver);
7207

7208
    return ret;
7209 7210
}

7211 7212 7213 7214 7215
static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                        virDomainEventPtr event,
                                        virConnectDomainEventCallback cb,
                                        void *cbopaque,
                                        void *opaque)
7216
{
7217
    struct qemud_driver *driver = opaque;
7218

7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262
    /* 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);
7263 7264
}

D
Daniel Veillard 已提交
7265 7266
/* Migration support. */

C
Chris Lalancette 已提交
7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285
/* 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) {
7286 7287
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
7288 7289 7290 7291 7292
        return -1;
    }

    qemuDriverLock(driver);
    if (qemust->watch == 0) {
7293 7294
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream does not have a callback registered"));
C
Chris Lalancette 已提交
7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322
        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) {
7323 7324
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
7325 7326 7327 7328 7329
        return -1;
    }

    qemuDriverLock(driver);
    if (qemust->watch == 0) {
7330 7331
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream does not have a callback registered"));
C
Chris Lalancette 已提交
7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388
        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) {
7389 7390
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
7391 7392 7393 7394 7395
        return -1;
    }

    qemuDriverLock(driver);
    if (qemust->watch != 0) {
7396 7397
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream already has a callback registered"));
C
Chris Lalancette 已提交
7398 7399 7400 7401 7402 7403 7404 7405
        goto cleanup;
    }

    if ((qemust->watch = virEventAddHandle(qemust->fd,
                                           events,
                                           qemuStreamMigEvent,
                                           st,
                                           NULL)) < 0) {
7406 7407
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("cannot register file watch on stream"));
C
Chris Lalancette 已提交
7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439
        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;

7440
    if (VIR_ALLOC(qemust) < 0) {
7441
        virReportOOMError();
C
Chris Lalancette 已提交
7442
        return NULL;
7443
    }
C
Chris Lalancette 已提交
7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504

    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) {
7505 7506
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("stream is not open"));
C
Chris Lalancette 已提交
7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520
        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;
7521
            virReportSystemError(errno, "%s",
C
Chris Lalancette 已提交
7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559
                                 _("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;
7560
    unsigned long long qemuCmdFlags;
C
Chris Lalancette 已提交
7561 7562 7563 7564
    struct qemuStreamMigFile *qemust = NULL;

    qemuDriverLock(driver);
    if (!dom_xml) {
7565 7566
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no domain XML passed"));
C
Chris Lalancette 已提交
7567 7568 7569
        goto cleanup;
    }
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
7570
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
C
Chris Lalancette 已提交
7571 7572 7573 7574
                         "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
        goto cleanup;
    }
    if (st == NULL) {
7575 7576
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("tunnelled migration requested but NULL stream passed"));
C
Chris Lalancette 已提交
7577 7578 7579 7580
        goto cleanup;
    }

    /* Parse the domain XML. */
7581
    if (!(def = virDomainDefParseString(driver->caps, dom_xml,
C
Chris Lalancette 已提交
7582
                                        VIR_DOMAIN_XML_INACTIVE))) {
7583 7584
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to parse XML"));
C
Chris Lalancette 已提交
7585 7586 7587 7588
        goto cleanup;
    }

    /* Target domain name, maybe renamed. */
7589 7590 7591 7592 7593 7594
    if (dname) {
        VIR_FREE(def->name);
        def->name = strdup(dname);
        if (def->name == NULL)
            goto cleanup;
    }
C
Chris Lalancette 已提交
7595

7596 7597
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
C
Chris Lalancette 已提交
7598

7599
    if (!(vm = virDomainAssignDef(driver->caps,
C
Chris Lalancette 已提交
7600 7601
                                  &driver->domains,
                                  def))) {
7602 7603
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to assign new VM"));
C
Chris Lalancette 已提交
7604 7605 7606 7607
        goto cleanup;
    }
    def = NULL;

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

C
Chris Lalancette 已提交
7611 7612 7613 7614 7615
    /* 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) {
7616
        virReportOOMError();
7617
        goto endjob;
C
Chris Lalancette 已提交
7618 7619 7620 7621 7622
    }
    unlink(unixfile);

    /* check that this qemu version supports the interactive exec */
    if (qemudExtractVersionInfo(vm->def->emulator, NULL, &qemuCmdFlags) < 0) {
7623 7624 7625
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot determine QEMU argv syntax %s"),
                        vm->def->emulator);
7626
        goto endjob;
C
Chris Lalancette 已提交
7627 7628 7629 7630 7631 7632
    }
    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 {
7633 7634
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("Destination qemu is too old to support tunnelled migration"));
7635
        goto endjob;
C
Chris Lalancette 已提交
7636 7637
    }
    if (internalret < 0) {
7638
        virReportOOMError();
7639
        goto endjob;
C
Chris Lalancette 已提交
7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653
    }
    /* 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;
        }
7654
        goto endjob;
C
Chris Lalancette 已提交
7655 7656 7657 7658
    }

    qemust = qemuStreamMigOpen(st, unixfile);
    if (qemust == NULL) {
7659
        qemudShutdownVMDaemon(driver, vm);
7660
        if (!vm->persistent) {
7661 7662
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains, vm);
7663 7664
            vm = NULL;
        }
7665
        virReportSystemError(errno,
C
Chris Lalancette 已提交
7666 7667
                             _("cannot open unix socket '%s' for tunnelled migration"),
                             unixfile);
7668
        goto endjob;
C
Chris Lalancette 已提交
7669 7670 7671 7672 7673 7674 7675 7676 7677 7678
    }

    st->driver = &qemuStreamMigDrv;
    st->privateData = qemust;

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_MIGRATED);
    ret = 0;

7679
endjob:
7680 7681 7682
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
7683

C
Chris Lalancette 已提交
7684 7685
cleanup:
    virDomainDefFree(def);
7686 7687
    if (unixfile)
        unlink(unixfile);
C
Chris Lalancette 已提交
7688 7689 7690 7691 7692 7693 7694 7695 7696
    VIR_FREE(unixfile);
    if (vm)
        virDomainObjUnlock(vm);
    if (event)
        qemuDomainEventQueue(driver, event);
    qemuDriverUnlock(driver);
    return ret;
}

D
Daniel Veillard 已提交
7697 7698 7699 7700
/* Prepare is the first step, and it runs on the destination host.
 *
 * This starts an empty VM listening on a TCP port.
 */
7701
static int ATTRIBUTE_NONNULL (5)
D
Daniel Veillard 已提交
7702 7703 7704 7705 7706
qemudDomainMigratePrepare2 (virConnectPtr dconn,
                            char **cookie ATTRIBUTE_UNUSED,
                            int *cookielen ATTRIBUTE_UNUSED,
                            const char *uri_in,
                            char **uri_out,
C
Chris Lalancette 已提交
7707
                            unsigned long flags,
D
Daniel Veillard 已提交
7708 7709 7710 7711 7712
                            const char *dname,
                            unsigned long resource ATTRIBUTE_UNUSED,
                            const char *dom_xml)
{
    static int port = 0;
7713 7714
    struct qemud_driver *driver = dconn->privateData;
    virDomainDefPtr def = NULL;
D
Daniel Veillard 已提交
7715 7716
    virDomainObjPtr vm = NULL;
    int this_port;
7717
    char *hostname;
D
Daniel Veillard 已提交
7718 7719
    char migrateFrom [64];
    const char *p;
7720
    virDomainEventPtr event = NULL;
7721
    int ret = -1;
7722
    int internalret;
7723 7724

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

7726
    qemuDriverLock(driver);
C
Chris Lalancette 已提交
7727 7728 7729 7730
    if (flags & VIR_MIGRATE_TUNNELLED) {
        /* this is a logical error; we never should have gotten here with
         * VIR_MIGRATE_TUNNELLED set
         */
7731 7732
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Tunnelled migration requested but invalid RPC method called"));
C
Chris Lalancette 已提交
7733 7734 7735
        goto cleanup;
    }

D
Daniel Veillard 已提交
7736
    if (!dom_xml) {
7737 7738
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no domain XML passed"));
7739
        goto cleanup;
D
Daniel Veillard 已提交
7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756
    }

    /* 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 */
7757
        if ((hostname = virGetHostname(dconn)) == NULL)
7758
            goto cleanup;
D
Daniel Veillard 已提交
7759

7760 7761 7762 7763 7764
        /* 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 已提交
7765
        /* Caller frees */
7766 7767 7768
        internalret = virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port);
        VIR_FREE(hostname);
        if (internalret < 0) {
7769
            virReportOOMError();
7770
            goto cleanup;
D
Daniel Veillard 已提交
7771 7772 7773 7774 7775 7776
        }
    } 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.
         */
7777
        if (!STRPREFIX (uri_in, "tcp:")) {
7778 7779
            qemuReportError (VIR_ERR_INVALID_ARG,
                             "%s", _("only tcp URIs are supported for KVM/QEMU migrations"));
7780
            goto cleanup;
D
Daniel Veillard 已提交
7781 7782 7783 7784
        }

        /* Get the port number. */
        p = strrchr (uri_in, ':');
7785 7786 7787 7788 7789 7790 7791 7792
        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) {
7793
                virReportOOMError();
7794 7795 7796 7797 7798 7799 7800
                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)) {
7801 7802
                qemuReportError(VIR_ERR_INVALID_ARG,
                                "%s", _("URI ended with incorrect ':port'"));
7803 7804
                goto cleanup;
            }
D
Daniel Veillard 已提交
7805 7806 7807
        }
    }

7808
    if (*uri_out)
7809 7810
        VIR_DEBUG("Generated uri_out=%s", *uri_out);

D
Daniel Veillard 已提交
7811
    /* Parse the domain XML. */
7812
    if (!(def = virDomainDefParseString(driver->caps, dom_xml,
7813
                                        VIR_DOMAIN_XML_INACTIVE))) {
7814 7815
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to parse XML"));
7816
        goto cleanup;
D
Daniel Veillard 已提交
7817 7818 7819
    }

    /* Target domain name, maybe renamed. */
7820 7821 7822 7823 7824 7825
    if (dname) {
        VIR_FREE(def->name);
        def->name = strdup(dname);
        if (def->name == NULL)
            goto cleanup;
    }
D
Daniel Veillard 已提交
7826

7827 7828
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
        goto cleanup;
D
Daniel Veillard 已提交
7829

7830
    if (!(vm = virDomainAssignDef(driver->caps,
D
Daniel Veillard 已提交
7831 7832
                                  &driver->domains,
                                  def))) {
7833 7834
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to assign new VM"));
7835
        goto cleanup;
D
Daniel Veillard 已提交
7836
    }
7837
    def = NULL;
D
Daniel Veillard 已提交
7838

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

D
Daniel Veillard 已提交
7842 7843 7844 7845 7846 7847 7848
    /* 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);
7849
    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
7850 7851 7852
        /* Note that we don't set an error here because qemudStartVMDaemon
         * should have already done that.
         */
7853
        if (!vm->persistent) {
7854 7855
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains, vm);
7856 7857
            vm = NULL;
        }
7858
        goto endjob;
D
Daniel Veillard 已提交
7859
    }
7860 7861 7862 7863

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

7866
endjob:
7867 7868 7869
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
7870

7871 7872 7873 7874 7875
cleanup:
    virDomainDefFree(def);
    if (ret != 0) {
        VIR_FREE(*uri_out);
    }
7876 7877
    if (vm)
        virDomainObjUnlock(vm);
7878 7879
    if (event)
        qemuDomainEventQueue(driver, event);
7880
    qemuDriverUnlock(driver);
7881
    return ret;
C
Chris Lalancette 已提交
7882 7883 7884

}

7885 7886 7887 7888

/* Perform migration using QEMU's native TCP migrate support,
 * not encrypted obviously
 */
7889
static int doNativeMigrate(struct qemud_driver *driver,
7890 7891 7892 7893 7894 7895 7896
                           virDomainObjPtr vm,
                           const char *uri,
                           unsigned long flags ATTRIBUTE_UNUSED,
                           const char *dname ATTRIBUTE_UNUSED,
                           unsigned long resource)
{
    int ret = -1;
7897
    xmlURIPtr uribits = NULL;
7898 7899
    int status;
    unsigned long long transferred, remaining, total;
7900
    qemuDomainObjPrivatePtr priv = vm->privateData;
7901 7902 7903 7904 7905 7906

    /* 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) {
7907
            virReportOOMError();
7908 7909 7910 7911 7912 7913 7914 7915
            goto cleanup;
        }
        uribits = xmlParseURI(tmpuri);
        VIR_FREE(tmpuri);
    } else {
        uribits = xmlParseURI(uri);
    }
    if (!uribits) {
7916 7917
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot parse URI %s"), uri);
7918 7919 7920
        goto cleanup;
    }

7921
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
7922
    if (resource > 0 &&
7923
        qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) {
7924
        qemuDomainObjExitMonitorWithDriver(driver, vm);
7925
        goto cleanup;
7926
    }
7927

7928
    if (qemuMonitorMigrateToHost(priv->mon, 0, uribits->server, uribits->port) < 0) {
7929
        qemuDomainObjExitMonitorWithDriver(driver, vm);
7930
        goto cleanup;
7931
    }
7932 7933 7934 7935

    /* it is also possible that the migrate didn't fail initially, but
     * rather failed later on.  Check the output of "info migrate"
     */
7936 7937
    if (qemuMonitorGetMigrationStatus(priv->mon,
                                      &status,
7938 7939 7940
                                      &transferred,
                                      &remaining,
                                      &total) < 0) {
7941
        qemuDomainObjExitMonitorWithDriver(driver, vm);
7942 7943
        goto cleanup;
    }
7944
    qemuDomainObjExitMonitorWithDriver(driver, vm);
7945 7946

    if (status != QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) {
7947 7948
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("migrate did not successfully complete"));
7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959
        goto cleanup;
    }

    ret = 0;

cleanup:
    xmlFreeURI(uribits);
    return ret;
}


7960
static int doTunnelSendAll(virStreamPtr st,
7961 7962 7963 7964 7965 7966 7967 7968 7969 7970
                           int sock)
{
    char buffer[65536];
    int nbytes = sizeof(buffer);

    /* XXX should honour the 'resource' parameter here */
    for (;;) {
        nbytes = saferead(sock, buffer, nbytes);
        if (nbytes < 0) {
            virStreamAbort(st);
7971
            virReportSystemError(errno, "%s",
7972 7973 7974 7975 7976 7977 7978 7979
                                 _("tunnelled migration failed to read from qemu"));
            return -1;
        }
        else if (nbytes == 0)
            /* EOF; get out of here */
            break;

        if (virStreamSend(st, buffer, nbytes) < 0) {
7980 7981
            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                            _("Failed to write migration data to remote libvirtd"));
7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992
            return -1;
        }
    }

    if (virStreamFinish(st) < 0)
        /* virStreamFinish set the error for us */
        return -1;

    return 0;
}

C
Chris Lalancette 已提交
7993
static int doTunnelMigrate(virDomainPtr dom,
7994
                           struct qemud_driver *driver,
7995
                           virConnectPtr dconn,
C
Chris Lalancette 已提交
7996
                           virDomainObjPtr vm,
7997
                           const char *dom_xml,
C
Chris Lalancette 已提交
7998 7999 8000 8001 8002
                           const char *uri,
                           unsigned long flags,
                           const char *dname,
                           unsigned long resource)
{
8003
    qemuDomainObjPrivatePtr priv = vm->privateData;
8004 8005
    int client_sock = -1;
    int qemu_sock = -1;
C
Chris Lalancette 已提交
8006 8007
    struct sockaddr_un sa_qemu, sa_client;
    socklen_t addrlen;
8008
    virDomainPtr ddomain = NULL;
C
Chris Lalancette 已提交
8009
    int retval = -1;
8010
    virStreamPtr st = NULL;
C
Chris Lalancette 已提交
8011 8012
    char *unixfile = NULL;
    int internalret;
8013
    unsigned long long qemuCmdFlags;
C
Chris Lalancette 已提交
8014 8015 8016
    int status;
    unsigned long long transferred, remaining, total;

8017 8018 8019 8020 8021 8022 8023 8024
    /*
     * 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 已提交
8025 8026
     */

8027

8028
    /* Stage 1. setup local support infrastructure */
C
Chris Lalancette 已提交
8029 8030 8031

    if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.src.%s",
                    driver->stateDir, vm->def->name) < 0) {
8032
        virReportOOMError();
8033
        goto cleanup;
C
Chris Lalancette 已提交
8034 8035 8036 8037
    }

    qemu_sock = socket(AF_UNIX, SOCK_STREAM, 0);
    if (qemu_sock < 0) {
8038
        virReportSystemError(errno, "%s",
C
Chris Lalancette 已提交
8039
                             _("cannot open tunnelled migration socket"));
8040
        goto cleanup;
C
Chris Lalancette 已提交
8041 8042 8043 8044 8045
    }
    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) {
8046 8047 8048
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Unix socket '%s' too big for destination"),
                        unixfile);
8049
        goto cleanup;
C
Chris Lalancette 已提交
8050 8051 8052
    }
    unlink(unixfile);
    if (bind(qemu_sock, (struct sockaddr *)&sa_qemu, sizeof(sa_qemu)) < 0) {
8053
        virReportSystemError(errno,
C
Chris Lalancette 已提交
8054 8055
                             _("Cannot bind to unix socket '%s' for tunnelled migration"),
                             unixfile);
8056
        goto cleanup;
C
Chris Lalancette 已提交
8057 8058
    }
    if (listen(qemu_sock, 1) < 0) {
8059
        virReportSystemError(errno,
C
Chris Lalancette 已提交
8060 8061
                             _("Cannot listen on unix socket '%s' for tunnelled migration"),
                             unixfile);
8062
        goto cleanup;
C
Chris Lalancette 已提交
8063 8064 8065 8066
    }

    /* check that this qemu version supports the unix migration */
    if (qemudExtractVersionInfo(vm->def->emulator, NULL, &qemuCmdFlags) < 0) {
8067 8068 8069
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Cannot extract Qemu version from '%s'"),
                        vm->def->emulator);
8070 8071 8072 8073 8074
        goto cleanup;
    }

    if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX) &&
        !(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)) {
8075 8076
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("Source qemu is too old to support tunnelled migration"));
8077
        goto cleanup;
C
Chris Lalancette 已提交
8078
    }
8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099


    /* 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 */
8100
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
C
Chris Lalancette 已提交
8101
    if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX)
8102
        internalret = qemuMonitorMigrateToUnix(priv->mon, 1, unixfile);
C
Chris Lalancette 已提交
8103 8104
    else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) {
        const char *args[] = { "nc", "-U", unixfile, NULL };
8105
        internalret = qemuMonitorMigrateToCommand(priv->mon, 1, args, "/dev/null");
8106 8107
    } else {
        internalret = -1;
C
Chris Lalancette 已提交
8108
    }
8109
    qemuDomainObjExitMonitorWithDriver(driver, vm);
C
Chris Lalancette 已提交
8110
    if (internalret < 0) {
8111 8112
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("tunnelled migration monitor command failed"));
8113
        goto finish;
C
Chris Lalancette 已提交
8114 8115
    }

8116 8117 8118
    /* From this point onwards we *must* call cancel to abort the
     * migration on source if anything goes wrong */

C
Chris Lalancette 已提交
8119 8120 8121
    /* it is also possible that the migrate didn't fail initially, but
     * rather failed later on.  Check the output of "info migrate"
     */
8122
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
8123 8124
    if (qemuMonitorGetMigrationStatus(priv->mon,
                                      &status,
C
Chris Lalancette 已提交
8125 8126 8127
                                      &transferred,
                                      &remaining,
                                      &total) < 0) {
8128
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8129
        goto cancel;
C
Chris Lalancette 已提交
8130
    }
8131
    qemuDomainObjExitMonitorWithDriver(driver, vm);
C
Chris Lalancette 已提交
8132 8133

    if (status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) {
8134 8135
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s",_("migrate failed"));
8136
        goto cancel;
C
Chris Lalancette 已提交
8137 8138 8139 8140 8141 8142
    }

    addrlen = sizeof(sa_client);
    while ((client_sock = accept(qemu_sock, (struct sockaddr *)&sa_client, &addrlen)) < 0) {
        if (errno == EAGAIN || errno == EINTR)
            continue;
8143
        virReportSystemError(errno, "%s",
C
Chris Lalancette 已提交
8144
                             _("tunnelled migration failed to accept from qemu"));
8145
        goto cancel;
C
Chris Lalancette 已提交
8146 8147
    }

8148
    retval = doTunnelSendAll(st, client_sock);
8149

8150
cancel:
8151
    if (retval != 0) {
8152
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
8153
        qemuMonitorMigrateCancel(priv->mon);
8154
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8155
    }
C
Chris Lalancette 已提交
8156

8157
finish:
C
Chris Lalancette 已提交
8158 8159 8160
    dname = dname ? dname : dom->name;
    ddomain = dconn->driver->domainMigrateFinish2
        (dconn, dname, NULL, 0, uri, flags, retval);
8161 8162 8163 8164 8165 8166 8167

cleanup:
    if (client_sock != -1)
        close(client_sock);
    if (qemu_sock != -1)
        close(qemu_sock);

C
Chris Lalancette 已提交
8168 8169 8170
    if (ddomain)
        virUnrefDomain(ddomain);

8171 8172 8173 8174
    if (unixfile) {
        unlink(unixfile);
        VIR_FREE(unixfile);
    }
C
Chris Lalancette 已提交
8175

8176 8177 8178
    if (st)
        /* don't call virStreamFree(), because that resets any pending errors */
        virUnrefStream(st);
8179 8180 8181 8182
    return retval;
}


8183 8184 8185 8186
/* 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,
8187
                              struct qemud_driver *driver,
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
                              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) {
8213 8214
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("domainMigratePrepare2 did not set uri"));
8215
        goto cleanup;
8216 8217
    }

8218
    if (doNativeMigrate(driver, vm, uri_out, flags, dname, resource) < 0)
8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235
        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;
}


8236
static int doPeer2PeerMigrate(virDomainPtr dom,
8237
                              struct qemud_driver *driver,
8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253
                              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) {
8254 8255
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        _("Failed to connect to remote libvirt URI %s"), uri);
8256 8257 8258
        return -1;
    }
    if (!VIR_DRV_SUPPORTS_FEATURE(dconn->driver, dconn,
8259
                                  VIR_DRV_FEATURE_MIGRATION_P2P)) {
8260 8261
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                        _("Destination libvirt does not support peer-to-peer migration protocol"));
8262 8263 8264
        goto cleanup;
    }

8265
    dom_xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
8266
    if (!dom_xml) {
8267 8268
        qemuReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to get domain xml"));
8269 8270 8271
        goto cleanup;
    }

8272
    if (flags & VIR_MIGRATE_TUNNELLED)
8273
        ret = doTunnelMigrate(dom, driver, dconn, vm, dom_xml, uri, flags, dname, resource);
8274
    else
8275
        ret = doNonTunnelMigrate(dom, driver, dconn, vm, dom_xml, uri, flags, dname, resource);
8276 8277 8278

cleanup:
    VIR_FREE(dom_xml);
C
Chris Lalancette 已提交
8279 8280 8281
    /* don't call virConnectClose(), because that resets any pending errors */
    virUnrefConnect(dconn);

8282
    return ret;
D
Daniel Veillard 已提交
8283 8284
}

8285

D
Daniel Veillard 已提交
8286 8287 8288 8289 8290 8291
/* 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,
8292
                           unsigned long flags,
8293
                           const char *dname,
D
Daniel Veillard 已提交
8294 8295
                           unsigned long resource)
{
8296 8297
    struct qemud_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
8298
    virDomainEventPtr event = NULL;
8299
    int ret = -1;
8300
    int paused = 0;
D
Daniel Veillard 已提交
8301

8302
    qemuDriverLock(driver);
8303
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
D
Daniel Veillard 已提交
8304
    if (!vm) {
8305 8306
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(dom->uuid, uuidstr);
8307 8308
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching uuid '%s'"), uuidstr);
8309
        goto cleanup;
D
Daniel Veillard 已提交
8310 8311
    }

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

D
Daniel P. Berrange 已提交
8315
    if (!virDomainObjIsActive(vm)) {
8316 8317
        qemuReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("domain is not running"));
8318
        goto endjob;
D
Daniel Veillard 已提交
8319 8320
    }

8321
    if (!(flags & VIR_MIGRATE_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
8322
        qemuDomainObjPrivatePtr priv = vm->privateData;
8323
        /* Pause domain for non-live migration */
8324
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
8325
        if (qemuMonitorStopCPUs(priv->mon) < 0) {
8326 8327
            qemuDomainObjExitMonitorWithDriver(driver, vm);
            goto endjob;
8328
        }
8329
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8330
        paused = 1;
8331

8332
        vm->state = VIR_DOMAIN_PAUSED;
8333 8334 8335 8336 8337 8338
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
        if (event)
            qemuDomainEventQueue(driver, event);
        event = NULL;
8339 8340
    }

8341
    if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
8342
        if (doPeer2PeerMigrate(dom, driver, vm, uri, flags, dname, resource) < 0)
8343
            /* doPeer2PeerMigrate already set the error, so just get out */
8344
            goto endjob;
8345
    } else {
8346
        if (doNativeMigrate(driver, vm, uri, flags, dname, resource) < 0)
8347
            goto endjob;
8348 8349
    }

D
Daniel Veillard 已提交
8350
    /* Clean up the source domain. */
8351
    qemudShutdownVMDaemon(driver, vm);
8352
    paused = 0;
8353 8354 8355 8356

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
C
Chris Lalancette 已提交
8357
    if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
8358
        virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
8359 8360
        if (qemuDomainObjEndJob(vm) > 0)
            virDomainRemoveInactive(&driver->domains, vm);
8361 8362
        vm = NULL;
    }
8363
    ret = 0;
D
Daniel Veillard 已提交
8364

8365
endjob:
8366
    if (paused) {
8367
        qemuDomainObjPrivatePtr priv = vm->privateData;
8368
        /* we got here through some sort of failure; start the domain again */
8369
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
8370
        if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) {
8371 8372 8373 8374
            /* 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
             */
8375
            VIR_ERROR(_("Failed to resume guest %s after failure"),
8376
                      vm->def->name);
8377
        }
8378
        qemuDomainObjExitMonitorWithDriver(driver, vm);
8379

8380
        vm->state = VIR_DOMAIN_RUNNING;
8381 8382 8383 8384
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
    }
8385 8386 8387
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
8388

8389
cleanup:
8390 8391
    if (vm)
        virDomainObjUnlock(vm);
8392 8393
    if (event)
        qemuDomainEventQueue(driver, event);
8394
    qemuDriverUnlock(driver);
8395
    return ret;
D
Daniel Veillard 已提交
8396 8397 8398 8399 8400 8401 8402 8403 8404
}

/* 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 已提交
8405
                           unsigned long flags,
D
Daniel Veillard 已提交
8406 8407
                           int retcode)
{
8408 8409 8410
    struct qemud_driver *driver = dconn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
8411
    virDomainEventPtr event = NULL;
8412
    virErrorPtr orig_err;
C
Chris Lalancette 已提交
8413
    int newVM = 1;
D
Daniel Veillard 已提交
8414

8415 8416 8417
    /* Migration failed. Save the current error so nothing squashes it */
    orig_err = virSaveLastError();

8418
    qemuDriverLock(driver);
8419
    vm = virDomainFindByName(&driver->domains, dname);
D
Daniel Veillard 已提交
8420
    if (!vm) {
8421 8422
        qemuReportError(VIR_ERR_NO_DOMAIN,
                        _("no domain with matching name '%s'"), dname);
8423
        goto cleanup;
D
Daniel Veillard 已提交
8424 8425
    }

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

D
Daniel Veillard 已提交
8429 8430 8431 8432
    /* 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 已提交
8433 8434 8435 8436 8437
        if (flags & VIR_MIGRATE_PERSIST_DEST) {
            if (vm->persistent)
                newVM = 0;
            vm->persistent = 1;

8438
            if (virDomainSaveConfig(driver->configDir, vm->def) < 0) {
C
Chris Lalancette 已提交
8439 8440 8441 8442 8443 8444 8445 8446 8447 8448
                /* 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;
8449
                goto endjob;
C
Chris Lalancette 已提交
8450 8451 8452 8453 8454 8455 8456 8457 8458
            }

            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_DEFINED,
                                             newVM ?
                                             VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                             VIR_DOMAIN_EVENT_DEFINED_UPDATED);
            if (event)
                qemuDomainEventQueue(driver, event);
8459
            event = NULL;
C
Chris Lalancette 已提交
8460 8461

        }
8462
        qemuDomainObjPrivatePtr priv = vm->privateData;
D
Daniel Veillard 已提交
8463
        dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
8464

8465 8466 8467 8468 8469 8470 8471 8472
        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)
8473 8474
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("resume operation failed"));
8475 8476 8477
                qemuDomainObjExitMonitorWithDriver(driver, vm);
                goto endjob;
            }
8478
            qemuDomainObjExitMonitorWithDriver(driver, vm);
8479 8480

            vm->state = VIR_DOMAIN_RUNNING;
8481 8482
        }

8483 8484 8485
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
8486 8487 8488 8489 8490 8491
        if (vm->state == VIR_DOMAIN_PAUSED) {
            qemuDomainEventQueue(driver, event);
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_SUSPENDED,
                                             VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
        }
8492
        virDomainSaveStatus(driver->caps, driver->stateDir, vm);
D
Daniel Veillard 已提交
8493
    } else {
8494
        qemudShutdownVMDaemon(driver, vm);
8495 8496 8497
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
8498
        if (!vm->persistent) {
8499 8500
            if (qemuDomainObjEndJob(vm) > 0)
                virDomainRemoveInactive(&driver->domains, vm);
8501 8502
            vm = NULL;
        }
D
Daniel Veillard 已提交
8503
    }
8504

8505
endjob:
8506 8507 8508
    if (vm &&
        qemuDomainObjEndJob(vm) == 0)
        vm = NULL;
8509

8510
cleanup:
8511 8512 8513 8514
    if (orig_err) {
        virSetError(orig_err);
        virFreeError(orig_err);
    }
8515 8516
    if (vm)
        virDomainObjUnlock(vm);
8517 8518
    if (event)
        qemuDomainEventQueue(driver, event);
8519
    qemuDriverUnlock(driver);
8520
    return dom;
D
Daniel Veillard 已提交
8521 8522
}

8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538
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;

8539
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE);
8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556
    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) {
8557 8558
        qemuReportError(VIR_ERR_INVALID_ARG,
                        _("device %s is not a PCI device"), dev->name);
8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578
        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;

8579
    pci = pciGetDevice(domain, bus, slot, function);
8580 8581 8582
    if (!pci)
        return -1;

8583
    if (pciDettachDevice(pci) < 0)
8584 8585 8586 8587
        goto out;

    ret = 0;
out:
8588
    pciFreeDevice(pci);
8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601
    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;

8602
    pci = pciGetDevice(domain, bus, slot, function);
8603 8604 8605
    if (!pci)
        return -1;

8606
    if (pciReAttachDevice(pci) < 0)
8607 8608 8609 8610
        goto out;

    ret = 0;
out:
8611
    pciFreeDevice(pci);
8612 8613 8614 8615 8616 8617
    return ret;
}

static int
qemudNodeDeviceReset (virNodeDevicePtr dev)
{
8618
    struct qemud_driver *driver = dev->conn->privateData;
8619 8620 8621 8622 8623 8624 8625
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

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

8626
    pci = pciGetDevice(domain, bus, slot, function);
8627 8628 8629
    if (!pci)
        return -1;

8630 8631
    qemuDriverLock(driver);

8632
    if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
8633 8634 8635 8636
        goto out;

    ret = 0;
out:
8637
    qemuDriverUnlock(driver);
8638
    pciFreeDevice(pci);
8639 8640 8641
    return ret;
}

8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652
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) {
8653 8654
        qemuReportError(VIR_ERR_NO_SUPPORT,
                        "%s", _("cannot get host CPU capabilities"));
8655 8656
    }
    else
8657
        ret = cpuCompareXML(driver->caps->host.cpu, xmlDesc);
8658 8659 8660 8661 8662 8663

    qemuDriverUnlock(driver);

    return ret;
}

8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676
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;
}

8677 8678 8679 8680 8681
static virDriver qemuDriver = {
    VIR_DRV_QEMU,
    "QEMU",
    qemudOpen, /* open */
    qemudClose, /* close */
D
Daniel Veillard 已提交
8682
    qemudSupportsFeature, /* supports_feature */
8683 8684
    qemudGetType, /* type */
    qemudGetVersion, /* version */
8685
    NULL, /* libvirtVersion (impl. in libvirt.c) */
8686
    virGetHostname, /* getHostname */
8687
    qemudGetMaxVCPUs, /* getMaxVcpus */
8688
    nodeGetInfo, /* nodeGetInfo */
8689 8690 8691
    qemudGetCapabilities, /* getCapabilities */
    qemudListDomains, /* listDomains */
    qemudNumDomains, /* numOfDomains */
8692
    qemudDomainCreate, /* domainCreateXML */
8693 8694 8695 8696 8697
    qemudDomainLookupByID, /* domainLookupByID */
    qemudDomainLookupByUUID, /* domainLookupByUUID */
    qemudDomainLookupByName, /* domainLookupByName */
    qemudDomainSuspend, /* domainSuspend */
    qemudDomainResume, /* domainResume */
8698
    qemudDomainShutdown, /* domainShutdown */
8699 8700 8701
    NULL, /* domainReboot */
    qemudDomainDestroy, /* domainDestroy */
    qemudDomainGetOSType, /* domainGetOSType */
8702 8703 8704
    qemudDomainGetMaxMemory, /* domainGetMaxMemory */
    qemudDomainSetMaxMemory, /* domainSetMaxMemory */
    qemudDomainSetMemory, /* domainSetMemory */
8705 8706 8707
    qemudDomainGetInfo, /* domainGetInfo */
    qemudDomainSave, /* domainSave */
    qemudDomainRestore, /* domainRestore */
P
Paolo Bonzini 已提交
8708
    qemudDomainCoreDump, /* domainCoreDump */
8709
    qemudDomainSetVcpus, /* domainSetVcpus */
8710 8711
    qemudDomainPinVcpu, /* domainPinVcpu */
    qemudDomainGetVcpus, /* domainGetVcpus */
8712
    qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
8713 8714
    qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */
    qemudNodeGetSecurityModel, /* nodeGetSecurityModel */
8715
    qemudDomainDumpXML, /* domainDumpXML */
8716
    qemuDomainXMLFromNative, /* domainXmlFromNative */
8717
    qemuDomainXMLToNative, /* domainXMLToNative */
8718 8719
    qemudListDefinedDomains, /* listDefinedDomains */
    qemudNumDefinedDomains, /* numOfDefinedDomains */
8720 8721 8722
    qemudDomainStart, /* domainCreate */
    qemudDomainDefine, /* domainDefineXML */
    qemudDomainUndefine, /* domainUndefine */
8723
    qemudDomainAttachDevice, /* domainAttachDevice */
8724
    qemudDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
8725
    qemudDomainDetachDevice, /* domainDetachDevice */
8726
    qemudDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
8727 8728
    qemudDomainGetAutostart, /* domainGetAutostart */
    qemudDomainSetAutostart, /* domainSetAutostart */
8729 8730 8731
    qemuGetSchedulerType, /* domainGetSchedulerType */
    qemuGetSchedulerParameters, /* domainGetSchedulerParameters */
    qemuSetSchedulerParameters, /* domainSetSchedulerParameters */
D
Daniel Veillard 已提交
8732 8733
    NULL, /* domainMigratePrepare (v1) */
    qemudDomainMigratePerform, /* domainMigratePerform */
8734
    NULL, /* domainMigrateFinish */
8735
    qemudDomainBlockStats, /* domainBlockStats */
8736
    qemudDomainInterfaceStats, /* domainInterfaceStats */
8737
    qemudDomainMemoryStats, /* domainMemoryStats */
8738
    qemudDomainBlockPeek, /* domainBlockPeek */
R
Richard W.M. Jones 已提交
8739
    qemudDomainMemoryPeek, /* domainMemoryPeek */
8740 8741
    nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    nodeGetFreeMemory,  /* getFreeMemory */
8742 8743
    qemudDomainEventRegister, /* domainEventRegister */
    qemudDomainEventDeregister, /* domainEventDeregister */
D
Daniel Veillard 已提交
8744 8745
    qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
    qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
8746 8747 8748
    qemudNodeDeviceDettach, /* nodeDeviceDettach */
    qemudNodeDeviceReAttach, /* nodeDeviceReAttach */
    qemudNodeDeviceReset, /* nodeDeviceReset */
C
Chris Lalancette 已提交
8749
    qemudDomainMigratePrepareTunnel, /* domainMigratePrepareTunnel */
8750 8751 8752 8753
    qemuIsEncrypted,
    qemuIsSecure,
    qemuDomainIsActive,
    qemuDomainIsPersistent,
8754
    qemuCPUCompare, /* cpuCompare */
8755
    qemuCPUBaseline, /* cpuBaseline */
8756 8757 8758
};


8759
static virStateDriver qemuStateDriver = {
8760
    .name = "QEMU",
8761 8762 8763 8764
    .initialize = qemudStartup,
    .cleanup = qemudShutdown,
    .reload = qemudReload,
    .active = qemudActive,
8765
};
8766

8767
int qemuRegister(void) {
8768 8769 8770 8771
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}