qemu_driver.c 485.7 KB
Newer Older
D
Daniel P. Berrange 已提交
1
/*
2
 * qemu_driver.c: core driver methods for managing qemu guests
D
Daniel P. Berrange 已提交
3
 *
4
 * Copyright (C) 2006-2013 Red Hat, Inc.
D
Daniel P. Berrange 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
D
Daniel P. Berrange 已提交
20 21 22 23
 *
 * 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 32 33 34 35 36
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
37 38 39 40 41
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
#include <sys/wait.h>
42
#include <sys/ioctl.h>
43
#include <sys/un.h>
44
#include <byteswap.h>
D
Daniel P. Berrange 已提交
45

46

47
#include "qemu_driver.h"
48
#include "qemu_agent.h"
49
#include "qemu_conf.h"
50
#include "qemu_capabilities.h"
51
#include "qemu_command.h"
52
#include "qemu_cgroup.h"
53
#include "qemu_hostdev.h"
54
#include "qemu_hotplug.h"
55
#include "qemu_monitor.h"
56
#include "qemu_bridge_filter.h"
57
#include "qemu_process.h"
58
#include "qemu_migration.h"
59

60
#include "virerror.h"
61
#include "virlog.h"
62
#include "datatypes.h"
63
#include "virbuffer.h"
64
#include "nodeinfo.h"
65
#include "virstatslinux.h"
66
#include "capabilities.h"
67
#include "viralloc.h"
68
#include "viruuid.h"
69
#include "domain_conf.h"
70
#include "domain_audit.h"
71
#include "node_device_conf.h"
72
#include "virpci.h"
73
#include "virusb.h"
74
#include "virprocess.h"
C
Chris Lalancette 已提交
75
#include "libvirt_internal.h"
76
#include "virxml.h"
77
#include "cpu/cpu.h"
78
#include "virsysinfo.h"
79
#include "domain_nwfilter.h"
80
#include "nwfilter_conf.h"
81
#include "virhook.h"
82
#include "virstoragefile.h"
E
Eric Blake 已提交
83
#include "virfile.h"
84
#include "fdstream.h"
85
#include "configmake.h"
86
#include "virthreadpool.h"
87
#include "locking/lock_manager.h"
88
#include "locking/domain_lock.h"
89
#include "virkeycode.h"
90
#include "virnodesuspend.h"
91
#include "virtime.h"
92
#include "virtypedparam.h"
93
#include "virbitmap.h"
94
#include "virstring.h"
95

96 97
#define VIR_FROM_THIS VIR_FROM_QEMU

98 99
#define QEMU_DRIVER_NAME "QEMU"

100 101
#define QEMU_NB_MEM_PARAM  3

102 103
#define QEMU_NB_BLOCK_IO_TUNE_PARAM  6

104 105
#define QEMU_NB_NUMA_PARAM 2

E
Eric Blake 已提交
106
#define QEMU_NB_TOTAL_CPU_STAT_PARAM 3
107
#define QEMU_NB_PER_CPU_STAT_PARAM 2
E
Eric Blake 已提交
108

109 110 111 112 113
#define QEMU_SCHED_MIN_PERIOD              1000LL
#define QEMU_SCHED_MAX_PERIOD           1000000LL
#define QEMU_SCHED_MIN_QUOTA               1000LL
#define QEMU_SCHED_MAX_QUOTA  18446744073709551LL

114 115 116
#if HAVE_LINUX_KVM_H
# include <linux/kvm.h>
#endif
117

118 119
/* device for kvm ioctls */
#define KVM_DEVICE "/dev/kvm"
120

121 122 123 124 125 126 127 128 129 130 131
/* add definitions missing in older linux/kvm.h */
#ifndef KVMIO
# define KVMIO 0xAE
#endif
#ifndef KVM_CHECK_EXTENSION
# define KVM_CHECK_EXTENSION       _IO(KVMIO,   0x03)
#endif
#ifndef KVM_CAP_NR_VCPUS
# define KVM_CAP_NR_VCPUS 9       /* returns max vcpus per vm */
#endif

132
#define QEMU_NB_BLKIO_PARAM  2
133

134 135
#define QEMU_NB_BANDWIDTH_PARAM 6

H
Hu Tao 已提交
136 137
static void processWatchdogEvent(void *data, void *opaque);

138
static int qemuStateCleanup(void);
139

140
static int qemuDomainObjStart(virConnectPtr conn,
141
                              virQEMUDriverPtr driver,
142
                              virDomainObjPtr vm,
143
                              unsigned int flags);
J
Jiri Denemark 已提交
144

145
static int qemuDomainGetMaxVcpus(virDomainPtr dom);
146

147 148
static int qemuDomainManagedSaveLoad(virDomainObjPtr vm,
                                     void *opaque);
149 150


151
virQEMUDriverPtr qemu_driver = NULL;
152 153


154
static void
155
qemuVMDriverLock(void) {}
156
static void
157
qemuVMDriverUnlock(void) {}
158 159 160

static int
qemuVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
161
                    virDomainObjListIterator iter, void *data)
162
{
163
    return virDomainObjListForEach(qemu_driver->domains, iter, data);
164 165 166 167 168 169 170 171 172 173
}

static virNWFilterCallbackDriver qemuCallbackDriver = {
    .name = QEMU_DRIVER_NAME,
    .vmFilterRebuild = qemuVMFilterRebuild,
    .vmDriverLock = qemuVMDriverLock,
    .vmDriverUnlock = qemuVMDriverUnlock,
};


174
struct qemuAutostartData {
175
    virQEMUDriverPtr driver;
176 177
    virConnectPtr conn;
};
178

179

180
/**
181
 * qemuDomObjFromDomain:
182 183
 * @domain: Domain pointer that has to be looked up
 *
184 185
 * This function looks up @domain and returns the appropriate
 * virDomainObjPtr.
186
 *
187 188
 * Returns the domain object which is locked on success, NULL
 * otherwise.
189
 */
190
static virDomainObjPtr
191
qemuDomObjFromDomain(virDomainPtr domain)
192 193
{
    virDomainObjPtr vm;
194
    virQEMUDriverPtr driver = domain->conn->privateData;
195 196
    char uuidstr[VIR_UUID_STRING_BUFLEN];

197
    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
198 199 200
    if (!vm) {
        virUUIDFormat(domain->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
201 202
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, domain->name);
203
        return NULL;
204 205
    }

206 207
    return vm;
}
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

/* Looks up the domain object from snapshot and unlocks the driver. The
 * returned domain object is locked and the caller is responsible for
 * unlocking it */
static virDomainObjPtr
qemuDomObjFromSnapshot(virDomainSnapshotPtr snapshot)
{
    return qemuDomObjFromDomain(snapshot->domain);
}


/* Looks up snapshot object from VM and name */
static virDomainSnapshotObjPtr
qemuSnapObjFromName(virDomainObjPtr vm,
                    const char *name)
{
    virDomainSnapshotObjPtr snap = NULL;
    snap = virDomainSnapshotFindByName(vm->snapshots, name);
    if (!snap)
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("no domain snapshot with matching name '%s'"),
                       name);

    return snap;
}


/* Looks up snapshot object from VM and snapshotPtr */
static virDomainSnapshotObjPtr
qemuSnapObjFromSnapshot(virDomainObjPtr vm,
                        virDomainSnapshotPtr snapshot)
{
    return qemuSnapObjFromName(vm, snapshot->name);
}

243 244
static int
qemuAutostartDomain(virDomainObjPtr vm,
245
                    void *opaque)
246 247
{
    struct qemuAutostartData *data = opaque;
248
    virErrorPtr err;
249
    int flags = 0;
250
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(data->driver);
251
    int ret = -1;
252

253
    if (cfg->autoStartBypassCache)
254
        flags |= VIR_DOMAIN_START_BYPASS_CACHE;
255

256
    virObjectLock(vm);
257
    virResetLastError();
258 259
    if (vm->autostart &&
        !virDomainObjIsActive(vm)) {
260 261
        if (qemuDomainObjBeginJob(data->driver, vm,
                                  QEMU_JOB_MODIFY) < 0) {
262 263 264 265 266 267 268 269
            err = virGetLastError();
            VIR_ERROR(_("Failed to start job on VM '%s': %s"),
                      vm->def->name,
                      err ? err->message : _("unknown error"));
            goto cleanup;
        }

        if (qemuDomainObjStart(data->conn, data->driver, vm, flags) < 0) {
270
            err = virGetLastError();
271
            VIR_ERROR(_("Failed to autostart VM '%s': %s"),
272
                      vm->def->name,
273
                      err ? err->message : _("unknown error"));
274
        }
275

276
        if (qemuDomainObjEndJob(data->driver, vm) == 0)
277
            vm = NULL;
278
    }
279

280
    ret = 0;
281
cleanup:
282
    if (vm)
283
        virObjectUnlock(vm);
284
    virObjectUnref(cfg);
285
    return ret;
286 287
}

288

289
static void
290
qemuAutostartDomains(virQEMUDriverPtr driver)
291
{
292
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
293 294 295 296 297
    /* 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
     */
298
    virConnectPtr conn = virConnectOpen(cfg->uri);
299
    /* Ignoring NULL conn which is mostly harmless here */
300
    struct qemuAutostartData data = { driver, conn };
301

302
    virDomainObjListForEach(driver->domains, qemuAutostartDomain, &data);
303

304 305
    if (conn)
        virConnectClose(conn);
306
    virObjectUnref(cfg);
307 308
}

309
static int
310
qemuSecurityInit(virQEMUDriverPtr driver)
311
{
312
    char **names;
313 314
    virSecurityManagerPtr mgr = NULL;
    virSecurityManagerPtr stack = NULL;
315
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
316

317 318 319
    if (cfg->securityDriverNames &&
        cfg->securityDriverNames[0]) {
        names = cfg->securityDriverNames;
320
        while (names && *names) {
321 322
            if (!(mgr = virSecurityManagerNew(*names,
                                              QEMU_DRIVER_NAME,
323 324 325
                                              cfg->allowDiskFormatProbing,
                                              cfg->securityDefaultConfined,
                                              cfg->securityRequireConfined)))
326
                goto error;
327 328 329 330 331 332 333 334
            if (!stack) {
                if (!(stack = virSecurityManagerNewStack(mgr)))
                    goto error;
            } else {
                if (virSecurityManagerStackAddNested(stack, mgr) < 0)
                    goto error;
            }
            mgr = NULL;
335 336
            names++;
        }
337 338 339
    } else {
        if (!(mgr = virSecurityManagerNew(NULL,
                                          QEMU_DRIVER_NAME,
340 341 342
                                          cfg->allowDiskFormatProbing,
                                          cfg->securityDefaultConfined,
                                          cfg->securityRequireConfined)))
343
            goto error;
344
        if (!(stack = virSecurityManagerNewStack(mgr)))
345
            goto error;
346 347
        mgr = NULL;
    }
348

349
    if (cfg->privileged) {
350
        if (!(mgr = virSecurityManagerNewDAC(QEMU_DRIVER_NAME,
351 352 353 354 355 356
                                             cfg->user,
                                             cfg->group,
                                             cfg->allowDiskFormatProbing,
                                             cfg->securityDefaultConfined,
                                             cfg->securityRequireConfined,
                                             cfg->dynamicOwnership)))
357 358 359 360 361 362 363 364 365
            goto error;
        if (!stack) {
            if (!(stack = virSecurityManagerNewStack(mgr)))
                goto error;
        } else {
            if (virSecurityManagerStackAddNested(stack, mgr) < 0)
                goto error;
        }
        mgr = NULL;
366
    }
D
Daniel Veillard 已提交
367

368
    driver->securityManager = stack;
369
    virObjectUnref(cfg);
370
    return 0;
371

372
error:
373
    VIR_ERROR(_("Failed to initialize security drivers"));
374 375
    virObjectUnref(stack);
    virObjectUnref(mgr);
376
    virObjectUnref(cfg);
377 378
    return -1;
}
379

380

381 382
static int
qemuDomainSnapshotLoad(virDomainObjPtr vm,
383
                       void *data)
384
{
385 386 387 388 389 390 391
    char *baseDir = (char *)data;
    char *snapDir = NULL;
    DIR *dir = NULL;
    struct dirent *entry;
    char *xmlStr;
    char *fullpath;
    virDomainSnapshotDefPtr def = NULL;
392
    virDomainSnapshotObjPtr snap = NULL;
393
    virDomainSnapshotObjPtr current = NULL;
394
    char ebuf[1024];
395
    unsigned int flags = (VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE |
396
                          VIR_DOMAIN_SNAPSHOT_PARSE_DISKS |
397
                          VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL);
398
    int ret = -1;
399
    virCapsPtr caps = NULL;
400

401
    virObjectLock(vm);
402 403 404
    if (virAsprintf(&snapDir, "%s/%s", baseDir, vm->def->name) < 0) {
        VIR_ERROR(_("Failed to allocate memory for snapshot directory for domain %s"),
                   vm->def->name);
405
        goto cleanup;
406 407
    }

408 409 410
    if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
        goto cleanup;

411 412
    VIR_INFO("Scanning for snapshots for domain %s in %s", vm->def->name,
             snapDir);
413

414 415 416 417 418
    if (!(dir = opendir(snapDir))) {
        if (errno != ENOENT)
            VIR_ERROR(_("Failed to open snapshot directory %s for domain %s: %s"),
                      snapDir, vm->def->name,
                      virStrerror(errno, ebuf, sizeof(ebuf)));
419
        goto cleanup;
420 421
    }

422 423 424
    while ((entry = readdir(dir))) {
        if (entry->d_name[0] == '.')
            continue;
425

426 427 428
        /* NB: ignoring errors, so one malformed config doesn't
           kill the whole process */
        VIR_INFO("Loading snapshot file '%s'", entry->d_name);
429

430
        if (virAsprintf(&fullpath, "%s/%s", snapDir, entry->d_name) < 0) {
431
            VIR_ERROR(_("Failed to allocate memory for path"));
432 433
            continue;
        }
434

435
        if (virFileReadAll(fullpath, 1024*1024*1, &xmlStr) < 0) {
436 437 438 439 440 441
            /* Nothing we can do here, skip this one */
            VIR_ERROR(_("Failed to read snapshot file %s: %s"), fullpath,
                      virStrerror(errno, ebuf, sizeof(ebuf)));
            VIR_FREE(fullpath);
            continue;
        }
442

443
        def = virDomainSnapshotDefParseString(xmlStr, caps,
444
                                              qemu_driver->xmlopt,
445 446
                                              QEMU_EXPECTED_VIRT_TYPES,
                                              flags);
447 448
        if (def == NULL) {
            /* Nothing we can do here, skip this one */
449 450
            VIR_ERROR(_("Failed to parse snapshot XML from file '%s'"),
                      fullpath);
451 452 453 454
            VIR_FREE(fullpath);
            VIR_FREE(xmlStr);
            continue;
        }
455

456
        snap = virDomainSnapshotAssignDef(vm->snapshots, def);
457 458
        if (snap == NULL) {
            virDomainSnapshotDefFree(def);
459 460 461 462
        } else if (snap->def->current) {
            current = snap;
            if (!vm->current_snapshot)
                vm->current_snapshot = snap;
463
        }
464

465 466
        VIR_FREE(fullpath);
        VIR_FREE(xmlStr);
467 468
    }

469 470 471 472 473 474
    if (vm->current_snapshot != current) {
        VIR_ERROR(_("Too many snapshots claiming to be current for domain %s"),
                  vm->def->name);
        vm->current_snapshot = NULL;
    }

475
    if (virDomainSnapshotUpdateRelations(vm->snapshots) < 0)
476 477 478
        VIR_ERROR(_("Snapshots have inconsistent relations for domain %s"),
                  vm->def->name);

479 480 481 482 483 484 485 486
    /* FIXME: qemu keeps internal track of snapshots.  We can get access
     * to this info via the "info snapshots" monitor command for running
     * domains, or via "qemu-img snapshot -l" for shutoff domains.  It would
     * be nice to update our internal state based on that, but there is a
     * a problem.  qemu doesn't track all of the same metadata that we do.
     * In particular we wouldn't be able to fill in the <parent>, which is
     * pretty important in our metadata.
     */
487

488
    virResetLastError();
489

490
    ret = 0;
491 492 493 494
cleanup:
    if (dir)
        closedir(dir);
    VIR_FREE(snapDir);
495
    virObjectUnref(caps);
496
    virObjectUnlock(vm);
497
    return ret;
498 499
}

500

501 502
static int
qemuDomainNetsRestart(virDomainObjPtr vm,
503
                      void *data ATTRIBUTE_UNUSED)
504
{
505 506 507
    int i;
    virDomainDefPtr def = vm->def;

508
    virObjectLock(vm);
509 510 511 512 513 514 515 516

    for (i = 0; i < def->nnets; i++) {
        virDomainNetDefPtr net = def->nets[i];
        if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT &&
            virDomainNetGetActualDirectMode(net) == VIR_NETDEV_MACVLAN_MODE_VEPA) {
            VIR_DEBUG("VEPA mode device %s active in domain %s. Reassociating.",
                      net->ifname, def->name);
            ignore_value(virNetDevMacVLanRestartWithVPortProfile(net->ifname,
517
                                                                 &net->mac,
518 519 520 521 522 523 524
                                                                 virDomainNetGetActualDirectDev(net),
                                                                 def->uuid,
                                                                 virDomainNetGetActualVirtPortProfile(net),
                                                                 VIR_NETDEV_VPORT_PROFILE_OP_CREATE));
        }
    }

525
    virObjectUnlock(vm);
526
    return 0;
527 528
}

529

530 531
static int
qemuDomainFindMaxID(virDomainObjPtr vm,
532 533 534 535 536 537
                    void *data)
{
    int *driver_maxid = data;

    if (vm->def->id >= *driver_maxid)
        *driver_maxid = vm->def->id + 1;
538 539

    return 0;
540 541 542
}


543
/**
544
 * qemuStateInitialize:
545 546 547
 *
 * Initialization function for the QEmu daemon
 */
548
static int
549 550 551
qemuStateInitialize(bool privileged,
                    virStateInhibitCallback callback,
                    void *opaque)
552
{
553 554
    char *driverConf = NULL;
    virConnectPtr conn = NULL;
555
    char ebuf[1024];
556 557
    char *membase = NULL;
    char *mempath = NULL;
558
    virQEMUDriverConfigPtr cfg;
559 560
    uid_t run_uid = -1;
    gid_t run_gid = -1;
561

562 563
    if (VIR_ALLOC(qemu_driver) < 0)
        return -1;
564

565
    if (virMutexInit(&qemu_driver->lock) < 0) {
566
        VIR_ERROR(_("cannot initialize mutex"));
567 568
        VIR_FREE(qemu_driver);
        return -1;
569
    }
570

571 572
    qemu_driver->inhibitCallback = callback;
    qemu_driver->inhibitOpaque = opaque;
573

574 575
    /* Don't have a dom0 so start from 1 */
    qemu_driver->nextvmid = 1;
576

577 578
    if (!(qemu_driver->domains = virDomainObjListNew()))
        goto error;
579

580
    /* Init domain events */
581
    qemu_driver->domainEventState = virDomainEventStateNew();
582
    if (!qemu_driver->domainEventState)
583
        goto error;
584

585 586 587
    /* read the host sysinfo */
    if (privileged)
        qemu_driver->hostsysinfo = virSysinfoRead();
588

589 590
    if (!(qemu_driver->config = cfg = virQEMUDriverConfigNew(privileged)))
        goto error;
591

592 593
    if (virAsprintf(&driverConf, "%s/qemu.conf", cfg->configBaseDir) < 0)
        goto out_of_memory;
594

595 596 597
    if (virQEMUDriverConfigLoadFile(cfg, driverConf) < 0)
        goto error;
    VIR_FREE(driverConf);
H
Hu Tao 已提交
598

599
    if (virFileMakePath(cfg->stateDir) < 0) {
600
        VIR_ERROR(_("Failed to create state dir '%s': %s"),
601
                  cfg->stateDir, virStrerror(errno, ebuf, sizeof(ebuf)));
602
        goto error;
H
Hu Tao 已提交
603
    }
604
    if (virFileMakePath(cfg->libDir) < 0) {
605
        VIR_ERROR(_("Failed to create lib dir '%s': %s"),
606
                  cfg->libDir, virStrerror(errno, ebuf, sizeof(ebuf)));
607 608
        goto error;
    }
609
    if (virFileMakePath(cfg->cacheDir) < 0) {
610
        VIR_ERROR(_("Failed to create cache dir '%s': %s"),
611
                  cfg->cacheDir, virStrerror(errno, ebuf, sizeof(ebuf)));
612 613
        goto error;
    }
614
    if (virFileMakePath(cfg->saveDir) < 0) {
615
        VIR_ERROR(_("Failed to create save dir '%s': %s"),
616
                  cfg->saveDir, virStrerror(errno, ebuf, sizeof(ebuf)));
617 618
        goto error;
    }
619
    if (virFileMakePath(cfg->snapshotDir) < 0) {
620
        VIR_ERROR(_("Failed to create save dir '%s': %s"),
621
                  cfg->snapshotDir, virStrerror(errno, ebuf, sizeof(ebuf)));
622 623
        goto error;
    }
624
    if (virFileMakePath(cfg->autoDumpPath) < 0) {
625
        VIR_ERROR(_("Failed to create dump dir '%s': %s"),
626
                  cfg->autoDumpPath, virStrerror(errno, ebuf, sizeof(ebuf)));
627
        goto error;
628 629
    }

630 631 632
    qemu_driver->qemuImgBinary = virFindFileInPath("kvm-img");
    if (!qemu_driver->qemuImgBinary)
        qemu_driver->qemuImgBinary = virFindFileInPath("qemu-img");
633 634 635 636 637 638 639

    if (!(qemu_driver->lockManager =
          virLockManagerPluginNew(cfg->lockManagerName ?
                                  cfg->lockManagerName : "nop",
                                  "qemu",
                                  cfg->configBaseDir,
                                  0)))
640
        goto error;
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656

   if (cfg->macFilter) {
        if (!(qemu_driver->ebtables = ebtablesContextNew("qemu"))) {
            virReportSystemError(errno,
                                 _("failed to enable mac filter in '%s'"),
                                 __FILE__);
            goto error;
        }

        if ((errno = networkDisableAllFrames(qemu_driver))) {
            virReportSystemError(errno,
                                 _("failed to add rule to drop all frames in '%s'"),
                                 __FILE__);
            goto error;
        }
   }
657

658 659 660
    /* Allocate bitmap for remote display port reservations. We cannot
     * do this before the config is loaded properly, since the port
     * numbers are configurable now */
661
    if ((qemu_driver->remotePorts =
662 663
         virPortAllocatorNew(cfg->remotePortMin,
                             cfg->remotePortMax)) == NULL)
664 665
        goto error;

666 667 668 669 670
    if ((qemu_driver->webSocketPorts =
         virPortAllocatorNew(cfg->webSocketPortMin,
                             cfg->webSocketPortMax)) == NULL)
        goto error;

671 672
    if (qemuSecurityInit(qemu_driver) < 0)
        goto error;
673

674
    if ((qemu_driver->activePciHostdevs = virPCIDeviceListNew()) == NULL)
675
        goto error;
676

677
    if ((qemu_driver->activeUsbHostdevs = virUSBDeviceListNew()) == NULL)
678 679
        goto error;

680
    if ((qemu_driver->inactivePciHostdevs = virPCIDeviceListNew()) == NULL)
681 682
        goto error;

683 684 685
    if ((qemu_driver->activeScsiHostdevs = virSCSIDeviceListNew()) == NULL)
        goto error;

686
    if (!(qemu_driver->sharedDevices = virHashCreate(30, qemuSharedDeviceEntryFree)))
687 688
        goto error;

689
    if (privileged) {
690
        if (chown(cfg->libDir, cfg->user, cfg->group) < 0) {
691 692
            virReportSystemError(errno,
                                 _("unable to set ownership of '%s' to user %d:%d"),
693
                                 cfg->libDir, cfg->user, cfg->group);
694
            goto error;
695
        }
696
        if (chown(cfg->cacheDir, cfg->user, cfg->group) < 0) {
697
            virReportSystemError(errno,
698
                                 _("unable to set ownership of '%s' to %d:%d"),
699
                                 cfg->cacheDir, cfg->user, cfg->group);
700
            goto error;
701
        }
702
        if (chown(cfg->saveDir, cfg->user, cfg->group) < 0) {
703 704
            virReportSystemError(errno,
                                 _("unable to set ownership of '%s' to %d:%d"),
705
                                 cfg->saveDir, cfg->user, cfg->group);
706 707
            goto error;
        }
708
        if (chown(cfg->snapshotDir, cfg->user, cfg->group) < 0) {
709 710
            virReportSystemError(errno,
                                 _("unable to set ownership of '%s' to %d:%d"),
711
                                 cfg->snapshotDir, cfg->user, cfg->group);
712
            goto error;
713
        }
714 715
        run_uid = cfg->user;
        run_gid = cfg->group;
716
    }
717

718
    qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
719 720
                                                     run_uid,
                                                     run_gid);
721
    if (!qemu_driver->qemuCapsCache)
722 723
        goto error;

724
    if ((qemu_driver->caps = virQEMUDriverCreateCapabilities(qemu_driver)) == NULL)
725 726
        goto error;

727
    if (!(qemu_driver->xmlopt = virQEMUDriverCreateXMLConf(qemu_driver)))
728 729
        goto error;

730 731 732 733 734 735
    /* 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
736
     */
737 738
    if (cfg->hugetlbfsMount &&
        cfg->hugetlbfsMount[0] == '/') {
739
        if (virAsprintf(&membase, "%s/libvirt",
740
                        cfg->hugetlbfsMount) < 0 ||
741
            virAsprintf(&mempath, "%s/qemu", membase) < 0)
742
            goto out_of_memory;
743

744 745
        if (virFileMakePath(mempath) < 0) {
            virReportSystemError(errno,
746 747
                                 _("unable to create hugepage path %s"), mempath);
            goto error;
748
        }
749
        if (cfg->privileged) {
750 751
            if (virFileUpdatePerm(membase, 0, S_IXGRP | S_IXOTH) < 0)
                goto error;
752
            if (chown(mempath, cfg->user, cfg->group) < 0) {
753 754
                virReportSystemError(errno,
                                     _("unable to set ownership on %s to %d:%d"),
755 756
                                     mempath, cfg->user,
                                     cfg->group);
757 758
                goto error;
            }
G
Guido Günther 已提交
759
        }
S
Stefan Berger 已提交
760
        VIR_FREE(membase);
E
Eric Blake 已提交
761

762
        cfg->hugepagePath = mempath;
763
    }
764

765
    if (!(qemu_driver->closeCallbacks = virQEMUCloseCallbacksNew()))
766 767
        goto error;

768
    /* Get all the running persistent or transient configs first */
769
    if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
770 771
                                       cfg->stateDir,
                                       NULL, 1,
772
                                       qemu_driver->caps,
773
                                       qemu_driver->xmlopt,
774
                                       QEMU_EXPECTED_VIRT_TYPES,
775
                                       NULL, NULL) < 0)
776
        goto error;
777

778 779 780
    /* find the maximum ID from active and transient configs to initialize
     * the driver with. This is to avoid race between autostart and reconnect
     * threads */
781 782 783
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainFindMaxID,
                            &qemu_driver->nextvmid);
784

785 786 787
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainNetsRestart,
                            NULL);
788

789
    conn = virConnectOpen(cfg->uri);
790

791
    qemuProcessReconnectAll(conn, qemu_driver);
792

793
    /* Then inactive persistent configs */
794
    if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
795 796
                                       cfg->configDir,
                                       cfg->autostartDir, 0,
797
                                       qemu_driver->caps,
798
                                       qemu_driver->xmlopt,
799
                                       QEMU_EXPECTED_VIRT_TYPES,
800
                                       NULL, NULL) < 0)
801
        goto error;
802

803

804 805 806
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainSnapshotLoad,
                            cfg->snapshotDir);
807

808 809 810
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainManagedSaveLoad,
                            qemu_driver);
811

812
    qemu_driver->workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver);
813 814
    if (!qemu_driver->workerPool)
        goto error;
815

816 817
    qemuAutostartDomains(qemu_driver);

818 819
    if (conn)
        virConnectClose(conn);
820

821
    virNWFilterRegisterCallbackDriver(&qemuCallbackDriver);
822
    return 0;
823

824 825 826 827 828 829
out_of_memory:
    virReportOOMError();
error:
    if (conn)
        virConnectClose(conn);
    VIR_FREE(driverConf);
830 831
    VIR_FREE(membase);
    VIR_FREE(mempath);
832
    qemuStateCleanup();
833
    return -1;
834 835
}

836
static void qemuNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
837
{
838
    virQEMUDriverPtr driver = opaque;
839

840 841 842 843 844 845 846
    if (newVM) {
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
        if (event)
            qemuDomainEventQueue(driver, event);
E
Eric Blake 已提交
847
    }
848
}
E
Eric Blake 已提交
849

850
/**
851
 * qemuStateReload:
852 853 854 855 856
 *
 * Function to restart the QEmu daemon, it will recheck the configuration
 * files and update its state and the networking
 */
static int
857
qemuStateReload(void) {
858 859
    virQEMUDriverConfigPtr cfg = NULL;
    virCapsPtr caps = NULL;
860

861 862
    if (!qemu_driver)
        return 0;
863

864 865 866
    if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
        goto cleanup;

867
    cfg = virQEMUDriverGetConfig(qemu_driver);
868 869
    virDomainObjListLoadAllConfigs(qemu_driver->domains,
                                   cfg->configDir,
870 871 872
                                   cfg->autostartDir, 0,
                                   caps, qemu_driver->xmlopt,
                                   QEMU_EXPECTED_VIRT_TYPES,
873
                                   qemuNotifyLoadDomain, qemu_driver);
874
cleanup:
875
    virObjectUnref(cfg);
876
    virObjectUnref(caps);
877 878
    return 0;
}
S
Stefan Berger 已提交
879

880 881

/*
882
 * qemuStateStop:
883 884 885 886 887
 *
 * Save any VMs in preparation for shutdown
 *
 */
static int
888
qemuStateStop(void) {
889 890
    int ret = -1;
    virConnectPtr conn;
891
    int numDomains = 0;
892 893 894 895
    size_t i;
    int state;
    virDomainPtr *domains = NULL;
    unsigned int *flags = NULL;
896
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(qemu_driver);
897

898 899
    if (!(conn = virConnectOpen(cfg->uri)))
        goto cleanup;
900 901 902 903 904 905 906 907 908 909 910 911 912 913

    if ((numDomains = virConnectListAllDomains(conn,
                                               &domains,
                                               VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0)
        goto cleanup;

    if (VIR_ALLOC_N(flags, numDomains) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    /* First we pause all VMs to make them stop dirtying
       pages, etc. We remember if any VMs were paused so
       we can restore that on resume. */
914
    for (i = 0; i < numDomains; i++) {
915 916 917 918 919 920 921 922 923 924 925
        flags[i] = VIR_DOMAIN_SAVE_RUNNING;
        if (virDomainGetState(domains[i], &state, NULL, 0) == 0) {
            if (state == VIR_DOMAIN_PAUSED) {
                flags[i] = VIR_DOMAIN_SAVE_PAUSED;
            }
        }
        virDomainSuspend(domains[i]);
    }

    ret = 0;
    /* Then we save the VMs to disk */
926
    for (i = 0; i < numDomains; i++)
927 928 929 930
        if (virDomainManagedSave(domains[i], flags[i]) < 0)
            ret = -1;

 cleanup:
931
    for (i = 0; i < numDomains; i++)
932 933 934
        virDomainFree(domains[i]);
    VIR_FREE(domains);
    VIR_FREE(flags);
935 936 937
    if (conn)
        virConnectClose(conn);
    virObjectUnref(cfg);
938 939 940 941

    return ret;
}

942
/**
943
 * qemuStateCleanup:
944 945 946 947
 *
 * Shutdown the QEmu daemon, it will stop all active domains and networks
 */
static int
948
qemuStateCleanup(void) {
949 950
    if (!qemu_driver)
        return -1;
951

952
    virNWFilterUnRegisterCallbackDriver(&qemuCallbackDriver);
953
    virObjectUnref(qemu_driver->config);
954 955 956
    virObjectUnref(qemu_driver->activePciHostdevs);
    virObjectUnref(qemu_driver->inactivePciHostdevs);
    virObjectUnref(qemu_driver->activeUsbHostdevs);
957
    virHashFree(qemu_driver->sharedDevices);
958
    virObjectUnref(qemu_driver->caps);
959
    virQEMUCapsCacheFree(qemu_driver->qemuCapsCache);
960

961
    virObjectUnref(qemu_driver->domains);
962
    virObjectUnref(qemu_driver->remotePorts);
963

964
    virObjectUnref(qemu_driver->xmlopt);
965

966
    virSysinfoDefFree(qemu_driver->hostsysinfo);
967

968
    virObjectUnref(qemu_driver->closeCallbacks);
969

E
Eric Blake 已提交
970
    VIR_FREE(qemu_driver->qemuImgBinary);
971

972
    virObjectUnref(qemu_driver->securityManager);
973

974
    ebtablesContextFree(qemu_driver->ebtables);
975

976
    /* Free domain callback list */
977
    virDomainEventStateFree(qemu_driver->domainEventState);
D
Daniel P. Berrange 已提交
978

979 980
    virLockManagerPluginUnref(qemu_driver->lockManager);

981 982 983
    virMutexDestroy(&qemu_driver->lock);
    virThreadPoolFree(qemu_driver->workerPool);
    VIR_FREE(qemu_driver);
984

985
    return 0;
986 987
}

988

989 990 991
static virDrvOpenStatus qemuConnectOpen(virConnectPtr conn,
                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                        unsigned int flags)
992
{
993 994
    virQEMUDriverConfigPtr cfg = NULL;
    virDrvOpenStatus ret = VIR_DRV_OPEN_ERROR;
E
Eric Blake 已提交
995 996
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

997
    if (conn->uri == NULL) {
998 999 1000 1001 1002 1003
        if (qemu_driver == NULL) {
            ret = VIR_DRV_OPEN_DECLINED;
            goto cleanup;
        }

        cfg = virQEMUDriverGetConfig(qemu_driver);
1004

1005 1006
        if (!(conn->uri = virURIParse(cfg->uri)))
            goto cleanup;
1007 1008 1009
    } else {
        /* If URI isn't 'qemu' its definitely not for us */
        if (conn->uri->scheme == NULL ||
1010 1011 1012 1013
            STRNEQ(conn->uri->scheme, "qemu")) {
            ret = VIR_DRV_OPEN_DECLINED;
            goto cleanup;
        }
1014 1015

        /* Allow remote driver to deal with URIs with hostname server */
1016 1017 1018 1019
        if (conn->uri->server != NULL) {
            ret = VIR_DRV_OPEN_DECLINED;
            goto cleanup;
        }
1020

1021
        if (qemu_driver == NULL) {
1022 1023
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("qemu state driver is not active"));
1024
            goto cleanup;
1025 1026
        }

J
Ján Tomko 已提交
1027
        cfg = virQEMUDriverGetConfig(qemu_driver);
1028
        if (conn->uri->path == NULL) {
1029 1030
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("no QEMU URI path given, try %s"),
1031 1032
                           cfg->uri);
            goto cleanup;
1033 1034
        }

1035
        if (cfg->privileged) {
1036 1037
            if (STRNEQ(conn->uri->path, "/system") &&
                STRNEQ(conn->uri->path, "/session")) {
1038 1039 1040
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected QEMU URI path '%s', try qemu:///system"),
                               conn->uri->path);
1041
                goto cleanup;
1042 1043
            }
        } else {
1044
            if (STRNEQ(conn->uri->path, "/session")) {
1045 1046 1047
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected QEMU URI path '%s', try qemu:///session"),
                               conn->uri->path);
1048
                goto cleanup;
1049 1050
            }
        }
1051 1052 1053
    }
    conn->privateData = qemu_driver;

1054 1055 1056 1057
    ret = VIR_DRV_OPEN_SUCCESS;
cleanup:
    virObjectUnref(cfg);
    return ret;
1058 1059
}

1060
static int qemuConnectClose(virConnectPtr conn)
1061
{
1062
    virQEMUDriverPtr driver = conn->privateData;
1063 1064

    /* Get rid of callbacks registered for this conn */
1065
    virQEMUCloseCallbacksRun(driver->closeCallbacks, conn, driver);
1066 1067 1068 1069 1070 1071

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
1072 1073
/* Which features are supported by this driver? */
static int
1074
qemuConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
D
Daniel Veillard 已提交
1075 1076
{
    switch (feature) {
1077
    case VIR_DRV_FEATURE_MIGRATION_V2:
1078
    case VIR_DRV_FEATURE_MIGRATION_V3:
1079
    case VIR_DRV_FEATURE_MIGRATION_P2P:
1080
    case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
1081
    case VIR_DRV_FEATURE_FD_PASSING:
1082
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
1083
    case VIR_DRV_FEATURE_XML_MIGRATABLE:
L
liguang 已提交
1084
    case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
1085 1086 1087
        return 1;
    default:
        return 0;
D
Daniel Veillard 已提交
1088 1089 1090
    }
}

1091
static const char *qemuConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1092
    return "QEMU";
1093 1094
}

1095

1096
static int qemuConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1097 1098 1099 1100 1101
{
    /* Trivially secure, since always inside the daemon */
    return 1;
}

1102
static int qemuConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1103 1104 1105 1106 1107
{
    /* Not encrypted, but remote driver takes care of that */
    return 0;
}

1108
static int qemuConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1109 1110 1111 1112
{
    return 1;
}

1113

1114 1115 1116 1117
static int
kvmGetMaxVCPUs(void) {
    int fd;
    int ret;
1118

1119
    if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) {
1120
        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
1121
        return -1;
1122 1123
    }

1124
#ifdef KVM_CAP_MAX_VCPUS
1125 1126 1127
    /* at first try KVM_CAP_MAX_VCPUS to determine the maximum count */
    if ((ret = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_MAX_VCPUS)) > 0)
        goto cleanup;
1128
#endif /* KVM_CAP_MAX_VCPUS */
1129 1130 1131 1132 1133 1134 1135 1136 1137

    /* as a fallback get KVM_CAP_NR_VCPUS (the recommended maximum number of
     * vcpus). Note that on most machines this is set to 160. */
    if ((ret = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_NR_VCPUS)) > 0)
        goto cleanup;

    /* if KVM_CAP_NR_VCPUS doesn't exist either, kernel documentation states
     * that 4 should be used as the maximum number of cpus */
    ret = 4;
1138

1139
cleanup:
1140
    VIR_FORCE_CLOSE(fd);
1141
    return ret;
1142 1143 1144
}


E
Eric Blake 已提交
1145
static char *
1146
qemuConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
E
Eric Blake 已提交
1147
{
1148
    virQEMUDriverPtr driver = conn->privateData;
1149
    virBuffer buf = VIR_BUFFER_INITIALIZER;
E
Eric Blake 已提交
1150 1151 1152 1153

    virCheckFlags(0, NULL);

    if (!driver->hostsysinfo) {
1154 1155
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Host SMBIOS information is not available"));
E
Eric Blake 已提交
1156 1157 1158
        return NULL;
    }

1159 1160 1161 1162 1163 1164 1165
    if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
        return NULL;
    if (virBufferError(&buf)) {
        virReportOOMError();
        return NULL;
    }
    return virBufferContentAndReset(&buf);
E
Eric Blake 已提交
1166 1167
}

1168
static int qemuConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type) {
1169 1170 1171
    if (!type)
        return 16;

1172
    if (STRCASEEQ(type, "qemu"))
1173 1174
        return 16;

1175
    if (STRCASEEQ(type, "kvm"))
1176
        return kvmGetMaxVCPUs();
1177

1178
    if (STRCASEEQ(type, "kqemu"))
1179
        return 1;
1180

1181 1182
    virReportError(VIR_ERR_INVALID_ARG,
                   _("unknown type '%s'"), type);
1183 1184 1185
    return -1;
}

1186

1187
static char *qemuConnectGetCapabilities(virConnectPtr conn) {
1188
    virQEMUDriverPtr driver = conn->privateData;
1189
    virCapsPtr caps = NULL;
1190
    char *xml = NULL;
1191

1192
    if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
1193
        goto cleanup;
1194

1195
    if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
1196
        virReportOOMError();
1197
    virObjectUnref(caps);
1198 1199

cleanup:
1200

1201
    return xml;
1202 1203 1204
}


1205
static int
1206 1207
qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
                   pid_t pid, int tid)
1208 1209
{
    char *proc;
D
Daniel P. Berrange 已提交
1210
    FILE *pidinfo;
1211
    unsigned long long usertime, systime;
1212
    long rss;
1213 1214
    int cpu;
    int ret;
D
Daniel P. Berrange 已提交
1215

1216 1217
    /* In general, we cannot assume pid_t fits in int; but /proc parsing
     * is specific to Linux where int works fine.  */
1218
    if (tid)
1219
        ret = virAsprintf(&proc, "/proc/%d/task/%d/stat", (int) pid, tid);
1220
    else
1221
        ret = virAsprintf(&proc, "/proc/%d/stat", (int) pid);
1222
    if (ret < 0)
D
Daniel P. Berrange 已提交
1223 1224 1225 1226
        return -1;

    if (!(pidinfo = fopen(proc, "r"))) {
        /* VM probably shut down, so fake 0 */
1227 1228 1229 1230
        if (cpuTime)
            *cpuTime = 0;
        if (lastCpu)
            *lastCpu = 0;
1231 1232
        if (vm_rss)
            *vm_rss = 0;
1233
        VIR_FREE(proc);
D
Daniel P. Berrange 已提交
1234 1235
        return 0;
    }
1236
    VIR_FREE(proc);
D
Daniel P. Berrange 已提交
1237

1238 1239 1240 1241 1242 1243
    /* 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 */
1244
               "%*d %*d %*d %*d %*d %*d %*u %*u %ld %*u %*u %*u"
1245 1246
               /* startstack -> processor */
               "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %d",
1247
               &usertime, &systime, &rss, &cpu) != 4) {
1248
        VIR_FORCE_FCLOSE(pidinfo);
1249
        VIR_WARN("cannot parse process status data");
1250
        errno = -EINVAL;
D
Daniel P. Berrange 已提交
1251 1252 1253 1254 1255 1256 1257 1258
        return -1;
    }

    /* We got jiffies
     * We want nanoseconds
     * _SC_CLK_TCK is jiffies per second
     * So calulate thus....
     */
1259 1260 1261 1262 1263
    if (cpuTime)
        *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
    if (lastCpu)
        *lastCpu = cpu;

1264 1265 1266 1267 1268 1269
    /* We got pages
     * We want kiloBytes
     * _SC_PAGESIZE is page size in Bytes
     * So calculate, but first lower the pagesize so we don't get overflow */
    if (vm_rss)
        *vm_rss = rss * (sysconf(_SC_PAGESIZE) >> 10);
D
Daniel P. Berrange 已提交
1270

1271 1272

    VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d rss=%ld",
1273
              (int) pid, tid, usertime, systime, cpu, rss);
D
Daniel P. Berrange 已提交
1274

1275
    VIR_FORCE_FCLOSE(pidinfo);
D
Daniel P. Berrange 已提交
1276 1277 1278 1279 1280

    return 0;
}


1281 1282
static virDomainPtr qemuDomainLookupByID(virConnectPtr conn,
                                         int id) {
1283
    virQEMUDriverPtr driver = conn->privateData;
1284 1285 1286
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

1287
    vm  = virDomainObjListFindByID(driver->domains, id);
1288 1289

    if (!vm) {
1290 1291
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching id %d"), id);
1292
        goto cleanup;
1293 1294
    }

1295
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1296
    if (dom) dom->id = vm->def->id;
1297 1298

cleanup:
1299
    if (vm)
1300
        virObjectUnlock(vm);
1301 1302
    return dom;
}
1303

1304 1305
static virDomainPtr qemuDomainLookupByUUID(virConnectPtr conn,
                                           const unsigned char *uuid) {
1306
    virQEMUDriverPtr driver = conn->privateData;
1307 1308
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1309

1310
    vm = virDomainObjListFindByUUID(driver->domains, uuid);
1311

1312
    if (!vm) {
1313 1314
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(uuid, uuidstr);
1315 1316
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s'"), uuidstr);
1317
        goto cleanup;
1318 1319
    }

1320
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1321
    if (dom) dom->id = vm->def->id;
1322 1323

cleanup:
1324
    if (vm)
1325
        virObjectUnlock(vm);
1326 1327
    return dom;
}
1328

1329 1330
static virDomainPtr qemuDomainLookupByName(virConnectPtr conn,
                                           const char *name) {
1331
    virQEMUDriverPtr driver = conn->privateData;
1332 1333
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1334

1335
    vm = virDomainObjListFindByName(driver->domains, name);
1336

1337
    if (!vm) {
1338 1339
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching name '%s'"), name);
1340
        goto cleanup;
1341 1342
    }

1343
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1344
    if (dom) dom->id = vm->def->id;
1345 1346

cleanup:
1347
    if (vm)
1348
        virObjectUnlock(vm);
1349 1350 1351
    return dom;
}

1352 1353 1354 1355 1356 1357

static int qemuDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

1358
    if (!(obj = qemuDomObjFromDomain(dom)))
1359
        goto cleanup;
1360

1361 1362 1363 1364
    ret = virDomainObjIsActive(obj);

cleanup:
    if (obj)
1365
        virObjectUnlock(obj);
1366 1367 1368 1369 1370 1371 1372 1373
    return ret;
}

static int qemuDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

1374
    if (!(obj = qemuDomObjFromDomain(dom)))
1375
        goto cleanup;
1376

1377 1378 1379 1380
    ret = obj->persistent;

cleanup:
    if (obj)
1381
        virObjectUnlock(obj);
1382 1383 1384
    return ret;
}

1385 1386 1387 1388 1389
static int qemuDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

1390
    if (!(obj = qemuDomObjFromDomain(dom)))
1391
        goto cleanup;
1392

1393 1394 1395 1396
    ret = obj->updated;

cleanup:
    if (obj)
1397
        virObjectUnlock(obj);
1398 1399
    return ret;
}
1400

1401
static int qemuConnectGetVersion(virConnectPtr conn, unsigned long *version) {
1402
    virQEMUDriverPtr driver = conn->privateData;
1403
    int ret = -1;
1404
    unsigned int qemuVersion = 0;
1405
    virCapsPtr caps = NULL;
1406

1407 1408 1409 1410
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (virQEMUCapsGetDefaultVersion(caps,
1411 1412
                                     driver->qemuCapsCache,
                                     &qemuVersion) < 0)
1413
        goto cleanup;
1414

1415
    *version = qemuVersion;
1416 1417 1418
    ret = 0;

cleanup:
1419
    virObjectUnref(caps);
1420
    return ret;
D
Daniel P. Berrange 已提交
1421 1422
}

1423 1424 1425 1426 1427 1428 1429

static char *qemuConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


1430
static int qemuConnectListDomains(virConnectPtr conn, int *ids, int nids) {
1431
    virQEMUDriverPtr driver = conn->privateData;
1432
    int n;
1433

1434
    n = virDomainObjListGetActiveIDs(driver->domains, ids, nids);
1435

1436
    return n;
D
Daniel P. Berrange 已提交
1437
}
1438

1439
static int qemuConnectNumOfDomains(virConnectPtr conn) {
1440
    virQEMUDriverPtr driver = conn->privateData;
1441
    int n;
1442

1443
    n = virDomainObjListNumOfDomains(driver->domains, 1);
1444

1445
    return n;
D
Daniel P. Berrange 已提交
1446
}
1447

1448 1449

static int
1450
qemuCanonicalizeMachine(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
1451
{
1452
    const char *canon;
1453

1454
    if (!(canon = virQEMUCapsGetCanonicalMachine(qemuCaps, def->os.machine)))
1455 1456 1457
        return 0;

    if (STRNEQ(canon, def->os.machine)) {
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
        char *tmp;
        if (!(tmp = strdup(canon))) {
            virReportOOMError();
            return -1;
        }
        VIR_FREE(def->os.machine);
        def->os.machine = tmp;
    }

    return 0;
}


1471 1472 1473
static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
                                        const char *xml,
                                        unsigned int flags) {
1474
    virQEMUDriverPtr driver = conn->privateData;
1475
    virDomainDefPtr def = NULL;
1476
    virDomainObjPtr vm = NULL;
1477
    virDomainPtr dom = NULL;
1478
    virDomainEventPtr event = NULL;
1479
    virDomainEventPtr event2 = NULL;
1480
    unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
1481
    virQEMUCapsPtr qemuCaps = NULL;
1482
    virCapsPtr caps = NULL;
D
Daniel P. Berrange 已提交
1483

1484 1485
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
                  VIR_DOMAIN_START_AUTODESTROY, NULL);
1486

1487 1488 1489
    if (flags & VIR_DOMAIN_START_PAUSED)
        start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
    if (flags & VIR_DOMAIN_START_AUTODESTROY)
1490
        start_flags |= VIR_QEMU_PROCESS_START_AUTODESTROY;
1491

1492 1493 1494
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

1495
    if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
M
Matthias Bolte 已提交
1496
                                        QEMU_EXPECTED_VIRT_TYPES,
1497
                                        VIR_DOMAIN_XML_INACTIVE)))
1498
        goto cleanup;
1499

1500
    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
1501 1502
        goto cleanup;

1503
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
1504 1505
        goto cleanup;

1506
    if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
1507 1508
        goto cleanup;

1509
    if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
1510 1511
        goto cleanup;

1512
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1513
                                   driver->xmlopt,
1514 1515
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1516 1517 1518
        goto cleanup;

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

1520
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1521 1522
        goto cleanup; /* XXXX free the 'vm' we created ? */

1523 1524 1525
    if (qemuProcessStart(conn, driver, vm, NULL, -1, NULL, NULL,
                         VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                         start_flags) < 0) {
1526
        virDomainAuditStart(vm, "booted", false);
1527
        if (qemuDomainObjEndJob(driver, vm) > 0)
1528
            qemuDomainRemoveInactive(driver, vm);
1529
        vm = NULL;
1530
        goto cleanup;
D
Daniel P. Berrange 已提交
1531
    }
1532 1533 1534 1535

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
    if (event && (flags & VIR_DOMAIN_START_PAUSED)) {
        /* There are two classes of event-watching clients - those
         * that only care about on/off (and must see a started event
         * no matter what, but don't care about suspend events), and
         * those that also care about running/paused.  To satisfy both
         * client types, we have to send two events.  */
        event2 = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_SUSPENDED,
                                          VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
    }
1546
    virDomainAuditStart(vm, "booted", true);
D
Daniel P. Berrange 已提交
1547

1548
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1549
    if (dom) dom->id = vm->def->id;
1550

1551
    if (vm &&
1552
        qemuDomainObjEndJob(driver, vm) == 0)
1553
        vm = NULL;
1554

1555 1556
cleanup:
    virDomainDefFree(def);
1557
    if (vm)
1558
        virObjectUnlock(vm);
1559
    if (event) {
1560
        qemuDomainEventQueue(driver, event);
1561 1562 1563
        if (event2)
            qemuDomainEventQueue(driver, event2);
    }
1564
    virObjectUnref(caps);
1565
    virObjectUnref(qemuCaps);
1566
    return dom;
D
Daniel P. Berrange 已提交
1567 1568 1569
}


1570
static int qemuDomainSuspend(virDomainPtr dom) {
1571
    virQEMUDriverPtr driver = dom->conn->privateData;
1572 1573
    virDomainObjPtr vm;
    int ret = -1;
1574
    virDomainEventPtr event = NULL;
1575
    qemuDomainObjPrivatePtr priv;
1576 1577
    virDomainPausedReason reason;
    int eventDetail;
1578
    int state;
1579
    virQEMUDriverConfigPtr cfg = NULL;
1580

1581 1582
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
1583

D
Daniel P. Berrange 已提交
1584
    if (!virDomainObjIsActive(vm)) {
1585 1586
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1587
        goto cleanup;
D
Daniel P. Berrange 已提交
1588
    }
1589

1590
    cfg = virQEMUDriverGetConfig(driver);
1591 1592
    priv = vm->privateData;

1593
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_SUSPEND) < 0)
1594 1595 1596
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
1597 1598
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1599 1600
        goto endjob;
    }
1601

1602 1603 1604
    if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) {
        reason = VIR_DOMAIN_PAUSED_MIGRATION;
        eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED;
1605 1606 1607
    } else if (priv->job.asyncJob == QEMU_ASYNC_JOB_SNAPSHOT) {
        reason = VIR_DOMAIN_PAUSED_SNAPSHOT;
        eventDetail = -1; /* don't create lifecycle events when doing snapshot */
1608 1609 1610 1611 1612
    } else {
        reason = VIR_DOMAIN_PAUSED_USER;
        eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
    }

1613 1614 1615 1616 1617 1618
    state = virDomainObjGetState(vm, NULL);
    if (state == VIR_DOMAIN_PMSUSPENDED) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is pmsuspended"));
        goto endjob;
    } else if (state != VIR_DOMAIN_PAUSED) {
1619
        if (qemuProcessStopCPUs(driver, vm, reason, QEMU_ASYNC_JOB_NONE) < 0) {
1620
            goto endjob;
1621
        }
1622 1623 1624 1625 1626 1627

        if (eventDetail >= 0) {
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_SUSPENDED,
                                             eventDetail);
        }
D
Daniel P. Berrange 已提交
1628
    }
1629
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1630 1631
        goto endjob;
    ret = 0;
1632

1633
endjob:
1634
    if (qemuDomainObjEndJob(driver, vm) == 0)
1635
        vm = NULL;
1636

1637
cleanup:
1638
    if (vm)
1639
        virObjectUnlock(vm);
1640

1641
    if (event)
1642
        qemuDomainEventQueue(driver, event);
1643
    virObjectUnref(cfg);
1644
    return ret;
D
Daniel P. Berrange 已提交
1645 1646 1647
}


1648
static int qemuDomainResume(virDomainPtr dom) {
1649
    virQEMUDriverPtr driver = dom->conn->privateData;
1650 1651
    virDomainObjPtr vm;
    int ret = -1;
1652
    virDomainEventPtr event = NULL;
1653
    int state;
1654
    virQEMUDriverConfigPtr cfg = NULL;
1655
    virCapsPtr caps = NULL;
1656

1657 1658
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
1659

1660 1661
    cfg = virQEMUDriverGetConfig(driver);

1662
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1663 1664
        goto cleanup;

D
Daniel P. Berrange 已提交
1665
    if (!virDomainObjIsActive(vm)) {
1666 1667
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1668
        goto endjob;
D
Daniel P. Berrange 已提交
1669
    }
1670 1671 1672 1673 1674 1675 1676

    state = virDomainObjGetState(vm, NULL);
    if (state == VIR_DOMAIN_PMSUSPENDED) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is pmsuspended"));
        goto endjob;
    } else if (state == VIR_DOMAIN_PAUSED) {
J
Jiri Denemark 已提交
1677
        if (qemuProcessStartCPUs(driver, vm, dom->conn,
1678 1679
                                 VIR_DOMAIN_RUNNING_UNPAUSED,
                                 QEMU_ASYNC_JOB_NONE) < 0) {
1680
            if (virGetLastError() == NULL)
1681 1682
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("resume operation failed"));
1683
            goto endjob;
1684
        }
1685 1686 1687
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
D
Daniel P. Berrange 已提交
1688
    }
1689 1690
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto endjob;
1691
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1692
        goto endjob;
1693 1694
    ret = 0;

1695
endjob:
1696
    if (qemuDomainObjEndJob(driver, vm) == 0)
1697
        vm = NULL;
1698

1699
cleanup:
1700
    if (vm)
1701
        virObjectUnlock(vm);
1702
    if (event)
1703
        qemuDomainEventQueue(driver, event);
1704
    virObjectUnref(caps);
1705
    virObjectUnref(cfg);
1706
    return ret;
D
Daniel P. Berrange 已提交
1707 1708
}

1709
static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags) {
1710
    virQEMUDriverPtr driver = dom->conn->privateData;
1711 1712
    virDomainObjPtr vm;
    int ret = -1;
1713
    qemuDomainObjPrivatePtr priv;
1714
    bool useAgent = false, agentRequested, acpiRequested;
1715 1716
    bool isReboot = false;
    int agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
1717 1718 1719

    virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
                  VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1);
1720

1721
    if (!(vm = qemuDomObjFromDomain(dom)))
1722
        goto cleanup;
1723

1724 1725 1726 1727 1728 1729 1730
    if (vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_RESTART ||
        vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_RESTART_RENAME) {
        isReboot = true;
        agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
        VIR_INFO("Domain on_poweroff setting overridden, attempting reboot");
    }

1731
    priv = vm->privateData;
1732 1733
    agentRequested = flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT;
    acpiRequested  = flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
1734

1735 1736
    /* Prefer agent unless we were requested to not to. */
    if (agentRequested || (!flags && priv->agent))
1737 1738
        useAgent = true;

1739 1740
    if (priv->agentError) {
        if (agentRequested && !acpiRequested) {
1741 1742 1743
            virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                           _("QEMU guest agent is not "
                             "available due to an error"));
1744
            goto cleanup;
1745 1746
        } else {
            useAgent = false;
1747
        }
1748 1749 1750 1751
    }

    if (!priv->agent) {
        if (agentRequested && !acpiRequested) {
1752 1753
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("QEMU guest agent is not configured"));
1754
            goto cleanup;
1755 1756
        } else {
            useAgent = false;
1757 1758 1759
        }
    }

1760
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1761 1762
        goto cleanup;

D
Daniel P. Berrange 已提交
1763
    if (!virDomainObjIsActive(vm)) {
1764 1765
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1766
        goto endjob;
1767 1768
    }

1769
    if (useAgent) {
1770
        qemuDomainObjEnterAgent(vm);
1771
        ret = qemuAgentShutdown(priv->agent, agentFlag);
1772
        qemuDomainObjExitAgent(vm);
1773 1774 1775 1776 1777 1778 1779
    }

    /* If we are not enforced to use just an agent, try ACPI
     * shutdown as well in case agent did not succeed.
     */
    if (!useAgent ||
        (ret < 0 && (acpiRequested || !flags))) {
1780
        qemuDomainSetFakeReboot(driver, vm, isReboot);
1781

1782 1783 1784 1785
        qemuDomainObjEnterMonitor(driver, vm);
        ret = qemuMonitorSystemPowerdown(priv->mon);
        qemuDomainObjExitMonitor(driver, vm);
    }
1786

1787
endjob:
1788
    if (qemuDomainObjEndJob(driver, vm) == 0)
1789
        vm = NULL;
1790

1791
cleanup:
1792
    if (vm)
1793
        virObjectUnlock(vm);
1794
    return ret;
1795 1796
}

1797 1798
static int qemuDomainShutdown(virDomainPtr dom)
{
1799 1800 1801
    return qemuDomainShutdownFlags(dom, 0);
}

1802

1803 1804 1805
static int
qemuDomainReboot(virDomainPtr dom, unsigned int flags)
{
1806
    virQEMUDriverPtr driver = dom->conn->privateData;
1807 1808 1809
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
1810
    bool useAgent = false;
1811 1812
    bool isReboot = true;
    int agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
1813

1814 1815
    virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
                  VIR_DOMAIN_REBOOT_GUEST_AGENT , -1);
1816

1817 1818 1819 1820 1821 1822 1823 1824
    /* At most one of these two flags should be set.  */
    if ((flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) &&
        (flags & VIR_DOMAIN_REBOOT_GUEST_AGENT)) {
        virReportInvalidArg(flags, "%s",
                            _("flags for acpi power button and guest agent are mutually exclusive"));
        return -1;
    }

1825
    if (!(vm = qemuDomObjFromDomain(dom)))
1826 1827
        goto cleanup;

1828 1829 1830 1831 1832 1833 1834
    if (vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_DESTROY ||
        vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_PRESERVE) {
        agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
        isReboot = false;
        VIR_INFO("Domain on_reboot setting overridden, shutting down");
    }

1835 1836
    priv = vm->privateData;

1837 1838
    if ((flags & VIR_DOMAIN_REBOOT_GUEST_AGENT) ||
        (!(flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) &&
1839 1840 1841 1842 1843
         priv->agent))
        useAgent = true;

    if (useAgent) {
        if (priv->agentError) {
1844 1845 1846
            virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                           _("QEMU guest agent is not "
                             "available due to an error"));
1847 1848 1849
            goto cleanup;
        }
        if (!priv->agent) {
1850 1851
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("QEMU guest agent is not configured"));
1852 1853 1854
            goto cleanup;
        }
    } else {
1855
#if WITH_YAJL
1856 1857
        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) {
1858 1859
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Reboot is not supported with this QEMU binary"));
1860 1861 1862 1863
                goto cleanup;
            }
        } else {
#endif
1864 1865
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Reboot is not supported without the JSON monitor"));
1866
            goto cleanup;
1867
#if WITH_YAJL
1868
        }
1869 1870
#endif
    }
1871

1872 1873
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;
1874

1875
    if (!virDomainObjIsActive(vm)) {
1876 1877
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1878 1879
        goto endjob;
    }
1880

1881
    if (useAgent) {
1882
        qemuDomainObjEnterAgent(vm);
1883
        ret = qemuAgentShutdown(priv->agent, agentFlag);
1884
        qemuDomainObjExitAgent(vm);
1885
    } else {
1886
        qemuDomainObjEnterMonitor(driver, vm);
1887
        ret = qemuMonitorSystemPowerdown(priv->mon);
1888
        qemuDomainObjExitMonitor(driver, vm);
1889

1890
        if (ret == 0)
1891
            qemuDomainSetFakeReboot(driver, vm, isReboot);
1892 1893
    }

1894 1895 1896 1897
endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

1898 1899
cleanup:
    if (vm)
1900
        virObjectUnlock(vm);
1901 1902 1903 1904
    return ret;
}


1905 1906 1907
static int
qemuDomainReset(virDomainPtr dom, unsigned int flags)
{
1908
    virQEMUDriverPtr driver = dom->conn->privateData;
1909 1910 1911 1912 1913 1914
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

1915
    if (!(vm = qemuDomObjFromDomain(dom)))
1916 1917 1918 1919 1920 1921
        goto cleanup;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
1922 1923
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939
        goto endjob;
    }

    priv = vm->privateData;
    qemuDomainObjEnterMonitor(driver, vm);
    ret = qemuMonitorSystemReset(priv->mon);
    qemuDomainObjExitMonitor(driver, vm);

    priv->fakeReboot = false;

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    if (vm)
1940
        virObjectUnlock(vm);
1941 1942 1943 1944
    return ret;
}


1945
/* Count how many snapshots in a set are external snapshots or checkpoints.  */
1946 1947 1948 1949 1950 1951 1952 1953
static void
qemuDomainSnapshotCountExternal(void *payload,
                                const void *name ATTRIBUTE_UNUSED,
                                void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    int *count = data;

1954
    if (virDomainSnapshotIsExternal(snap))
1955 1956 1957
        (*count)++;
}

1958 1959 1960 1961
static int
qemuDomainDestroyFlags(virDomainPtr dom,
                       unsigned int flags)
{
1962
    virQEMUDriverPtr driver = dom->conn->privateData;
1963 1964
    virDomainObjPtr vm;
    int ret = -1;
1965
    virDomainEventPtr event = NULL;
1966
    qemuDomainObjPrivatePtr priv;
1967

1968
    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);
1969

1970 1971
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
1972

1973 1974
    priv = vm->privateData;

1975
    qemuDomainSetFakeReboot(driver, vm, false);
1976

1977 1978 1979 1980 1981 1982

    /* We need to prevent monitor EOF callback from doing our work (and sending
     * misleading events) while the vm is unlocked inside BeginJob/ProcessKill API
     */
    priv->beingDestroyed = true;

1983 1984 1985 1986 1987
    /* Although qemuProcessStop does this already, there may
     * be an outstanding job active. We want to make sure we
     * can kill the process even if a job is active. Killing
     * it now means the job will be released
     */
1988
    if (flags & VIR_DOMAIN_DESTROY_GRACEFUL) {
1989
        if (qemuProcessKill(vm, 0) < 0) {
1990
            priv->beingDestroyed = false;
1991
            goto cleanup;
1992
        }
1993
    } else {
1994
        if (qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE) < 0) {
1995
            priv->beingDestroyed = false;
1996
            goto cleanup;
1997
        }
1998
    }
1999

2000
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_DESTROY) < 0)
2001 2002
        goto cleanup;

2003 2004
    priv->beingDestroyed = false;

D
Daniel P. Berrange 已提交
2005
    if (!virDomainObjIsActive(vm)) {
2006 2007
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2008
        goto endjob;
2009
    }
2010

2011
    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED, 0);
2012 2013 2014
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2015
    virDomainAuditStop(vm, "destroyed");
2016

2017
    if (!vm->persistent) {
2018
        if (qemuDomainObjEndJob(driver, vm) > 0)
2019
            qemuDomainRemoveInactive(driver, vm);
2020 2021
        vm = NULL;
    }
2022 2023
    ret = 0;

2024
endjob:
2025
    if (vm &&
2026
        qemuDomainObjEndJob(driver, vm) == 0)
2027
        vm = NULL;
2028

2029
cleanup:
2030
    if (vm)
2031
        virObjectUnlock(vm);
2032 2033
    if (event)
        qemuDomainEventQueue(driver, event);
2034
    return ret;
D
Daniel P. Berrange 已提交
2035 2036
}

2037 2038 2039 2040 2041
static int
qemuDomainDestroy(virDomainPtr dom)
{
    return qemuDomainDestroyFlags(dom, 0);
}
D
Daniel P. Berrange 已提交
2042

2043
static char *qemuDomainGetOSType(virDomainPtr dom) {
2044 2045
    virDomainObjPtr vm;
    char *type = NULL;
2046

2047
    if (!(vm = qemuDomObjFromDomain(dom)))
2048
        goto cleanup;
2049

2050
    if (!(type = strdup(vm->def->os.type)))
2051
        virReportOOMError();
2052 2053

cleanup:
2054
    if (vm)
2055
        virObjectUnlock(vm);
2056 2057 2058
    return type;
}

2059
/* Returns max memory in kb, 0 if error */
2060 2061 2062
static unsigned long long
qemuDomainGetMaxMemory(virDomainPtr dom)
{
2063
    virDomainObjPtr vm;
2064
    unsigned long long ret = 0;
2065

2066
    if (!(vm = qemuDomObjFromDomain(dom)))
2067
        goto cleanup;
2068

2069
    ret = vm->def->mem.max_balloon;
2070 2071

cleanup:
2072
    if (vm)
2073
        virObjectUnlock(vm);
2074
    return ret;
2075 2076
}

2077 2078
static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
                                    unsigned int flags) {
2079
    virQEMUDriverPtr driver = dom->conn->privateData;
2080
    qemuDomainObjPrivatePtr priv;
2081
    virDomainObjPtr vm;
2082
    virDomainDefPtr persistentDef = NULL;
2083
    int ret = -1, r;
2084
    virQEMUDriverConfigPtr cfg = NULL;
2085
    virCapsPtr caps = NULL;
2086

2087 2088
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2089
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
2090

2091
    if (!(vm = qemuDomObjFromDomain(dom)))
2092
        goto cleanup;
2093

2094 2095
    cfg = virQEMUDriverGetConfig(driver);

2096
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2097 2098
        goto cleanup;

2099 2100
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto endjob;
2101
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
2102
                                        &persistentDef) < 0)
2103
        goto endjob;
2104

2105 2106 2107
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */

2108
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
2109 2110 2111
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot resize the maximum memory on an "
                             "active domain"));
2112
            goto endjob;
2113
        }
2114

2115
        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
E
Eric Blake 已提交
2116 2117
            /* Help clang 2.8 decipher the logic flow.  */
            sa_assert(persistentDef);
2118 2119 2120
            persistentDef->mem.max_balloon = newmem;
            if (persistentDef->mem.cur_balloon > newmem)
                persistentDef->mem.cur_balloon = newmem;
2121
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
2122 2123 2124
            goto endjob;
        }

2125 2126 2127 2128
    } else {
        /* resize the current memory */

        if (newmem > vm->def->mem.max_balloon) {
2129 2130
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
2131 2132 2133
            goto endjob;
        }

2134
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
2135
            priv = vm->privateData;
2136
            qemuDomainObjEnterMonitor(driver, vm);
2137
            r = qemuMonitorSetBalloon(priv->mon, newmem);
2138
            qemuDomainObjExitMonitor(driver, vm);
2139 2140
            virDomainAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update",
                                 r == 1);
2141 2142 2143 2144 2145
            if (r < 0)
                goto endjob;

            /* Lack of balloon support is a fatal error */
            if (r == 0) {
2146 2147 2148
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("Unable to change memory of active domain without "
                                 "the balloon device and guest OS balloon driver"));
2149 2150 2151 2152
                goto endjob;
            }
        }

2153
        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
E
Eric Blake 已提交
2154
            sa_assert(persistentDef);
2155
            persistentDef->mem.cur_balloon = newmem;
2156
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
2157 2158
            goto endjob;
        }
2159
    }
2160

2161
    ret = 0;
2162
endjob:
2163
    if (qemuDomainObjEndJob(driver, vm) == 0)
2164
        vm = NULL;
2165

2166
cleanup:
2167
    if (vm)
2168
        virObjectUnlock(vm);
2169
    virObjectUnref(caps);
2170
    virObjectUnref(cfg);
2171
    return ret;
2172 2173
}

2174
static int qemuDomainSetMemory(virDomainPtr dom, unsigned long newmem)
2175
{
2176
    return qemuDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_AFFECT_LIVE);
2177 2178
}

2179
static int qemuDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
2180
{
2181
    return qemuDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
2182 2183
}

2184 2185
static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
{
2186
    virQEMUDriverPtr driver = domain->conn->privateData;
2187 2188 2189 2190 2191 2192
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

2193 2194
    if (!(vm = qemuDomObjFromDomain(domain)))
        return -1;
2195 2196

    if (!virDomainObjIsActive(vm)) {
2197 2198
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2199 2200 2201 2202 2203
        goto cleanup;
    }

    priv = vm->privateData;

2204
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2205
        goto cleanup;
2206 2207

    if (!virDomainObjIsActive(vm)) {
2208 2209
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2210 2211 2212
        goto endjob;
    }

2213
    qemuDomainObjEnterMonitor(driver, vm);
2214
    ret = qemuMonitorInjectNMI(priv->mon);
2215
    qemuDomainObjExitMonitor(driver, vm);
2216 2217

endjob:
2218
    if (qemuDomainObjEndJob(driver, vm) == 0) {
2219 2220 2221 2222 2223 2224
        vm = NULL;
        goto cleanup;
    }

cleanup:
    if (vm)
2225
        virObjectUnlock(vm);
2226 2227 2228
    return ret;
}

2229 2230 2231 2232 2233 2234 2235
static int qemuDomainSendKey(virDomainPtr domain,
                             unsigned int codeset,
                             unsigned int holdtime,
                             unsigned int *keycodes,
                             int nkeycodes,
                             unsigned int flags)
{
2236
    virQEMUDriverPtr driver = domain->conn->privateData;
2237 2238 2239 2240 2241 2242
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

2243 2244
    /* translate the keycode to RFB for qemu driver */
    if (codeset != VIR_KEYCODE_SET_RFB) {
2245 2246 2247 2248
        int i;
        int keycode;

        for (i = 0; i < nkeycodes; i++) {
2249
            keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_RFB,
2250 2251
                                               keycodes[i]);
            if (keycode < 0) {
2252 2253 2254 2255
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot translate keycode %u of %s codeset to rfb keycode"),
                               keycodes[i],
                               virKeycodeSetTypeToString(codeset));
2256 2257 2258 2259 2260 2261
                return -1;
            }
            keycodes[i] = keycode;
        }
    }

2262
    if (!(vm = qemuDomObjFromDomain(domain)))
2263 2264 2265 2266
        goto cleanup;

    priv = vm->privateData;

2267
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2268 2269 2270
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
2271 2272
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2273
        goto endjob;
2274 2275
    }

2276
    qemuDomainObjEnterMonitor(driver, vm);
2277
    ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
2278
    qemuDomainObjExitMonitor(driver, vm);
2279 2280 2281

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
2282 2283 2284 2285
        vm = NULL;

cleanup:
    if (vm)
2286
        virObjectUnlock(vm);
2287 2288 2289
    return ret;
}

2290 2291
static int qemuDomainGetInfo(virDomainPtr dom,
                             virDomainInfoPtr info)
2292
{
2293
    virQEMUDriverPtr driver = dom->conn->privateData;
2294 2295
    virDomainObjPtr vm;
    int ret = -1;
2296
    int err;
2297
    unsigned long long balloon;
2298

2299
    if (!(vm = qemuDomObjFromDomain(dom)))
2300
        goto cleanup;
D
Daniel P. Berrange 已提交
2301

J
Jiri Denemark 已提交
2302
    info->state = virDomainObjGetState(vm, NULL);
D
Daniel P. Berrange 已提交
2303

D
Daniel P. Berrange 已提交
2304
    if (!virDomainObjIsActive(vm)) {
2305
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
2306
    } else {
2307
        if (qemuGetProcessInfo(&(info->cpuTime), NULL, NULL, vm->pid, 0) < 0) {
2308 2309
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("cannot read cputime for domain"));
2310
            goto cleanup;
D
Daniel P. Berrange 已提交
2311 2312 2313
        }
    }

2314
    info->maxMem = vm->def->mem.max_balloon;
2315

D
Daniel P. Berrange 已提交
2316
    if (virDomainObjIsActive(vm)) {
2317
        qemuDomainObjPrivatePtr priv = vm->privateData;
2318 2319 2320

        if ((vm->def->memballoon != NULL) &&
            (vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_NONE)) {
2321
            info->memory = vm->def->mem.max_balloon;
2322
        } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BALLOON_EVENT)) {
2323
            info->memory = vm->def->mem.cur_balloon;
2324
        } else if (qemuDomainJobAllowed(priv, QEMU_JOB_QUERY)) {
2325
            if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
2326
                goto cleanup;
2327 2328 2329
            if (!virDomainObjIsActive(vm))
                err = 0;
            else {
2330
                qemuDomainObjEnterMonitor(driver, vm);
2331
                err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
2332
                qemuDomainObjExitMonitor(driver, vm);
2333
            }
2334
            if (qemuDomainObjEndJob(driver, vm) == 0) {
2335
                vm = NULL;
2336 2337 2338
                goto cleanup;
            }

2339 2340 2341 2342 2343 2344 2345
            if (err < 0) {
                /* We couldn't get current memory allocation but that's not
                 * a show stopper; we wouldn't get it if there was a job
                 * active either
                 */
                info->memory = vm->def->mem.cur_balloon;
            } else if (err == 0) {
2346
                /* Balloon not supported, so maxmem is always the allocation */
2347
                info->memory = vm->def->mem.max_balloon;
2348
            } else {
2349
                info->memory = balloon;
2350
            }
2351
        } else {
2352
            info->memory = vm->def->mem.cur_balloon;
2353
        }
2354
    } else {
2355
        info->memory = vm->def->mem.cur_balloon;
2356 2357
    }

2358
    info->nrVirtCpu = vm->def->vcpus;
2359 2360 2361
    ret = 0;

cleanup:
2362
    if (vm)
2363
        virObjectUnlock(vm);
2364
    return ret;
D
Daniel P. Berrange 已提交
2365 2366
}

2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377
static int
qemuDomainGetState(virDomainPtr dom,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

2378
    if (!(vm = qemuDomObjFromDomain(dom)))
2379 2380
        goto cleanup;

J
Jiri Denemark 已提交
2381
    *state = virDomainObjGetState(vm, reason);
2382 2383 2384 2385
    ret = 0;

cleanup:
    if (vm)
2386
        virObjectUnlock(vm);
2387 2388 2389
    return ret;
}

2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400
static int
qemuDomainGetControlInfo(virDomainPtr dom,
                          virDomainControlInfoPtr info,
                          unsigned int flags)
{
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(0, -1);

2401
    if (!(vm = qemuDomObjFromDomain(dom)))
2402 2403 2404
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
2405 2406
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2407 2408 2409 2410 2411 2412 2413 2414 2415
        goto cleanup;
    }

    priv = vm->privateData;

    memset(info, 0, sizeof(*info));

    if (priv->monError) {
        info->state = VIR_DOMAIN_CONTROL_ERROR;
2416
    } else if (priv->job.active) {
2417 2418
        if (!priv->monStart) {
            info->state = VIR_DOMAIN_CONTROL_JOB;
2419
            if (virTimeMillisNow(&info->stateTime) < 0)
2420
                goto cleanup;
2421
            info->stateTime -= priv->job.start;
2422 2423
        } else {
            info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
2424
            if (virTimeMillisNow(&info->stateTime) < 0)
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435
                goto cleanup;
            info->stateTime -= priv->monStart;
        }
    } else {
        info->state = VIR_DOMAIN_CONTROL_OK;
    }

    ret = 0;

cleanup:
    if (vm)
2436
        virObjectUnlock(vm);
2437 2438 2439
    return ret;
}

D
Daniel P. Berrange 已提交
2440

2441 2442 2443 2444 2445 2446
/* It would be nice to replace 'Qemud' with 'Qemu' but
 * this magic string is ABI, so it can't be changed
 */
#define QEMU_SAVE_MAGIC   "LibvirtQemudSave"
#define QEMU_SAVE_PARTIAL "LibvirtQemudPart"
#define QEMU_SAVE_VERSION 2
2447

2448
verify(sizeof(QEMU_SAVE_MAGIC) == sizeof(QEMU_SAVE_PARTIAL));
E
Eric Blake 已提交
2449

2450
typedef enum {
2451 2452 2453
    QEMU_SAVE_FORMAT_RAW = 0,
    QEMU_SAVE_FORMAT_GZIP = 1,
    QEMU_SAVE_FORMAT_BZIP2 = 2,
2454 2455
    /*
     * Deprecated by xz and never used as part of a release
2456
     * QEMU_SAVE_FORMAT_LZMA
2457
     */
2458 2459
    QEMU_SAVE_FORMAT_XZ = 3,
    QEMU_SAVE_FORMAT_LZOP = 4,
2460 2461 2462
    /* Note: add new members only at the end.
       These values are used in the on-disk format.
       Do not change or re-use numbers. */
2463

2464
    QEMU_SAVE_FORMAT_LAST
2465
} virQEMUSaveFormat;
2466

2467 2468
VIR_ENUM_DECL(qemuSaveCompression)
VIR_ENUM_IMPL(qemuSaveCompression, QEMU_SAVE_FORMAT_LAST,
2469 2470 2471
              "raw",
              "gzip",
              "bzip2",
2472 2473
              "xz",
              "lzop")
2474

2475 2476 2477
typedef struct _virQEMUSaveHeader virQEMUSaveHeader;
typedef virQEMUSaveHeader *virQEMUSaveHeaderPtr;
struct _virQEMUSaveHeader {
2478
    char magic[sizeof(QEMU_SAVE_MAGIC)-1];
2479 2480 2481 2482 2483
    uint32_t version;
    uint32_t xml_len;
    uint32_t was_running;
    uint32_t compressed;
    uint32_t unused[15];
2484 2485
};

2486
static inline void
2487
bswap_header(virQEMUSaveHeaderPtr hdr) {
2488 2489 2490 2491 2492 2493 2494
    hdr->version = bswap_32(hdr->version);
    hdr->xml_len = bswap_32(hdr->xml_len);
    hdr->was_running = bswap_32(hdr->was_running);
    hdr->compressed = bswap_32(hdr->compressed);
}


2495
/* return -errno on failure, or 0 on success */
E
Eric Blake 已提交
2496
static int
2497
qemuDomainSaveHeader(int fd, const char *path, const char *xml,
2498
                     virQEMUSaveHeaderPtr header)
E
Eric Blake 已提交
2499
{
2500 2501
    int ret = 0;

E
Eric Blake 已提交
2502
    if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
2503
        ret = -errno;
2504 2505 2506
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("failed to write header to domain save file '%s'"),
                       path);
2507 2508 2509
        goto endjob;
    }

E
Eric Blake 已提交
2510
    if (safewrite(fd, xml, header->xml_len) != header->xml_len) {
2511
        ret = -errno;
2512 2513
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("failed to write xml to '%s'"), path);
2514 2515 2516 2517 2518 2519
        goto endjob;
    }
endjob:
    return ret;
}

2520
/* Given a virQEMUSaveFormat compression level, return the name
2521 2522 2523 2524
 * of the program to run, or NULL if no program is needed.  */
static const char *
qemuCompressProgramName(int compress)
{
2525 2526
    return (compress == QEMU_SAVE_FORMAT_RAW ? NULL :
            qemuSaveCompressionTypeToString(compress));
2527 2528
}

2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555
static virCommandPtr
qemuCompressGetCommand(virQEMUSaveFormat compression)
{
    virCommandPtr ret = NULL;
    const char *prog = qemuSaveCompressionTypeToString(compression);

    if (!prog) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("Invalid compressed save format %d"),
                       compression);
        return NULL;
    }

    ret = virCommandNew(prog);
    virCommandAddArg(ret, "-dc");

    switch (compression) {
    case QEMU_SAVE_FORMAT_LZOP:
        virCommandAddArg(ret, "--ignore-warn");
        break;
    default:
        break;
    }

    return ret;
}

E
Eric Blake 已提交
2556 2557 2558
/* Internal function to properly create or open existing files, with
 * ownership affected by qemu driver setup.  */
static int
2559
qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
E
Eric Blake 已提交
2560 2561 2562 2563 2564 2565
             bool *needUnlink, bool *bypassSecurityDriver)
{
    struct stat sb;
    bool is_reg = true;
    bool need_unlink = false;
    bool bypass_security = false;
L
Laine Stump 已提交
2566
    unsigned int vfoflags = 0;
E
Eric Blake 已提交
2567
    int fd = -1;
2568
    int path_shared = virStorageFileIsSharedFS(path);
E
Eric Blake 已提交
2569 2570
    uid_t uid = getuid();
    gid_t gid = getgid();
2571
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
E
Eric Blake 已提交
2572 2573 2574 2575 2576 2577

    /* path might be a pre-existing block dev, in which case
     * we need to skip the create step, and also avoid unlink
     * in the failure case */
    if (oflags & O_CREAT) {
        need_unlink = true;
2578 2579 2580

        /* Don't force chown on network-shared FS
         * as it is likely to fail. */
2581
        if (path_shared <= 0 || cfg->dynamicOwnership)
2582 2583
            vfoflags |= VIR_FILE_OPEN_FORCE_OWNER;

E
Eric Blake 已提交
2584 2585 2586 2587 2588
        if (stat(path, &sb) == 0) {
            is_reg = !!S_ISREG(sb.st_mode);
            /* If the path is regular file which exists
             * already and dynamic_ownership is off, we don't
             * want to change it's ownership, just open it as-is */
2589
            if (is_reg && !cfg->dynamicOwnership) {
E
Eric Blake 已提交
2590 2591 2592 2593 2594 2595 2596 2597
                uid = sb.st_uid;
                gid = sb.st_gid;
            }
        }
    }

    /* First try creating the file as root */
    if (!is_reg) {
2598 2599 2600
        if ((fd = open(path, oflags & ~O_CREAT)) < 0) {
            fd = -errno;
            goto error;
E
Eric Blake 已提交
2601 2602
        }
    } else {
L
Laine Stump 已提交
2603 2604
        if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR, uid, gid,
                                vfoflags | VIR_FILE_OPEN_NOFORK)) < 0) {
E
Eric Blake 已提交
2605 2606 2607
            /* If we failed as root, and the error was permission-denied
               (EACCES or EPERM), assume it's on a network-connected share
               where root access is restricted (eg, root-squashed NFS). If the
2608
               qemu user (cfg->user) is non-root, just set a flag to
E
Eric Blake 已提交
2609 2610
               bypass security driver shenanigans, and retry the operation
               after doing setuid to qemu user */
2611 2612
            if ((fd != -EACCES && fd != -EPERM) || cfg->user == getuid())
                goto error;
E
Eric Blake 已提交
2613 2614

            /* On Linux we can also verify the FS-type of the directory. */
2615
            switch (path_shared) {
E
Eric Blake 已提交
2616
                case 1:
2617 2618 2619 2620
                    /* it was on a network share, so we'll continue
                     * as outlined above
                     */
                    break;
E
Eric Blake 已提交
2621 2622

                case -1:
2623 2624 2625 2626 2627 2628 2629
                    virReportSystemError(-fd, oflags & O_CREAT
                                         ? _("Failed to create file "
                                             "'%s': couldn't determine fs type")
                                         : _("Failed to open file "
                                             "'%s': couldn't determine fs type"),
                                         path);
                    goto cleanup;
E
Eric Blake 已提交
2630 2631 2632

                case 0:
                default:
2633 2634
                    /* local file - log the error returned by virFileOpenAs */
                    goto error;
E
Eric Blake 已提交
2635 2636
            }

2637
            /* Retry creating the file as cfg->user */
E
Eric Blake 已提交
2638 2639 2640

            if ((fd = virFileOpenAs(path, oflags,
                                    S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
2641
                                    cfg->user, cfg->group,
L
Laine Stump 已提交
2642
                                    vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
2643 2644 2645
                virReportSystemError(-fd, oflags & O_CREAT
                                     ? _("Error from child process creating '%s'")
                                     : _("Error from child process opening '%s'"),
E
Eric Blake 已提交
2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661
                                     path);
                goto cleanup;
            }

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

            bypass_security = true;
        }
    }
cleanup:
    if (needUnlink)
        *needUnlink = need_unlink;
    if (bypassSecurityDriver)
        *bypassSecurityDriver = bypass_security;
2662
    virObjectUnref(cfg);
E
Eric Blake 已提交
2663
    return fd;
2664 2665 2666 2667 2668 2669 2670

error:
    virReportSystemError(-fd, oflags & O_CREAT
                         ? _("Failed to create file '%s'")
                         : _("Failed to open file '%s'"),
                         path);
    goto cleanup;
E
Eric Blake 已提交
2671 2672
}

2673 2674 2675
/* Helper function to execute a migration to file with a correct save header
 * the caller needs to make sure that the processors are stopped and do all other
 * actions besides saving memory */
2676
static int
2677
qemuDomainSaveMemory(virQEMUDriverPtr driver,
2678 2679
                     virDomainObjPtr vm,
                     const char *path,
2680
                     const char *domXML,
2681 2682 2683 2684
                     int compressed,
                     bool was_running,
                     unsigned int flags,
                     enum qemuDomainAsyncJob asyncJob)
2685
{
2686
    virQEMUSaveHeader header;
2687
    bool bypassSecurityDriver = false;
E
Eric Blake 已提交
2688
    bool needUnlink = false;
2689
    int ret = -1;
2690
    int fd = -1;
2691
    int directFlag = 0;
J
Jiri Denemark 已提交
2692
    virFileWrapperFdPtr wrapperFd = NULL;
2693
    unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
2694 2695 2696
    unsigned long long pad;
    unsigned long long offset;
    size_t len;
2697
    char *xml = NULL;
2698

2699
    memset(&header, 0, sizeof(header));
2700 2701
    memcpy(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic));
    header.version = QEMU_SAVE_VERSION;
2702
    header.was_running = was_running ? 1 : 0;
2703

2704
    header.compressed = compressed;
2705

2706
    len = strlen(domXML) + 1;
2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719
    offset = sizeof(header) + len;

    /* Due to way we append QEMU state on our header with dd,
     * we need to ensure there's a 512 byte boundary. Unfortunately
     * we don't have an explicit offset in the header, so we fake
     * it by padding the XML string with NUL bytes.  Additionally,
     * we want to ensure that virDomainSaveImageDefineXML can supply
     * slightly larger XML, so we add a miminum padding prior to
     * rounding out to page boundaries.
     */
    pad = 1024;
    pad += (QEMU_MONITOR_MIGRATE_TO_FILE_BS -
            ((offset + pad) % QEMU_MONITOR_MIGRATE_TO_FILE_BS));
2720
    if (VIR_ALLOC_N(xml, len + pad) < 0) {
2721
        virReportOOMError();
2722
        goto cleanup;
2723
    }
2724 2725
    strcpy(xml, domXML);

2726 2727
    offset += pad;
    header.xml_len = len;
2728

2729
    /* Obtain the file handle.  */
2730 2731
    if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) {
        wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
2732 2733
        directFlag = virFileDirectFdFlag();
        if (directFlag < 0) {
2734 2735
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("bypass cache unsupported by this system"));
E
Eric Blake 已提交
2736
            goto cleanup;
2737
        }
2738
    }
E
Eric Blake 已提交
2739 2740 2741
    fd = qemuOpenFile(driver, path, O_WRONLY | O_TRUNC | O_CREAT | directFlag,
                      &needUnlink, &bypassSecurityDriver);
    if (fd < 0)
2742 2743
        goto cleanup;

2744
    if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
2745
        goto cleanup;
2746

2747
    /* Write header to file, followed by XML */
2748 2749
    if (qemuDomainSaveHeader(fd, path, xml, &header) < 0)
        goto cleanup;
2750

2751
    /* Perform the migration */
2752
    if (qemuMigrationToFile(driver, vm, fd, offset, path,
2753
                            qemuCompressProgramName(compressed),
E
Eric Blake 已提交
2754
                            bypassSecurityDriver,
2755 2756
                            asyncJob) < 0)
        goto cleanup;
E
Eric Blake 已提交
2757

2758 2759 2760 2761 2762 2763 2764 2765
    /* Touch up file header to mark image complete. */

    /* Reopen the file to touch up the header, since we aren't set
     * up to seek backwards on wrapperFd.  The reopened fd will
     * trigger a single page of file system cache pollution, but
     * that's acceptable.  */
    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno, _("unable to close %s"), path);
2766
        goto cleanup;
E
Eric Blake 已提交
2767
    }
2768

2769
    if (virFileWrapperFdClose(wrapperFd) < 0)
2770 2771 2772 2773
        goto cleanup;

    if ((fd = qemuOpenFile(driver, path, O_WRONLY, NULL, NULL)) < 0)
        goto cleanup;
2774

2775
    memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic));
2776

E
Eric Blake 已提交
2777 2778
    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
        virReportSystemError(errno, _("unable to write %s"), path);
2779
        goto cleanup;
E
Eric Blake 已提交
2780
    }
2781

2782 2783
    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno, _("unable to close %s"), path);
2784
        goto cleanup;
2785 2786
    }

2787 2788
    ret = 0;

2789 2790 2791
cleanup:
    VIR_FORCE_CLOSE(fd);
    virFileWrapperFdFree(wrapperFd);
2792
    VIR_FREE(xml);
2793 2794 2795 2796 2797 2798 2799

    if (ret != 0 && needUnlink)
        unlink(path);

    return ret;
}

2800
/* The vm must be active + locked. Vm will be unlocked and
2801 2802 2803 2804 2805
 * potentially free'd after this returns (eg transient VMs are freed
 * shutdown). So 'vm' must not be referenced by the caller after
 * this returns (whether returning success or failure).
 */
static int
2806
qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
2807 2808 2809 2810 2811 2812 2813 2814 2815
                       virDomainObjPtr vm, const char *path,
                       int compressed, const char *xmlin, unsigned int flags)
{
    char *xml = NULL;
    bool was_running = false;
    int ret = -1;
    int rc;
    virDomainEventPtr event = NULL;
    qemuDomainObjPrivatePtr priv = vm->privateData;
2816 2817 2818 2819
    virCapsPtr caps;

    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;
2820

2821
    if (!qemuMigrationIsAllowed(driver, vm, vm->def, false))
2822 2823
        goto cleanup;

2824
    if (qemuDomainObjBeginAsyncJob(driver, vm,
2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856
                                             QEMU_ASYNC_JOB_SAVE) < 0)

    memset(&priv->job.info, 0, sizeof(priv->job.info));
    priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;

    /* Pause */
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
        was_running = true;
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
                                QEMU_ASYNC_JOB_SAVE) < 0)
            goto endjob;

        if (!virDomainObjIsActive(vm)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
            goto endjob;
        }
    }

   /* libvirt.c already guaranteed these two flags are exclusive.  */
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
        was_running = true;
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
        was_running = false;

    /* Get XML for the domain.  Restore needs only the inactive xml,
     * including secure.  We should get the same result whether xmlin
     * is NULL or whether it was the live xml of the domain moments
     * before.  */
    if (xmlin) {
        virDomainDefPtr def = NULL;

2857
        if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt,
2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880
                                            QEMU_EXPECTED_VIRT_TYPES,
                                            VIR_DOMAIN_XML_INACTIVE))) {
            goto endjob;
        }
        if (!virDomainDefCheckABIStability(vm->def, def)) {
            virDomainDefFree(def);
            goto endjob;
        }
        xml = qemuDomainDefFormatLive(driver, def, true, true);
    } else {
        xml = qemuDomainDefFormatLive(driver, vm->def, true, true);
    }
    if (!xml) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("failed to get domain xml"));
        goto endjob;
    }

    ret = qemuDomainSaveMemory(driver, vm, path, xml, compressed,
                               was_running, flags, QEMU_ASYNC_JOB_SAVE);
    if (ret < 0)
        goto endjob;

2881
    /* Shut it down */
2882
    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED, 0);
2883
    virDomainAuditStop(vm, "saved");
2884 2885 2886
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2887
    if (!vm->persistent) {
2888
        if (qemuDomainObjEndAsyncJob(driver, vm) > 0)
2889
            qemuDomainRemoveInactive(driver, vm);
2890 2891
        vm = NULL;
    }
2892

2893
endjob:
2894
    if (vm) {
2895
        if (ret != 0) {
2896
            if (was_running && virDomainObjIsActive(vm)) {
J
Jiri Denemark 已提交
2897
                rc = qemuProcessStartCPUs(driver, vm, dom->conn,
2898 2899
                                          VIR_DOMAIN_RUNNING_SAVE_CANCELED,
                                          QEMU_ASYNC_JOB_SAVE);
2900
                if (rc < 0) {
2901
                    VIR_WARN("Unable to resume guest CPUs after save failure");
2902 2903 2904 2905
                    event = virDomainEventNewFromObj(vm,
                                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                                     VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
                }
2906
            }
2907
        }
2908
        if (qemuDomainObjEndAsyncJob(driver, vm) == 0)
2909
            vm = NULL;
2910
    }
2911

2912 2913
cleanup:
    VIR_FREE(xml);
2914 2915
    if (event)
        qemuDomainEventQueue(driver, event);
2916
    if (vm)
2917
        virObjectUnlock(vm);
2918
    virObjectUnref(caps);
2919
    return ret;
D
Daniel P. Berrange 已提交
2920 2921
}

2922
/* Returns true if a compression program is available in PATH */
2923
static bool qemuCompressProgramAvailable(virQEMUSaveFormat compress)
2924 2925 2926 2927
{
    const char *prog;
    char *c;

2928
    if (compress == QEMU_SAVE_FORMAT_RAW)
2929
        return true;
2930
    prog = qemuSaveCompressionTypeToString(compress);
2931 2932 2933 2934 2935 2936 2937
    c = virFindFileInPath(prog);
    if (!c)
        return false;
    VIR_FREE(c);
    return true;
}

2938 2939 2940
static int
qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
                    unsigned int flags)
2941
{
2942
    virQEMUDriverPtr driver = dom->conn->privateData;
2943
    int compressed;
2944 2945
    int ret = -1;
    virDomainObjPtr vm = NULL;
2946
    virQEMUDriverConfigPtr cfg = NULL;
2947

2948 2949 2950
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
2951

2952 2953
    cfg = virQEMUDriverGetConfig(driver);
    if (cfg->saveImageFormat == NULL)
2954
        compressed = QEMU_SAVE_FORMAT_RAW;
2955
    else {
2956
        compressed = qemuSaveCompressionTypeFromString(cfg->saveImageFormat);
2957
        if (compressed < 0) {
2958 2959 2960
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("Invalid save image format specified "
                                   "in configuration file"));
2961
            goto cleanup;
2962
        }
2963
        if (!qemuCompressProgramAvailable(compressed)) {
2964 2965 2966
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("Compression program for image format "
                                   "in configuration file isn't available"));
2967
            goto cleanup;
2968
        }
2969 2970
    }

2971
    if (!(vm = qemuDomObjFromDomain(dom)))
2972 2973
        goto cleanup;

2974
    if (!virDomainObjIsActive(vm)) {
2975 2976
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2977 2978 2979
        goto cleanup;
    }

2980
    ret = qemuDomainSaveInternal(driver, dom, vm, path, compressed,
2981
                                 dxml, flags);
2982
    vm = NULL;
2983 2984 2985

cleanup:
    if (vm)
2986
        virObjectUnlock(vm);
2987
    virObjectUnref(cfg);
2988
    return ret;
2989 2990
}

2991 2992 2993 2994 2995 2996
static int
qemuDomainSave(virDomainPtr dom, const char *path)
{
    return qemuDomainSaveFlags(dom, path, NULL, 0);
}

2997
static char *
2998 2999
qemuDomainManagedSavePath(virQEMUDriverPtr driver, virDomainObjPtr vm)
{
3000
    char *ret;
3001
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3002

3003
    if (virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name) < 0) {
3004
        virReportOOMError();
3005
        virObjectUnref(cfg);
3006
        return NULL;
3007 3008
    }

3009
    virObjectUnref(cfg);
3010
    return ret;
3011 3012 3013 3014 3015
}

static int
qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
3016
    virQEMUDriverPtr driver = dom->conn->privateData;
3017
    virDomainObjPtr vm;
3018 3019 3020 3021
    char *name = NULL;
    int ret = -1;
    int compressed;

3022 3023 3024
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
3025

3026
    if (!(vm = qemuDomObjFromDomain(dom)))
3027
        return -1;
3028

3029
    if (!virDomainObjIsActive(vm)) {
3030 3031
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
3032 3033
        goto cleanup;
    }
3034
    if (!vm->persistent) {
3035 3036
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
3037 3038
        goto cleanup;
    }
3039

3040
    if (!(name = qemuDomainManagedSavePath(driver, vm)))
3041
        goto cleanup;
3042

3043
    VIR_INFO("Saving state to %s", name);
3044

3045
    compressed = QEMU_SAVE_FORMAT_RAW;
3046 3047 3048 3049
    if ((ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed,
                                      NULL, flags)) == 0)
        vm->hasManagedSave = true;

3050
    vm = NULL;
3051 3052 3053

cleanup:
    if (vm)
3054
        virObjectUnlock(vm);
3055 3056 3057
    VIR_FREE(name);

    return ret;
3058 3059
}

3060 3061
static int
qemuDomainManagedSaveLoad(virDomainObjPtr vm,
3062 3063
                          void *opaque)
{
3064
    virQEMUDriverPtr driver = opaque;
3065
    char *name;
3066
    int ret = -1;
3067

3068
    virObjectLock(vm);
3069 3070 3071 3072 3073 3074

    if (!(name = qemuDomainManagedSavePath(driver, vm)))
        goto cleanup;

    vm->hasManagedSave = virFileExists(name);

3075
    ret = 0;
3076
cleanup:
3077
    virObjectUnlock(vm);
3078
    VIR_FREE(name);
3079
    return ret;
3080 3081
}

3082

3083 3084 3085 3086
static int
qemuDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
3087
    int ret;
3088

3089
    virCheckFlags(0, -1);
3090

3091 3092
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
3093

3094
    ret = vm->hasManagedSave;
3095
    virObjectUnlock(vm);
3096 3097 3098 3099 3100 3101
    return ret;
}

static int
qemuDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
3102
    virQEMUDriverPtr driver = dom->conn->privateData;
3103
    virDomainObjPtr vm;
3104 3105 3106
    int ret = -1;
    char *name = NULL;

3107
    virCheckFlags(0, -1);
3108

3109
    if (!(vm = qemuDomObjFromDomain(dom)))
3110
        return -1;
3111

3112
    if (!(name = qemuDomainManagedSavePath(driver, vm)))
3113 3114
        goto cleanup;

3115 3116 3117 3118 3119 3120 3121
    if (unlink(name) < 0) {
        virReportSystemError(errno,
                             _("Failed to remove managed save file '%s'"),
                             name);
        goto cleanup;
    }

3122
    vm->hasManagedSave = false;
3123
    ret = 0;
3124 3125 3126

cleanup:
    VIR_FREE(name);
3127
    virObjectUnlock(vm);
3128 3129
    return ret;
}
D
Daniel P. Berrange 已提交
3130

3131
static int qemuDumpToFd(virQEMUDriverPtr driver, virDomainObjPtr vm,
3132 3133 3134 3135 3136
                        int fd, enum qemuDomainAsyncJob asyncJob)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int ret = -1;

3137
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY)) {
3138
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3139
                       _("dump-guest-memory is not supported"));
3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151
        return -1;
    }

    if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
                                          fd) < 0)
        return -1;

    priv->job.dump_memory_only = true;

    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
        return -1;

3152
    ret = qemuMonitorDumpToFd(priv->mon, fd);
3153
    qemuDomainObjExitMonitor(driver, vm);
3154 3155 3156 3157

    return ret;
}

3158
static int
3159
doCoreDump(virQEMUDriverPtr driver,
3160 3161
           virDomainObjPtr vm,
           const char *path,
3162
           virQEMUSaveFormat compress,
3163
           unsigned int dump_flags)
H
Hu Tao 已提交
3164 3165 3166
{
    int fd = -1;
    int ret = -1;
J
Jiri Denemark 已提交
3167
    virFileWrapperFdPtr wrapperFd = NULL;
3168
    int directFlag = 0;
3169
    unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
H
Hu Tao 已提交
3170 3171

    /* Create an empty file with appropriate ownership.  */
3172
    if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
3173
        flags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
3174 3175
        directFlag = virFileDirectFdFlag();
        if (directFlag < 0) {
3176 3177
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("bypass cache unsupported by this system"));
3178 3179 3180
            goto cleanup;
        }
    }
E
Eric Blake 已提交
3181 3182 3183 3184 3185 3186
    /* Core dumps usually imply last-ditch analysis efforts are
     * desired, so we intentionally do not unlink even if a file was
     * created.  */
    if ((fd = qemuOpenFile(driver, path,
                           O_CREAT | O_TRUNC | O_WRONLY | directFlag,
                           NULL, NULL)) < 0)
H
Hu Tao 已提交
3187 3188
        goto cleanup;

3189
    if (!(wrapperFd = virFileWrapperFdNew(&fd, path, flags)))
3190 3191
        goto cleanup;

3192 3193 3194 3195 3196 3197 3198 3199 3200
    if (dump_flags & VIR_DUMP_MEMORY_ONLY) {
        ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP);
    } else {
        ret = qemuMigrationToFile(driver, vm, fd, 0, path,
                                  qemuCompressProgramName(compress), false,
                                  QEMU_ASYNC_JOB_DUMP);
    }

    if (ret < 0)
3201 3202
        goto cleanup;

H
Hu Tao 已提交
3203 3204
    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno,
3205
                             _("unable to close file %s"),
H
Hu Tao 已提交
3206 3207 3208
                             path);
        goto cleanup;
    }
J
Jiri Denemark 已提交
3209
    if (virFileWrapperFdClose(wrapperFd) < 0)
3210
        goto cleanup;
H
Hu Tao 已提交
3211

3212
    ret = 0;
H
Hu Tao 已提交
3213 3214

cleanup:
3215
    VIR_FORCE_CLOSE(fd);
3216
    if (ret != 0)
H
Hu Tao 已提交
3217
        unlink(path);
3218
    virFileWrapperFdFree(wrapperFd);
H
Hu Tao 已提交
3219 3220 3221
    return ret;
}

3222
static virQEMUSaveFormat
3223
getCompressionType(virQEMUDriverPtr driver)
3224
{
3225 3226
    int ret = QEMU_SAVE_FORMAT_RAW;
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3227

3228 3229 3230 3231
    /*
     * We reuse "save" flag for "dump" here. Then, we can support the same
     * format in "save" and "dump".
     */
3232 3233
    if (cfg->dumpImageFormat) {
        ret = qemuSaveCompressionTypeFromString(cfg->dumpImageFormat);
3234 3235 3236
        /* Use "raw" as the format if the specified format is not valid,
         * or the compress program is not available.
         */
3237
        if (ret < 0) {
3238 3239
            VIR_WARN("%s", _("Invalid dump image format specified in "
                             "configuration file, using raw"));
3240 3241
            ret = QEMU_SAVE_FORMAT_RAW;
            goto cleanup;
3242
        }
3243
        if (!qemuCompressProgramAvailable(ret)) {
3244 3245 3246
            VIR_WARN("%s", _("Compression program for dump image format "
                             "in configuration file isn't available, "
                             "using raw"));
3247 3248
            ret = QEMU_SAVE_FORMAT_RAW;
            goto cleanup;
3249
        }
3250
    }
3251 3252 3253
cleanup:
    virObjectUnref(cfg);
    return ret;
3254 3255
}

3256 3257 3258
static int qemuDomainCoreDump(virDomainPtr dom,
                              const char *path,
                              unsigned int flags)
3259
{
3260
    virQEMUDriverPtr driver = dom->conn->privateData;
3261
    virDomainObjPtr vm;
M
Michal Privoznik 已提交
3262
    qemuDomainObjPrivatePtr priv;
3263
    int resume = 0, paused = 0;
H
Hu Tao 已提交
3264
    int ret = -1;
3265 3266
    virDomainEventPtr event = NULL;

M
Michal Privoznik 已提交
3267
    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
3268 3269
                  VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET |
                  VIR_DUMP_MEMORY_ONLY, -1);
3270

3271 3272
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
P
Paolo Bonzini 已提交
3273

3274 3275
    if (qemuDomainObjBeginAsyncJob(driver, vm,
                                   QEMU_ASYNC_JOB_DUMP) < 0)
3276 3277
        goto cleanup;

D
Daniel P. Berrange 已提交
3278
    if (!virDomainObjIsActive(vm)) {
3279 3280
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
3281
        goto endjob;
P
Paolo Bonzini 已提交
3282 3283
    }

P
Paolo Bonzini 已提交
3284 3285
    /* Migrate will always stop the VM, so the resume condition is
       independent of whether the stop command is issued.  */
J
Jiri Denemark 已提交
3286
    resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
P
Paolo Bonzini 已提交
3287 3288

    /* Pause domain for non-live dump */
J
Jiri Denemark 已提交
3289 3290
    if (!(flags & VIR_DUMP_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
3291 3292
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_DUMP,
                                QEMU_ASYNC_JOB_DUMP) < 0)
3293
            goto endjob;
P
Paolo Bonzini 已提交
3294
        paused = 1;
3295 3296

        if (!virDomainObjIsActive(vm)) {
3297 3298
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
3299 3300
            goto endjob;
        }
P
Paolo Bonzini 已提交
3301 3302
    }

3303
    ret = doCoreDump(driver, vm, path, getCompressionType(driver), flags);
3304 3305 3306 3307
    if (ret < 0)
        goto endjob;

    paused = 1;
3308 3309

endjob:
3310
    if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
3311
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, 0);
3312
        virDomainAuditStop(vm, "crashed");
3313 3314 3315 3316 3317
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
    }

P
Paolo Bonzini 已提交
3318 3319 3320
    /* 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.  */
M
Michal Privoznik 已提交
3321 3322 3323 3324
    else if (((resume && paused) || (flags & VIR_DUMP_RESET)) &&
             virDomainObjIsActive(vm)) {
        if ((ret == 0) && (flags & VIR_DUMP_RESET)) {
            priv =  vm->privateData;
3325
            qemuDomainObjEnterMonitor(driver, vm);
M
Michal Privoznik 已提交
3326
            ret = qemuMonitorSystemReset(priv->mon);
3327
            qemuDomainObjExitMonitor(driver, vm);
M
Michal Privoznik 已提交
3328 3329 3330 3331 3332
        }

        if (resume && qemuProcessStartCPUs(driver, vm, dom->conn,
                                           VIR_DOMAIN_RUNNING_UNPAUSED,
                                           QEMU_ASYNC_JOB_DUMP) < 0) {
3333 3334 3335
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_SUSPENDED,
                                             VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
3336
            if (virGetLastError() == NULL)
3337 3338
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("resuming after dump failed"));
P
Paolo Bonzini 已提交
3339 3340
        }
    }
3341

3342
    if (qemuDomainObjEndAsyncJob(driver, vm) == 0)
3343
        vm = NULL;
3344
    else if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) {
3345
        qemuDomainRemoveInactive(driver, vm);
3346 3347
        vm = NULL;
    }
3348 3349

cleanup:
P
Paolo Bonzini 已提交
3350
    if (vm)
3351
        virObjectUnlock(vm);
3352 3353
    if (event)
        qemuDomainEventQueue(driver, event);
P
Paolo Bonzini 已提交
3354 3355 3356
    return ret;
}

3357 3358 3359 3360
static char *
qemuDomainScreenshot(virDomainPtr dom,
                     virStreamPtr st,
                     unsigned int screen,
E
Eric Blake 已提交
3361
                     unsigned int flags)
3362
{
3363
    virQEMUDriverPtr driver = dom->conn->privateData;
3364 3365 3366 3367 3368
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    char *tmp = NULL;
    int tmp_fd = -1;
    char *ret = NULL;
E
Eric Blake 已提交
3369
    bool unlink_tmp = false;
3370
    virQEMUDriverConfigPtr cfg = NULL;
3371

E
Eric Blake 已提交
3372 3373
    virCheckFlags(0, NULL);

3374
    if (!(vm = qemuDomObjFromDomain(dom)))
3375 3376 3377
        goto cleanup;

    priv = vm->privateData;
3378
    cfg = virQEMUDriverGetConfig(driver);
3379

3380
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
3381 3382 3383
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
3384 3385
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
3386 3387 3388 3389 3390 3391
        goto endjob;
    }

    /* Well, even if qemu allows multiple graphic cards, heads, whatever,
     * screenshot command does not */
    if (screen) {
3392 3393 3394
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("currently is supported only taking "
                               "screenshots of screen ID 0"));
3395 3396 3397
        goto endjob;
    }

3398
    if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", cfg->cacheDir) < 0) {
3399 3400 3401 3402
        virReportOOMError();
        goto endjob;
    }

3403 3404
    if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
        virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
3405 3406
        goto endjob;
    }
E
Eric Blake 已提交
3407
    unlink_tmp = true;
3408

3409
    virSecurityManagerSetSavedStateLabel(qemu_driver->securityManager, vm->def, tmp);
3410

3411
    qemuDomainObjEnterMonitor(driver, vm);
3412
    if (qemuMonitorScreendump(priv->mon, tmp) < 0) {
3413
        qemuDomainObjExitMonitor(driver, vm);
3414 3415
        goto endjob;
    }
3416
    qemuDomainObjExitMonitor(driver, vm);
3417 3418 3419 3420 3421 3422

    if (VIR_CLOSE(tmp_fd) < 0) {
        virReportSystemError(errno, _("unable to close %s"), tmp);
        goto endjob;
    }

E
Eric Blake 已提交
3423
    if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
3424 3425
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("unable to open stream"));
3426 3427 3428 3429 3430 3431 3432
        goto endjob;
    }

    ret = strdup("image/x-portable-pixmap");

endjob:
    VIR_FORCE_CLOSE(tmp_fd);
E
Eric Blake 已提交
3433 3434
    if (unlink_tmp)
        unlink(tmp);
E
Eric Blake 已提交
3435
    VIR_FREE(tmp);
3436

3437
    if (qemuDomainObjEndJob(driver, vm) == 0)
3438 3439 3440 3441
        vm = NULL;

cleanup:
    if (vm)
3442
        virObjectUnlock(vm);
3443
    virObjectUnref(cfg);
3444 3445 3446
    return ret;
}

H
Hu Tao 已提交
3447 3448 3449
static void processWatchdogEvent(void *data, void *opaque)
{
    int ret;
3450
    struct qemuDomainWatchdogEvent *wdEvent = data;
3451
    virQEMUDriverPtr driver = opaque;
3452
    virQEMUDriverConfigPtr cfg;
H
Hu Tao 已提交
3453

3454
    virObjectLock(wdEvent->vm);
3455
    cfg = virQEMUDriverGetConfig(driver);
W
Wen Congyang 已提交
3456

H
Hu Tao 已提交
3457 3458 3459 3460
    switch (wdEvent->action) {
    case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
        {
            char *dumpfile;
3461
            unsigned int flags = 0;
H
Hu Tao 已提交
3462

E
Eric Blake 已提交
3463
            if (virAsprintf(&dumpfile, "%s/%s-%u",
3464
                            cfg->autoDumpPath,
H
Hu Tao 已提交
3465
                            wdEvent->vm->def->name,
E
Eric Blake 已提交
3466 3467
                            (unsigned int)time(NULL)) < 0) {
                virReportOOMError();
W
Wen Congyang 已提交
3468
                goto unlock;
E
Eric Blake 已提交
3469
            }
H
Hu Tao 已提交
3470

3471
            if (qemuDomainObjBeginAsyncJob(driver, wdEvent->vm,
3472
                                                     QEMU_ASYNC_JOB_DUMP) < 0) {
W
Wen Congyang 已提交
3473 3474 3475
                VIR_FREE(dumpfile);
                goto unlock;
            }
H
Hu Tao 已提交
3476 3477

            if (!virDomainObjIsActive(wdEvent->vm)) {
3478 3479
                virReportError(VIR_ERR_OPERATION_INVALID,
                               "%s", _("domain is not running"));
W
Wen Congyang 已提交
3480 3481
                VIR_FREE(dumpfile);
                goto endjob;
H
Hu Tao 已提交
3482 3483
            }

3484
            flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
3485
            ret = doCoreDump(driver, wdEvent->vm, dumpfile,
3486
                             getCompressionType(driver), flags);
H
Hu Tao 已提交
3487
            if (ret < 0)
3488 3489
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("Dump failed"));
H
Hu Tao 已提交
3490

J
Jiri Denemark 已提交
3491
            ret = qemuProcessStartCPUs(driver, wdEvent->vm, NULL,
3492 3493
                                       VIR_DOMAIN_RUNNING_UNPAUSED,
                                       QEMU_ASYNC_JOB_DUMP);
H
Hu Tao 已提交
3494 3495

            if (ret < 0)
3496 3497
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("Resuming after dump failed"));
H
Hu Tao 已提交
3498 3499 3500 3501

            VIR_FREE(dumpfile);
        }
        break;
W
Wen Congyang 已提交
3502 3503
    default:
        goto unlock;
H
Hu Tao 已提交
3504 3505
    }

W
Wen Congyang 已提交
3506 3507 3508 3509
endjob:
    /* Safe to ignore value since ref count was incremented in
     * qemuProcessHandleWatchdog().
     */
3510
    ignore_value(qemuDomainObjEndAsyncJob(driver, wdEvent->vm));
W
Wen Congyang 已提交
3511 3512

unlock:
3513
    virObjectUnlock(wdEvent->vm);
3514
    virObjectUnref(wdEvent->vm);
H
Hu Tao 已提交
3515
    VIR_FREE(wdEvent);
3516
    virObjectUnref(cfg);
H
Hu Tao 已提交
3517
}
P
Paolo Bonzini 已提交
3518

3519
static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
3520 3521
                                  virDomainObjPtr vm,
                                  unsigned int nvcpus)
3522 3523
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
3524
    int i, rc = 1;
3525
    int ret = -1;
3526
    int oldvcpus = vm->def->vcpus;
E
Eric Blake 已提交
3527
    int vcpus = oldvcpus;
3528 3529
    pid_t *cpupids = NULL;
    int ncpupids;
3530
    virCgroupPtr cgroup_vcpu = NULL;
3531

3532
    qemuDomainObjEnterMonitor(driver, vm);
3533

3534 3535 3536
    /* We need different branches here, because we want to offline
     * in reverse order to onlining, so any partial fail leaves us in a
     * reasonably sensible state */
E
Eric Blake 已提交
3537
    if (nvcpus > vcpus) {
3538
        for (i = vcpus; i < nvcpus; i++) {
3539 3540 3541 3542 3543 3544 3545
            /* Online new CPU */
            rc = qemuMonitorSetCPU(priv->mon, i, 1);
            if (rc == 0)
                goto unsupported;
            if (rc < 0)
                goto cleanup;

E
Eric Blake 已提交
3546
            vcpus++;
3547 3548
        }
    } else {
3549
        for (i = vcpus - 1; i >= nvcpus; i--) {
3550 3551 3552 3553 3554 3555 3556
            /* Offline old CPU */
            rc = qemuMonitorSetCPU(priv->mon, i, 0);
            if (rc == 0)
                goto unsupported;
            if (rc < 0)
                goto cleanup;

E
Eric Blake 已提交
3557
            vcpus--;
3558 3559 3560
        }
    }

3561 3562
    /* hotplug succeeded */

3563 3564
    ret = 0;

3565 3566 3567 3568 3569 3570 3571 3572 3573 3574
    /* After hotplugging the CPUs we need to re-detect threads corresponding
     * to the virtual CPUs. Some older versions don't provide the thread ID
     * or don't have the "info cpus" command (and they don't support multiple
     * CPUs anyways), so errors in the re-detection will not be treated
     * fatal */
    if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) <= 0) {
        virResetLastError();
        goto cleanup;
    }

3575 3576 3577 3578 3579 3580 3581 3582 3583
    /* check if hotplug has failed */
    if (vcpus < oldvcpus && ncpupids == oldvcpus) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("qemu didn't unplug the vCPUs properly"));
        vcpus = oldvcpus;
        ret = -1;
        goto cleanup;
    }

3584
    if (ncpupids != vcpus) {
3585 3586 3587 3588
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("got wrong number of vCPU pids from QEMU monitor. "
                         "got %d, wanted %d"),
                       ncpupids, vcpus);
3589 3590 3591 3592
        ret = -1;
        goto cleanup;
    }

3593 3594
    if (nvcpus > oldvcpus) {
        for (i = oldvcpus; i < nvcpus; i++) {
3595
            if (priv->cgroup) {
3596
                int rv = -1;
3597
                /* Create cgroup for the onlined vcpu */
3598
                rv = virCgroupNewVcpu(priv->cgroup, i, true, &cgroup_vcpu);
3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615
                if (rv < 0) {
                    virReportSystemError(-rv,
                                         _("Unable to create vcpu cgroup for %s(vcpu:"
                                           " %d)"),
                                         vm->def->name, i);
                    goto cleanup;
                }

                /* Add vcpu thread to the cgroup */
                rv = virCgroupAddTask(cgroup_vcpu, cpupids[i]);
                if (rv < 0) {
                    virReportSystemError(-rv,
                                         _("unable to add vcpu %d task %d to cgroup"),
                                         i, cpupids[i]);
                    virCgroupRemove(cgroup_vcpu);
                    goto cleanup;
                }
3616
            }
3617

3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640
            /* Inherit def->cpuset */
            if (vm->def->cpumask) {
                /* vm->def->cputune.vcpupin can't be NULL if
                 * vm->def->cpumask is not NULL.
                 */
                virDomainVcpuPinDefPtr vcpupin = NULL;

                if (VIR_REALLOC_N(vm->def->cputune.vcpupin,
                                  vm->def->cputune.nvcpupin + 1) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }

                if (VIR_ALLOC(vcpupin) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }

                vcpupin->cpumask = virBitmapNew(VIR_DOMAIN_CPUMASK_LEN);
                virBitmapCopy(vcpupin->cpumask, vm->def->cpumask);
                vcpupin->vcpuid = i;
                vm->def->cputune.vcpupin[vm->def->cputune.nvcpupin++] = vcpupin;

3641
                if (cgroup_vcpu) {
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651
                    if (qemuSetupCgroupVcpuPin(cgroup_vcpu,
                                               vm->def->cputune.vcpupin,
                                               vm->def->cputune.nvcpupin, i) < 0) {
                        virReportError(VIR_ERR_OPERATION_INVALID,
                                       _("failed to set cpuset.cpus in cgroup"
                                         " for vcpu %d"), i);
                        ret = -1;
                        goto cleanup;
                    }
                } else {
3652 3653
                    if (virProcessSetAffinity(cpupids[i],
                                              vcpupin->cpumask) < 0) {
3654 3655 3656 3657 3658 3659 3660
                        virReportError(VIR_ERR_SYSTEM_ERROR,
                                       _("failed to set cpu affinity for vcpu %d"),
                                       i);
                        ret = -1;
                        goto cleanup;
                    }
                }
3661
            }
3662 3663

            virCgroupFree(&cgroup_vcpu);
G
Guido Günther 已提交
3664
        }
3665 3666 3667 3668
    } else {
        for (i = oldvcpus - 1; i >= nvcpus; i--) {
            virDomainVcpuPinDefPtr vcpupin = NULL;

3669
            if (priv->cgroup) {
3670 3671
                int rv = -1;

3672
                rv = virCgroupNewVcpu(priv->cgroup, i, false, &cgroup_vcpu);
3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685
                if (rv < 0) {
                    virReportSystemError(-rv,
                                         _("Unable to access vcpu cgroup for %s(vcpu:"
                                           " %d)"),
                                         vm->def->name, i);
                    goto cleanup;
                }

                /* Remove cgroup for the offlined vcpu */
                virCgroupRemove(cgroup_vcpu);
                virCgroupFree(&cgroup_vcpu);
            }

3686 3687 3688 3689 3690
            /* Free vcpupin setting */
            if ((vcpupin = virDomainLookupVcpuPin(vm->def, i))) {
                VIR_FREE(vcpupin);
            }
        }
3691 3692
    }

3693 3694 3695 3696 3697
    priv->nvcpupids = ncpupids;
    VIR_FREE(priv->vcpupids);
    priv->vcpupids = cpupids;
    cpupids = NULL;

3698
cleanup:
3699
    qemuDomainObjExitMonitor(driver, vm);
E
Eric Blake 已提交
3700
    vm->def->vcpus = vcpus;
3701
    VIR_FREE(cpupids);
3702
    virDomainAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1);
3703 3704
    if (cgroup_vcpu)
        virCgroupFree(&cgroup_vcpu);
3705 3706 3707
    return ret;

unsupported:
3708 3709
    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                   _("cannot change vcpu count of this domain"));
3710 3711 3712 3713
    goto cleanup;
}


3714
static int
3715 3716
qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                        unsigned int flags)
3717
{
3718
    virQEMUDriverPtr driver = dom->conn->privateData;
3719
    virDomainObjPtr vm = NULL;
3720
    virDomainDefPtr persistentDef;
3721
    int ret = -1;
3722
    bool maximum;
3723
    virQEMUDriverConfigPtr cfg = NULL;
3724
    virCapsPtr caps = NULL;
3725

3726 3727
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
3728 3729 3730
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
3731 3732
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
3733 3734 3735
        return -1;
    }

3736
    cfg = virQEMUDriverGetConfig(driver);
3737 3738
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;
3739

3740
    if (!(vm = qemuDomObjFromDomain(dom)))
3741
        goto cleanup;
3742

3743
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
3744 3745
        goto cleanup;

3746 3747 3748
    maximum = (flags & VIR_DOMAIN_VCPU_MAXIMUM) != 0;
    flags &= ~VIR_DOMAIN_VCPU_MAXIMUM;

3749
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
3750 3751
                                        &persistentDef) < 0)
        goto endjob;
3752 3753 3754

    /* MAXIMUM cannot be mixed with LIVE.  */
    if (maximum && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
3755 3756
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("cannot adjust maximum on running domain"));
3757 3758 3759
        goto endjob;
    }

3760
    if (!maximum && nvcpus > vm->def->maxvcpus) {
3761 3762
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpus is greater than max allowable"
3763 3764
                         " vcpus for the domain: %d > %d"),
                       nvcpus, vm->def->maxvcpus);
3765 3766 3767
        goto endjob;
    }

3768
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
3769
        if (qemuDomainHotplugVcpus(driver, vm, nvcpus) < 0)
3770 3771 3772 3773
            goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
3774 3775 3776 3777 3778 3779 3780
        if (maximum) {
            persistentDef->maxvcpus = nvcpus;
            if (nvcpus < persistentDef->vcpus)
                persistentDef->vcpus = nvcpus;
        } else {
            persistentDef->vcpus = nvcpus;
        }
3781

3782
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
3783
            goto endjob;
3784
    }
3785

3786
    ret = 0;
3787

3788
endjob:
3789
    if (qemuDomainObjEndJob(driver, vm) == 0)
3790
        vm = NULL;
3791

3792
cleanup:
3793
    if (vm)
3794
        virObjectUnlock(vm);
3795
    virObjectUnref(caps);
3796
    virObjectUnref(cfg);
3797
    return ret;
3798 3799
}

3800
static int
3801
qemuDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
3802
{
3803
    return qemuDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE);
3804 3805
}

3806 3807

static int
3808 3809 3810 3811 3812
qemuDomainPinVcpuFlags(virDomainPtr dom,
                       unsigned int vcpu,
                       unsigned char *cpumap,
                       int maplen,
                       unsigned int flags) {
3813

3814
    virQEMUDriverPtr driver = dom->conn->privateData;
3815
    virDomainObjPtr vm;
3816
    virDomainDefPtr persistentDef = NULL;
3817
    virCgroupPtr cgroup_vcpu = NULL;
3818
    int ret = -1;
3819
    qemuDomainObjPrivatePtr priv;
3820
    bool doReset = false;
3821 3822
    int newVcpuPinNum = 0;
    virDomainVcpuPinDefPtr *newVcpuPin = NULL;
3823
    virBitmapPtr pcpumap = NULL;
3824
    virQEMUDriverConfigPtr cfg = NULL;
3825
    virCapsPtr caps = NULL;
3826

3827 3828 3829
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

3830 3831
    cfg = virQEMUDriverGetConfig(driver);

3832
    if (!(vm = qemuDomObjFromDomain(dom)))
3833 3834
        goto cleanup;

3835 3836 3837
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

3838
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
3839
                                        &persistentDef) < 0)
3840
        goto cleanup;
3841

3842 3843 3844
    priv = vm->privateData;

    if (vcpu > (priv->nvcpupids-1)) {
3845 3846 3847
        virReportError(VIR_ERR_INVALID_ARG,
                       _("vcpu number out of range %d > %d"),
                       vcpu, priv->nvcpupids);
3848
        goto cleanup;
3849 3850
    }

3851 3852 3853 3854
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
        goto cleanup;

3855 3856 3857 3858 3859 3860
    if (virBitmapIsAllClear(pcpumap)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Empty cpu list for pinning"));
        goto cleanup;
    }

3861 3862 3863
    /* pinning to all physical cpus means resetting,
     * so check if we can reset setting.
     */
3864 3865
    if (virBitmapIsAllSet(pcpumap))
        doReset = true;
3866

3867
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
3868

3869
        if (priv->vcpupids == NULL) {
3870 3871
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cpu affinity is not supported"));
3872 3873 3874
            goto cleanup;
        }

3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889
        if (vm->def->cputune.vcpupin) {
            newVcpuPin = virDomainVcpuPinDefCopy(vm->def->cputune.vcpupin,
                                                 vm->def->cputune.nvcpupin);
            if (!newVcpuPin)
                goto cleanup;

            newVcpuPinNum = vm->def->cputune.nvcpupin;
        } else {
            if (VIR_ALLOC(newVcpuPin) < 0) {
                virReportOOMError();
                goto cleanup;
            }
            newVcpuPinNum = 0;
        }

3890
        if (virDomainVcpuPinAdd(&newVcpuPin, &newVcpuPinNum, cpumap, maplen, vcpu) < 0) {
3891 3892
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("failed to update vcpupin"));
H
Hu Tao 已提交
3893
            virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
3894 3895 3896 3897
            goto cleanup;
        }

        /* Configure the corresponding cpuset cgroup before set affinity. */
3898
        if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
3899
            if (virCgroupNewVcpu(priv->cgroup, vcpu, false, &cgroup_vcpu) == 0 &&
3900 3901 3902 3903
                qemuSetupCgroupVcpuPin(cgroup_vcpu, newVcpuPin, newVcpuPinNum, vcpu) < 0) {
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("failed to set cpuset.cpus in cgroup"
                                 " for vcpu %d"), vcpu);
3904 3905 3906
                goto cleanup;
            }
        } else {
3907
            if (virProcessSetAffinity(priv->vcpupids[vcpu], pcpumap) < 0) {
3908 3909 3910 3911
                virReportError(VIR_ERR_SYSTEM_ERROR,
                               _("failed to set cpu affinity for vcpu %d"),
                               vcpu);
                goto cleanup;
H
Hu Tao 已提交
3912
            }
3913 3914
        }

3915
        if (doReset) {
3916
            if (virDomainVcpuPinDel(vm->def, vcpu) < 0) {
3917
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3918
                               _("failed to delete vcpupin xml of "
3919
                                 "a running domain"));
3920 3921
                goto cleanup;
            }
3922 3923
        } else {
            if (vm->def->cputune.vcpupin)
H
Hu Tao 已提交
3924
                virDomainVcpuPinDefArrayFree(vm->def->cputune.vcpupin, vm->def->cputune.nvcpupin);
3925 3926 3927 3928

            vm->def->cputune.vcpupin = newVcpuPin;
            vm->def->cputune.nvcpupin = newVcpuPinNum;
            newVcpuPin = NULL;
3929 3930
        }

3931
        if (newVcpuPin)
H
Hu Tao 已提交
3932
            virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
3933

3934
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3935
            goto cleanup;
3936
    }
3937

3938 3939
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {

3940
        if (doReset) {
E
Eric Blake 已提交
3941
            if (virDomainVcpuPinDel(persistentDef, vcpu) < 0) {
3942 3943 3944
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to delete vcpupin xml of "
                                 "a persistent domain"));
3945 3946 3947
                goto cleanup;
            }
        } else {
H
Hu Tao 已提交
3948 3949 3950 3951 3952 3953 3954
            if (!persistentDef->cputune.vcpupin) {
                if (VIR_ALLOC(persistentDef->cputune.vcpupin) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }
                persistentDef->cputune.nvcpupin = 0;
            }
3955
            if (virDomainVcpuPinAdd(&persistentDef->cputune.vcpupin,
H
Hu Tao 已提交
3956 3957 3958 3959
                                    &persistentDef->cputune.nvcpupin,
                                    cpumap,
                                    maplen,
                                    vcpu) < 0) {
3960 3961 3962
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to update or add vcpupin xml of "
                                 "a persistent domain"));
3963 3964
                goto cleanup;
            }
3965
        }
3966

3967
        ret = virDomainSaveConfig(cfg->configDir, persistentDef);
3968 3969 3970
        goto cleanup;
    }

3971
    ret = 0;
3972

3973
cleanup:
3974 3975
    if (cgroup_vcpu)
        virCgroupFree(&cgroup_vcpu);
3976
    if (vm)
3977
        virObjectUnlock(vm);
3978
    virBitmapFree(pcpumap);
3979
    virObjectUnref(caps);
3980
    virObjectUnref(cfg);
3981
    return ret;
3982 3983
}

3984
static int
3985
qemuDomainPinVcpu(virDomainPtr dom,
3986 3987 3988
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
3989 3990
    return qemuDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
                                  VIR_DOMAIN_AFFECT_LIVE);
3991 3992
}

3993
static int
3994 3995 3996 3997 3998
qemuDomainGetVcpuPinInfo(virDomainPtr dom,
                         int ncpumaps,
                         unsigned char *cpumaps,
                         int maplen,
                         unsigned int flags) {
3999

4000
    virQEMUDriverPtr driver = dom->conn->privateData;
E
Eric Blake 已提交
4001
    virDomainObjPtr vm = NULL;
4002 4003 4004 4005
    virDomainDefPtr targetDef = NULL;
    int ret = -1;
    int maxcpu, hostcpus, vcpu, pcpu;
    int n;
E
Eric Blake 已提交
4006
    virDomainVcpuPinDefPtr *vcpupin_list;
H
Hu Tao 已提交
4007
    virBitmapPtr cpumask = NULL;
4008
    unsigned char *cpumap;
H
Hu Tao 已提交
4009
    bool pinned;
4010
    virCapsPtr caps = NULL;
4011 4012 4013 4014

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

4015
    if (!(vm = qemuDomObjFromDomain(dom)))
4016 4017
        goto cleanup;

4018 4019 4020
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

4021
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
4022 4023
                                        &targetDef) < 0)
        goto cleanup;
4024 4025 4026 4027 4028

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        targetDef = vm->def;
    }

4029 4030 4031
    /* Coverity didn't realize that targetDef must be set if we got here.  */
    sa_assert(targetDef);

4032
    if ((hostcpus = nodeGetCPUCount()) < 0)
4033
        goto cleanup;
4034

4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062
    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

    /* Clamp to actual number of vcpus */
    if (ncpumaps > targetDef->vcpus)
        ncpumaps = targetDef->vcpus;

    if (ncpumaps < 1) {
        goto cleanup;
    }

    /* initialize cpumaps */
    memset(cpumaps, 0xff, maplen * ncpumaps);
    if (maxcpu % 8) {
        for (vcpu = 0; vcpu < ncpumaps; vcpu++) {
            cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
            cpumap[maplen - 1] &= (1 << maxcpu % 8) - 1;
        }
    }

    /* if vcpupin setting exists, there are unused physical cpus */
    for (n = 0; n < targetDef->cputune.nvcpupin; n++) {
        vcpupin_list = targetDef->cputune.vcpupin;
        vcpu = vcpupin_list[n]->vcpuid;
        cpumask = vcpupin_list[n]->cpumask;
        cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
        for (pcpu = 0; pcpu < maxcpu; pcpu++) {
H
Hu Tao 已提交
4063 4064 4065
            if (virBitmapGetBit(cpumask, pcpu, &pinned) < 0)
                goto cleanup;
            if (!pinned)
4066 4067 4068 4069 4070 4071 4072
                VIR_UNUSE_CPU(cpumap, pcpu);
        }
    }
    ret = ncpumaps;

cleanup:
    if (vm)
4073
        virObjectUnlock(vm);
4074
    virObjectUnref(caps);
4075 4076 4077
    return ret;
}

H
Hu Tao 已提交
4078
static int
4079 4080 4081 4082
qemuDomainPinEmulator(virDomainPtr dom,
                      unsigned char *cpumap,
                      int maplen,
                      unsigned int flags)
H
Hu Tao 已提交
4083
{
4084
    virQEMUDriverPtr driver = dom->conn->privateData;
H
Hu Tao 已提交
4085 4086 4087 4088 4089 4090
    virDomainObjPtr vm;
    virCgroupPtr cgroup_emulator = NULL;
    pid_t pid;
    virDomainDefPtr persistentDef = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
4091
    bool doReset = false;
H
Hu Tao 已提交
4092 4093
    int newVcpuPinNum = 0;
    virDomainVcpuPinDefPtr *newVcpuPin = NULL;
4094
    virBitmapPtr pcpumap = NULL;
4095
    virQEMUDriverConfigPtr cfg = NULL;
4096
    virCapsPtr caps = NULL;
H
Hu Tao 已提交
4097 4098 4099 4100

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

4101 4102
    cfg = virQEMUDriverGetConfig(driver);

4103
    if (!(vm = qemuDomObjFromDomain(dom)))
H
Hu Tao 已提交
4104 4105
        goto cleanup;

4106 4107 4108
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

4109 4110 4111 4112 4113 4114 4115
    if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Changing affinity for emulator thread dynamically "
                         "is not allowed when CPU placement is 'auto'"));
        goto cleanup;
    }

4116
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
H
Hu Tao 已提交
4117 4118 4119 4120 4121
                                        &persistentDef) < 0)
        goto cleanup;

    priv = vm->privateData;

4122 4123 4124 4125
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
        goto cleanup;

4126 4127 4128 4129 4130 4131
    if (virBitmapIsAllClear(pcpumap)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Empty cpu list for pinning"));
        goto cleanup;
    }

H
Hu Tao 已提交
4132 4133 4134
    /* pinning to all physical cpus means resetting,
     * so check if we can reset setting.
     */
4135 4136
    if (virBitmapIsAllSet(pcpumap))
        doReset = true;
H
Hu Tao 已提交
4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147

    pid = vm->pid;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {

        if (priv->vcpupids != NULL) {
            if (VIR_ALLOC(newVcpuPin) < 0) {
                virReportOOMError();
                goto cleanup;
            }

4148
            if (virDomainVcpuPinAdd(&newVcpuPin, &newVcpuPinNum, cpumap, maplen, -1) < 0) {
H
Hu Tao 已提交
4149 4150
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to update vcpupin"));
H
Hu Tao 已提交
4151
                virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
H
Hu Tao 已提交
4152 4153 4154
                goto cleanup;
            }

4155 4156
            if (virCgroupHasController(priv->cgroup,
                                       VIR_CGROUP_CONTROLLER_CPUSET)) {
H
Hu Tao 已提交
4157 4158 4159 4160
                /*
                 * Configure the corresponding cpuset cgroup.
                 * If no cgroup for domain or hypervisor exists, do nothing.
                 */
4161
                if (virCgroupNewEmulator(priv->cgroup, false, &cgroup_emulator) == 0) {
4162 4163 4164 4165 4166 4167
                    if (qemuSetupCgroupEmulatorPin(cgroup_emulator,
                                                   newVcpuPin[0]->cpumask) < 0) {
                        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                                       _("failed to set cpuset.cpus in cgroup"
                                         " for emulator threads"));
                        goto cleanup;
H
Hu Tao 已提交
4168 4169 4170
                    }
                }
            } else {
4171
                if (virProcessSetAffinity(pid, pcpumap) < 0) {
H
Hu Tao 已提交
4172 4173 4174 4175 4176 4177 4178
                    virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
                                   _("failed to set cpu affinity for "
                                     "emulator threads"));
                    goto cleanup;
                }
            }

4179
            if (doReset) {
H
Hu Tao 已提交
4180 4181 4182 4183 4184 4185 4186
                if (virDomainEmulatorPinDel(vm->def) < 0) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("failed to delete emulatorpin xml of "
                                     "a running domain"));
                    goto cleanup;
                }
            } else {
H
Hu Tao 已提交
4187
                virDomainVcpuPinDefFree(vm->def->cputune.emulatorpin);
H
Hu Tao 已提交
4188 4189 4190 4191 4192
                vm->def->cputune.emulatorpin = newVcpuPin[0];
                VIR_FREE(newVcpuPin);
            }

            if (newVcpuPin)
H
Hu Tao 已提交
4193
                virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
H
Hu Tao 已提交
4194 4195 4196 4197 4198 4199
        } else {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cpu affinity is not supported"));
            goto cleanup;
        }

4200
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
H
Hu Tao 已提交
4201 4202 4203 4204 4205
            goto cleanup;
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {

4206
        if (doReset) {
H
Hu Tao 已提交
4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221
            if (virDomainEmulatorPinDel(persistentDef) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to delete emulatorpin xml of "
                                 "a persistent domain"));
                goto cleanup;
            }
        } else {
            if (virDomainEmulatorPinAdd(persistentDef, cpumap, maplen) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to update or add emulatorpin xml "
                                 "of a persistent domain"));
                goto cleanup;
            }
        }

4222
        ret = virDomainSaveConfig(cfg->configDir, persistentDef);
H
Hu Tao 已提交
4223 4224 4225 4226 4227 4228 4229 4230
        goto cleanup;
    }

    ret = 0;

cleanup:
    if (cgroup_emulator)
        virCgroupFree(&cgroup_emulator);
4231
    virBitmapFree(pcpumap);
4232
    virObjectUnref(caps);
H
Hu Tao 已提交
4233
    if (vm)
4234
        virObjectUnlock(vm);
4235
    virObjectUnref(cfg);
H
Hu Tao 已提交
4236 4237 4238 4239
    return ret;
}

static int
4240 4241 4242 4243
qemuDomainGetEmulatorPinInfo(virDomainPtr dom,
                             unsigned char *cpumaps,
                             int maplen,
                             unsigned int flags)
H
Hu Tao 已提交
4244
{
4245
    virQEMUDriverPtr driver = dom->conn->privateData;
H
Hu Tao 已提交
4246 4247 4248 4249
    virDomainObjPtr vm = NULL;
    virDomainDefPtr targetDef = NULL;
    int ret = -1;
    int maxcpu, hostcpus, pcpu;
H
Hu Tao 已提交
4250 4251
    virBitmapPtr cpumask = NULL;
    bool pinned;
4252
    virCapsPtr caps = NULL;
H
Hu Tao 已提交
4253 4254 4255 4256

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

4257
    if (!(vm = qemuDomObjFromDomain(dom)))
H
Hu Tao 已提交
4258 4259
        goto cleanup;

4260 4261 4262
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

4263
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
4264
                                        vm, &flags, &targetDef) < 0)
H
Hu Tao 已提交
4265 4266 4267 4268 4269 4270 4271 4272
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_LIVE)
        targetDef = vm->def;

    /* Coverity didn't realize that targetDef must be set if we got here. */
    sa_assert(targetDef);

4273
    if ((hostcpus = nodeGetCPUCount()) < 0)
H
Hu Tao 已提交
4274
        goto cleanup;
4275

H
Hu Tao 已提交
4276 4277 4278 4279 4280 4281 4282 4283 4284 4285
    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

    /* initialize cpumaps */
    memset(cpumaps, 0xff, maplen);
    if (maxcpu % 8) {
        cpumaps[maplen - 1] &= (1 << maxcpu % 8) - 1;
    }

4286 4287 4288 4289 4290
    if (targetDef->cputune.emulatorpin) {
        cpumask = targetDef->cputune.emulatorpin->cpumask;
    } else if (targetDef->cpumask) {
        cpumask = targetDef->cpumask;
    } else {
H
Hu Tao 已提交
4291 4292 4293 4294 4295
        ret = 0;
        goto cleanup;
    }

    for (pcpu = 0; pcpu < maxcpu; pcpu++) {
H
Hu Tao 已提交
4296 4297 4298
        if (virBitmapGetBit(cpumask, pcpu, &pinned) < 0)
            goto cleanup;
        if (!pinned)
H
Hu Tao 已提交
4299 4300 4301 4302 4303 4304 4305
            VIR_UNUSE_CPU(cpumaps, pcpu);
    }

    ret = 1;

cleanup:
    if (vm)
4306
        virObjectUnlock(vm);
4307
    virObjectUnref(caps);
H
Hu Tao 已提交
4308 4309 4310
    return ret;
}

4311
static int
4312 4313 4314 4315 4316
qemuDomainGetVcpus(virDomainPtr dom,
                   virVcpuInfoPtr info,
                   int maxinfo,
                   unsigned char *cpumaps,
                   int maplen) {
4317
    virDomainObjPtr vm;
4318
    int i, v, maxcpu, hostcpus;
4319
    int ret = -1;
4320
    qemuDomainObjPrivatePtr priv;
4321

4322
    if (!(vm = qemuDomObjFromDomain(dom)))
4323 4324
        goto cleanup;

D
Daniel P. Berrange 已提交
4325
    if (!virDomainObjIsActive(vm)) {
4326 4327 4328
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",
                       _("cannot list vcpu pinning for an inactive domain"));
4329
        goto cleanup;
4330 4331
    }

4332 4333
    priv = vm->privateData;

4334
    if ((hostcpus = nodeGetCPUCount()) < 0)
4335
        goto cleanup;
4336 4337

    maxcpu = maplen * 8;
4338 4339
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
4340 4341

    /* Clamp to actual number of vcpus */
4342 4343
    if (maxinfo > priv->nvcpupids)
        maxinfo = priv->nvcpupids;
4344

4345 4346 4347
    if (maxinfo >= 1) {
        if (info != NULL) {
            memset(info, 0, sizeof(*info) * maxinfo);
4348
            for (i = 0; i < maxinfo; i++) {
4349 4350
                info[i].number = i;
                info[i].state = VIR_VCPU_RUNNING;
4351

4352
                if (priv->vcpupids != NULL &&
4353 4354 4355 4356 4357
                    qemuGetProcessInfo(&(info[i].cpuTime),
                                       &(info[i].cpu),
                                       NULL,
                                       vm->pid,
                                       priv->vcpupids[i]) < 0) {
4358
                    virReportSystemError(errno, "%s",
4359 4360 4361
                                         _("cannot get vCPU placement & pCPU time"));
                    goto cleanup;
                }
4362
            }
4363 4364
        }

4365 4366
        if (cpumaps != NULL) {
            memset(cpumaps, 0, maplen * maxinfo);
4367
            if (priv->vcpupids != NULL) {
4368
                for (v = 0; v < maxinfo; v++) {
4369
                    unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
4370 4371 4372
                    virBitmapPtr map = NULL;
                    unsigned char *tmpmap = NULL;
                    int tmpmapLen = 0;
4373

4374 4375
                    if (virProcessGetAffinity(priv->vcpupids[v],
                                              &map, maxcpu) < 0)
4376
                        goto cleanup;
4377 4378 4379 4380 4381 4382 4383
                    virBitmapToData(map, &tmpmap, &tmpmapLen);
                    if (tmpmapLen > maplen)
                        tmpmapLen = maplen;
                    memcpy(cpumap, tmpmap, tmpmapLen);

                    VIR_FREE(tmpmap);
                    virBitmapFree(map);
4384
                }
4385
            } else {
4386 4387
                virReportError(VIR_ERR_OPERATION_INVALID,
                               "%s", _("cpu affinity is not available"));
4388
                goto cleanup;
4389 4390 4391
            }
        }
    }
4392
    ret = maxinfo;
4393

4394
cleanup:
4395
    if (vm)
4396
        virObjectUnlock(vm);
4397
    return ret;
4398 4399 4400
}


4401
static int
4402
qemuDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
4403
{
4404
    virQEMUDriverPtr driver = dom->conn->privateData;
4405
    virDomainObjPtr vm;
4406
    virDomainDefPtr def;
4407
    int ret = -1;
4408
    virCapsPtr caps = NULL;
4409

4410 4411
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
4412 4413
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

4414
    if (!(vm = qemuDomObjFromDomain(dom)))
4415
        goto cleanup;
4416

4417 4418 4419
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

4420
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
4421
                                        vm, &flags, &def) < 0)
4422
        goto cleanup;
4423

4424
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
4425
        def = vm->def;
4426 4427
    }

4428
    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
4429

4430
cleanup:
4431
    if (vm)
4432
        virObjectUnlock(vm);
4433
    virObjectUnref(caps);
4434 4435 4436
    return ret;
}

4437
static int
4438
qemuDomainGetMaxVcpus(virDomainPtr dom)
4439
{
4440 4441
    return qemuDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
                                         VIR_DOMAIN_VCPU_MAXIMUM));
4442 4443
}

4444
static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
4445
{
4446
    virQEMUDriverPtr driver = dom->conn->privateData;
4447 4448 4449
    virDomainObjPtr vm;
    int ret = -1;

4450 4451
    memset(seclabel, 0, sizeof(*seclabel));

4452 4453
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
4454

4455
    if (!virDomainVirtTypeToString(vm->def->virtType)) {
4456 4457 4458
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown virt type in domain definition '%d'"),
                       vm->def->virtType);
4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475
        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 已提交
4476
    if (virDomainObjIsActive(vm)) {
4477
        if (virSecurityManagerGetProcessLabel(driver->securityManager,
4478
                                              vm->def, vm->pid, seclabel) < 0) {
4479 4480
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Failed to get security label"));
4481
            goto cleanup;
4482 4483 4484 4485 4486 4487 4488
        }
    }

    ret = 0;

cleanup:
    if (vm)
4489
        virObjectUnlock(vm);
4490 4491 4492
    return ret;
}

M
Marcelo Cerri 已提交
4493 4494 4495
static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
                                          virSecurityLabelPtr* seclabels)
{
4496
    virQEMUDriverPtr driver = dom->conn->privateData;
M
Marcelo Cerri 已提交
4497 4498 4499
    virDomainObjPtr vm;
    int i, ret = -1;

4500 4501
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
M
Marcelo Cerri 已提交
4502 4503 4504 4505 4506 4507 4508 4509 4510

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

    /*
4511
     * Check the comment in qemuDomainGetSecurityLabel function.
M
Marcelo Cerri 已提交
4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551
     */
    if (!virDomainObjIsActive(vm)) {
        /* No seclabels */
        *seclabels = NULL;
        ret = 0;
    } else {
        int len = 0;
        virSecurityManagerPtr* mgrs = virSecurityManagerGetNested(
                                            driver->securityManager);
        if (!mgrs)
            goto cleanup;

        /* Allocate seclabels array */
        for (i = 0; mgrs[i]; i++)
            len++;

        if (VIR_ALLOC_N((*seclabels), len) < 0) {
            virReportOOMError();
            VIR_FREE(mgrs);
            goto cleanup;
        }
        memset(*seclabels, 0, sizeof(**seclabels) * len);

        /* Fill the array */
        for (i = 0; i < len; i++) {
            if (virSecurityManagerGetProcessLabel(mgrs[i], vm->def, vm->pid,
                                                  &(*seclabels)[i]) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("Failed to get security label"));
                VIR_FREE(mgrs);
                VIR_FREE(*seclabels);
                goto cleanup;
            }
        }
        ret = len;
        VIR_FREE(mgrs);
    }

cleanup:
    if (vm)
4552
        virObjectUnlock(vm);
M
Marcelo Cerri 已提交
4553 4554
    return ret;
}
4555 4556


4557 4558
static int qemuNodeGetSecurityModel(virConnectPtr conn,
                                    virSecurityModelPtr secmodel)
4559
{
4560
    virQEMUDriverPtr driver = conn->privateData;
4561
    char *p;
4562
    int ret = 0;
4563
    virCapsPtr caps = NULL;
4564

4565 4566
    memset(secmodel, 0, sizeof(*secmodel));

4567 4568 4569
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

4570
    /* We treat no driver as success, but simply return no data in *secmodel */
4571 4572
    if (caps->host.nsecModels == 0 ||
        caps->host.secModels[0].model == NULL)
4573
        goto cleanup;
4574

4575
    p = caps->host.secModels[0].model;
4576
    if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
4577 4578 4579
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("security model string exceeds max %d bytes"),
                       VIR_SECURITY_MODEL_BUFLEN-1);
4580 4581
        ret = -1;
        goto cleanup;
4582 4583 4584
    }
    strcpy(secmodel->model, p);

4585
    p = caps->host.secModels[0].doi;
4586
    if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
4587 4588 4589
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("security DOI string exceeds max %d bytes"),
                       VIR_SECURITY_DOI_BUFLEN-1);
4590 4591
        ret = -1;
        goto cleanup;
4592 4593
    }
    strcpy(secmodel->doi, p);
4594 4595

cleanup:
4596
    virObjectUnref(caps);
4597
    return ret;
4598 4599
}

E
Eric Blake 已提交
4600
/* Return -1 on most failures after raising error, -2 if edit was specified
4601 4602 4603
 * but xmlin and state (-1 for no change, 0 for paused, 1 for running) do
 * not represent any changes (no error raised), -3 if corrupt image was
 * unlinked (no error raised), and opened fd on success.  */
4604
static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
4605
qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
4606 4607
                        const char *path,
                        virDomainDefPtr *ret_def,
4608
                        virQEMUSaveHeaderPtr ret_header,
J
Jiri Denemark 已提交
4609 4610
                        bool bypass_cache,
                        virFileWrapperFdPtr *wrapperFd,
4611 4612
                        const char *xmlin, int state, bool edit,
                        bool unlink_corrupt)
J
Jiri Denemark 已提交
4613
{
W
Wen Congyang 已提交
4614
    int fd = -1;
4615
    virQEMUSaveHeader header;
J
Jiri Denemark 已提交
4616 4617
    char *xml = NULL;
    virDomainDefPtr def = NULL;
4618
    int oflags = edit ? O_RDWR : O_RDONLY;
4619
    virCapsPtr caps = NULL;
4620

4621
    if (bypass_cache) {
4622
        int directFlag = virFileDirectFdFlag();
4623
        if (directFlag < 0) {
4624 4625
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("bypass cache unsupported by this system"));
4626 4627
            goto error;
        }
4628
        oflags |= directFlag;
4629
    }
4630

4631 4632 4633
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto error;

E
Eric Blake 已提交
4634 4635
    if ((fd = qemuOpenFile(driver, path, oflags, NULL, NULL)) < 0)
        goto error;
J
Jiri Denemark 已提交
4636 4637 4638
    if (bypass_cache &&
        !(*wrapperFd = virFileWrapperFdNew(&fd, path,
                                           VIR_FILE_WRAPPER_BYPASS_CACHE)))
4639
        goto error;
4640 4641

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
4642 4643 4644 4645 4646 4647 4648 4649 4650
        if (unlink_corrupt) {
            if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
                virReportSystemError(errno,
                                     _("cannot remove corrupt file: %s"),
                                     path);
                goto error;
            }
            return -3;
        }
4651 4652
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("failed to read qemu header"));
J
Jiri Denemark 已提交
4653
        goto error;
4654 4655
    }

4656
    if (memcmp(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic)) != 0) {
E
Eric Blake 已提交
4657 4658
        const char *msg = _("image magic is incorrect");

4659
        if (memcmp(header.magic, QEMU_SAVE_PARTIAL,
E
Eric Blake 已提交
4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671
                   sizeof(header.magic)) == 0) {
            msg = _("save image is incomplete");
            if (unlink_corrupt) {
                if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
                    virReportSystemError(errno,
                                         _("cannot remove corrupt file: %s"),
                                         path);
                    goto error;
                }
                return -3;
            }
        }
4672
        virReportError(VIR_ERR_OPERATION_FAILED, "%s", msg);
J
Jiri Denemark 已提交
4673
        goto error;
4674 4675
    }

4676
    if (header.version > QEMU_SAVE_VERSION) {
4677 4678 4679 4680
        /* convert endianess and try again */
        bswap_header(&header);
    }

4681
    if (header.version > QEMU_SAVE_VERSION) {
4682 4683
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("image version is not supported (%d > %d)"),
4684
                       header.version, QEMU_SAVE_VERSION);
J
Jiri Denemark 已提交
4685
        goto error;
4686 4687
    }

4688
    if (header.xml_len <= 0) {
4689 4690
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("invalid XML length: %d"), header.xml_len);
J
Jiri Denemark 已提交
4691
        goto error;
4692 4693
    }

4694 4695
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
        virReportOOMError();
J
Jiri Denemark 已提交
4696
        goto error;
4697 4698 4699
    }

    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
4700 4701
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("failed to read XML"));
J
Jiri Denemark 已提交
4702
        goto error;
4703 4704
    }

4705 4706
    if (edit && STREQ(xml, xmlin) &&
        (state < 0 || state == header.was_running)) {
4707 4708 4709 4710 4711 4712 4713
        VIR_FREE(xml);
        if (VIR_CLOSE(fd) < 0) {
            virReportSystemError(errno, _("cannot close file: %s"), path);
            goto error;
        }
        return -2;
    }
4714 4715
    if (state >= 0)
        header.was_running = state;
4716

4717
    /* Create a domain from this XML */
4718
    if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
M
Matthias Bolte 已提交
4719
                                        QEMU_EXPECTED_VIRT_TYPES,
4720
                                        VIR_DOMAIN_XML_INACTIVE)))
J
Jiri Denemark 已提交
4721
        goto error;
4722 4723 4724
    if (xmlin) {
        virDomainDefPtr def2 = NULL;

4725
        if (!(def2 = virDomainDefParseString(xmlin, caps, driver->xmlopt,
4726 4727 4728 4729 4730 4731 4732 4733 4734 4735
                                             QEMU_EXPECTED_VIRT_TYPES,
                                             VIR_DOMAIN_XML_INACTIVE)))
            goto error;
        if (!virDomainDefCheckABIStability(def, def2)) {
            virDomainDefFree(def2);
            goto error;
        }
        virDomainDefFree(def);
        def = def2;
    }
4736

J
Jiri Denemark 已提交
4737
    VIR_FREE(xml);
4738

J
Jiri Denemark 已提交
4739 4740
    *ret_def = def;
    *ret_header = header;
4741

4742 4743
    virObjectUnref(caps);

J
Jiri Denemark 已提交
4744
    return fd;
4745

J
Jiri Denemark 已提交
4746 4747 4748
error:
    virDomainDefFree(def);
    VIR_FREE(xml);
4749
    VIR_FORCE_CLOSE(fd);
4750
    virObjectUnref(caps);
J
Jiri Denemark 已提交
4751 4752 4753 4754

    return -1;
}

4755 4756
static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6)
qemuDomainSaveImageStartVM(virConnectPtr conn,
4757
                           virQEMUDriverPtr driver,
4758 4759
                           virDomainObjPtr vm,
                           int *fd,
4760
                           const virQEMUSaveHeaderPtr header,
4761 4762
                           const char *path,
                           bool start_paused)
J
Jiri Denemark 已提交
4763 4764 4765 4766
{
    int ret = -1;
    virDomainEventPtr event;
    int intermediatefd = -1;
4767
    virCommandPtr cmd = NULL;
4768
    char *errbuf = NULL;
4769
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
J
Jiri Denemark 已提交
4770

4771 4772 4773
    if ((header->version == 2) &&
        (header->compressed != QEMU_SAVE_FORMAT_RAW)) {
        if (!(cmd = qemuCompressGetCommand(header->compressed)))
4774
            goto cleanup;
4775

4776 4777
        intermediatefd = *fd;
        *fd = -1;
4778

4779 4780 4781 4782
        virCommandSetInputFD(cmd, intermediatefd);
        virCommandSetOutputFD(cmd, fd);
        virCommandSetErrorBuffer(cmd, &errbuf);
        virCommandDoAsyncIO(cmd);
4783

4784 4785 4786
        if (virCommandRunAsync(cmd, NULL) < 0) {
            *fd = intermediatefd;
            goto cleanup;
4787 4788
        }
    }
J
Jiri Denemark 已提交
4789

4790
    /* Set the migration source and start it up. */
4791 4792 4793
    ret = qemuProcessStart(conn, driver, vm, "stdio", *fd, path, NULL,
                           VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
                           VIR_QEMU_PROCESS_START_PAUSED);
J
Jiri Denemark 已提交
4794

4795
    if (intermediatefd != -1) {
4796
        if (ret < 0) {
4797 4798 4799
            /* if there was an error setting up qemu, the intermediate
             * process will wait forever to write to stdout, so we
             * must manually kill it.
4800 4801
             */
            VIR_FORCE_CLOSE(intermediatefd);
4802
            VIR_FORCE_CLOSE(*fd);
4803 4804
        }

4805 4806
        if (virCommandWait(cmd, NULL) < 0) {
            qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0);
4807
            ret = -1;
4808
        }
4809
        VIR_DEBUG("Decompression binary stderr: %s", NULLSTR(errbuf));
4810
    }
4811
    VIR_FORCE_CLOSE(intermediatefd);
J
Jiri Denemark 已提交
4812

4813 4814 4815
    if (VIR_CLOSE(*fd) < 0) {
        virReportSystemError(errno, _("cannot close file: %s"), path);
        ret = -1;
4816
    }
J
Jiri Denemark 已提交
4817

4818
    if (ret < 0) {
4819
        virDomainAuditStart(vm, "restored", false);
4820
        goto cleanup;
4821
    }
4822

4823 4824 4825
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
4826
    virDomainAuditStart(vm, "restored", true);
J
Jiri Denemark 已提交
4827 4828 4829
    if (event)
        qemuDomainEventQueue(driver, event);

4830

4831 4832
    /* If it was running before, resume it now unless caller requested pause. */
    if (header->was_running && !start_paused) {
J
Jiri Denemark 已提交
4833
        if (qemuProcessStartCPUs(driver, vm, conn,
4834 4835
                                 VIR_DOMAIN_RUNNING_RESTORED,
                                 QEMU_ASYNC_JOB_NONE) < 0) {
4836
            if (virGetLastError() == NULL)
4837 4838
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("failed to resume domain"));
4839
            goto cleanup;
4840
        }
4841
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
4842
            VIR_WARN("Failed to save status on vm %s", vm->def->name);
4843
            goto cleanup;
4844
        }
4845 4846 4847 4848 4849 4850 4851 4852
    } else {
        int detail = (start_paused ? VIR_DOMAIN_EVENT_SUSPENDED_PAUSED :
                      VIR_DOMAIN_EVENT_SUSPENDED_RESTORED);
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         detail);
        if (event)
            qemuDomainEventQueue(driver, event);
4853
    }
J
Jiri Denemark 已提交
4854

4855
    ret = 0;
4856

4857
cleanup:
4858
    virCommandFree(cmd);
4859
    VIR_FREE(errbuf);
4860
    if (virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
4861
                                                 vm->def, path) < 0)
4862
        VIR_WARN("failed to restore save state label on %s", path);
4863
    virObjectUnref(cfg);
J
Jiri Denemark 已提交
4864 4865 4866
    return ret;
}

4867
static int
4868 4869 4870 4871
qemuDomainRestoreFlags(virConnectPtr conn,
                       const char *path,
                       const char *dxml,
                       unsigned int flags)
4872
{
4873
    virQEMUDriverPtr driver = conn->privateData;
J
Jiri Denemark 已提交
4874 4875 4876 4877
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    int fd = -1;
    int ret = -1;
4878
    virQEMUSaveHeader header;
J
Jiri Denemark 已提交
4879
    virFileWrapperFdPtr wrapperFd = NULL;
4880
    int state = -1;
J
Jiri Denemark 已提交
4881

4882 4883 4884
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
4885

J
Jiri Denemark 已提交
4886

4887 4888 4889 4890 4891
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
        state = 1;
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
        state = 0;

4892 4893
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
                                 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
J
Jiri Denemark 已提交
4894
                                 &wrapperFd, dxml, state, false, false);
J
Jiri Denemark 已提交
4895 4896 4897
    if (fd < 0)
        goto cleanup;

4898
    if (!(vm = virDomainObjListAdd(driver->domains, def,
4899
                                   driver->xmlopt,
4900 4901 4902
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jiri Denemark 已提交
4903 4904 4905
        goto cleanup;
    def = NULL;

4906
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
J
Jiri Denemark 已提交
4907 4908
        goto cleanup;

4909 4910
    ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path,
                                     false);
J
Jiri Denemark 已提交
4911
    if (virFileWrapperFdClose(wrapperFd) < 0)
4912
        VIR_WARN("Failed to close %s", path);
J
Jiri Denemark 已提交
4913

4914
    if (qemuDomainObjEndJob(driver, vm) == 0)
4915
        vm = NULL;
J
Jiri Denemark 已提交
4916
    else if (ret < 0 && !vm->persistent) {
4917
        qemuDomainRemoveInactive(driver, vm);
J
Jiri Denemark 已提交
4918 4919
        vm = NULL;
    }
4920

4921 4922
cleanup:
    virDomainDefFree(def);
4923
    VIR_FORCE_CLOSE(fd);
J
Jiri Denemark 已提交
4924
    virFileWrapperFdFree(wrapperFd);
4925
    if (vm)
4926
        virObjectUnlock(vm);
4927
    return ret;
D
Daniel P. Berrange 已提交
4928 4929
}

4930 4931 4932 4933 4934 4935 4936
static int
qemuDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return qemuDomainRestoreFlags(conn, path, NULL, 0);
}

4937 4938 4939 4940
static char *
qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
                              unsigned int flags)
{
4941
    virQEMUDriverPtr driver = conn->privateData;
4942 4943 4944
    char *ret = NULL;
    virDomainDefPtr def = NULL;
    int fd = -1;
4945
    virQEMUSaveHeader header;
4946 4947 4948 4949 4950

    /* We only take subset of virDomainDefFormat flags.  */
    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);

    fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
4951
                                 NULL, -1, false, false);
4952 4953 4954 4955

    if (fd < 0)
        goto cleanup;

4956
    ret = qemuDomainDefFormatXML(driver, def, flags);
4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967

cleanup:
    virDomainDefFree(def);
    VIR_FORCE_CLOSE(fd);
    return ret;
}

static int
qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
                             const char *dxml, unsigned int flags)
{
4968
    virQEMUDriverPtr driver = conn->privateData;
4969 4970 4971
    int ret = -1;
    virDomainDefPtr def = NULL;
    int fd = -1;
4972
    virQEMUSaveHeader header;
4973 4974
    char *xml = NULL;
    size_t len;
4975
    int state = -1;
4976

4977 4978
    virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
4979

4980 4981 4982 4983 4984
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
        state = 1;
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
        state = 0;

4985
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
4986
                                 dxml, state, true, false);
4987 4988 4989 4990 4991 4992 4993 4994

    if (fd < 0) {
        /* Check for special case of no change needed.  */
        if (fd == -2)
            ret = 0;
        goto cleanup;
    }

4995 4996
    xml = qemuDomainDefFormatXML(driver, def,
                                 VIR_DOMAIN_XML_INACTIVE |
4997 4998
                                 VIR_DOMAIN_XML_SECURE |
                                 VIR_DOMAIN_XML_MIGRATABLE);
4999 5000 5001 5002 5003
    if (!xml)
        goto cleanup;
    len = strlen(xml) + 1;

    if (len > header.xml_len) {
5004 5005
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("new xml too large to fit in file"));
5006 5007 5008 5009 5010 5011 5012
        goto cleanup;
    }
    if (VIR_EXPAND_N(xml, len, header.xml_len - len) < 0) {
        virReportOOMError();
        goto cleanup;
    }

5013
    if (lseek(fd, 0, SEEK_SET) != 0) {
5014 5015 5016
        virReportSystemError(errno, _("cannot seek in '%s'"), path);
        goto cleanup;
    }
5017 5018
    if (safewrite(fd, &header, sizeof(header)) != sizeof(header) ||
        safewrite(fd, xml, len) != len ||
5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032
        VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno, _("failed to write xml to '%s'"), path);
        goto cleanup;
    }

    ret = 0;

cleanup:
    virDomainDefFree(def);
    VIR_FORCE_CLOSE(fd);
    VIR_FREE(xml);
    return ret;
}

E
Eric Blake 已提交
5033 5034
/* Return 0 on success, 1 if incomplete saved image was silently unlinked,
 * and -1 on failure with error raised.  */
5035 5036
static int
qemuDomainObjRestore(virConnectPtr conn,
5037
                     virQEMUDriverPtr driver,
5038
                     virDomainObjPtr vm,
5039
                     const char *path,
5040
                     bool start_paused,
5041
                     bool bypass_cache)
J
Jiri Denemark 已提交
5042 5043 5044 5045
{
    virDomainDefPtr def = NULL;
    int fd = -1;
    int ret = -1;
5046
    virQEMUSaveHeader header;
J
Jiri Denemark 已提交
5047
    virFileWrapperFdPtr wrapperFd = NULL;
J
Jiri Denemark 已提交
5048

5049
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
J
Jiri Denemark 已提交
5050
                                 bypass_cache, &wrapperFd, NULL, -1, false,
5051
                                 true);
E
Eric Blake 已提交
5052 5053 5054
    if (fd < 0) {
        if (fd == -3)
            ret = 1;
J
Jiri Denemark 已提交
5055
        goto cleanup;
E
Eric Blake 已提交
5056
    }
J
Jiri Denemark 已提交
5057 5058 5059 5060 5061 5062 5063

    if (STRNEQ(vm->def->name, def->name) ||
        memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
        char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
        char def_uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(vm->def->uuid, vm_uuidstr);
        virUUIDFormat(def->uuid, def_uuidstr);
5064 5065 5066 5067 5068
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("cannot restore domain '%s' uuid %s from a file"
                         " which belongs to domain '%s' uuid %s"),
                       vm->def->name, vm_uuidstr,
                       def->name, def_uuidstr);
J
Jiri Denemark 已提交
5069 5070 5071
        goto cleanup;
    }

5072
    virDomainObjAssignDef(vm, def, true, NULL);
J
Jiri Denemark 已提交
5073 5074
    def = NULL;

5075 5076
    ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path,
                                     start_paused);
J
Jiri Denemark 已提交
5077
    if (virFileWrapperFdClose(wrapperFd) < 0)
5078
        VIR_WARN("Failed to close %s", path);
J
Jiri Denemark 已提交
5079 5080 5081

cleanup:
    virDomainDefFree(def);
5082
    VIR_FORCE_CLOSE(fd);
J
Jiri Denemark 已提交
5083
    virFileWrapperFdFree(wrapperFd);
J
Jiri Denemark 已提交
5084 5085 5086
    return ret;
}

D
Daniel P. Berrange 已提交
5087

5088
static char *qemuDomainGetXMLDesc(virDomainPtr dom,
5089 5090
                                  unsigned int flags)
{
5091
    virQEMUDriverPtr driver = dom->conn->privateData;
5092 5093
    virDomainObjPtr vm;
    char *ret = NULL;
5094
    unsigned long long balloon;
5095
    int err = 0;
5096
    qemuDomainObjPrivatePtr priv;
5097

5098
    /* Flags checked by virDomainDefFormat */
5099

5100
    if (!(vm = qemuDomObjFromDomain(dom)))
5101
        goto cleanup;
D
Daniel P. Berrange 已提交
5102

5103 5104
    priv = vm->privateData;

5105 5106 5107
    /* Refresh current memory based on balloon info if supported */
    if ((vm->def->memballoon != NULL) &&
        (vm->def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE) &&
5108
        !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BALLOON_EVENT) &&
5109
        (virDomainObjIsActive(vm))) {
5110 5111
        /* Don't delay if someone's using the monitor, just use
         * existing most recent data instead */
5112
        if (qemuDomainJobAllowed(priv, QEMU_JOB_QUERY)) {
5113
            if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
5114 5115
                goto cleanup;

5116
            if (!virDomainObjIsActive(vm)) {
5117 5118
                virReportError(VIR_ERR_OPERATION_INVALID,
                               "%s", _("domain is not running"));
5119 5120 5121
                goto endjob;
            }

5122
            qemuDomainObjEnterMonitor(driver, vm);
5123
            err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
5124
            qemuDomainObjExitMonitor(driver, vm);
5125 5126

endjob:
5127
            if (qemuDomainObjEndJob(driver, vm) == 0) {
5128 5129 5130
                vm = NULL;
                goto cleanup;
            }
5131 5132 5133
            if (err < 0)
                goto cleanup;
            if (err > 0)
5134
                vm->def->mem.cur_balloon = balloon;
5135 5136
            /* err == 0 indicates no balloon support, so ignore it */
        }
5137
    }
5138

5139 5140 5141 5142
    if ((flags & VIR_DOMAIN_XML_MIGRATABLE))
        flags |= QEMU_DOMAIN_FORMAT_LIVE_FLAGS;

    ret = qemuDomainFormatXML(driver, vm, flags);
5143 5144

cleanup:
5145
    if (vm)
5146
        virObjectUnlock(vm);
5147
    return ret;
D
Daniel P. Berrange 已提交
5148 5149 5150
}


5151 5152 5153 5154
static char *qemuConnectDomainXMLFromNative(virConnectPtr conn,
                                            const char *format,
                                            const char *config,
                                            unsigned int flags)
E
Eric Blake 已提交
5155
{
5156
    virQEMUDriverPtr driver = conn->privateData;
5157 5158
    virDomainDefPtr def = NULL;
    char *xml = NULL;
5159
    virCapsPtr caps = NULL;
5160

E
Eric Blake 已提交
5161 5162
    virCheckFlags(0, NULL);

5163
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
5164 5165
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
5166 5167 5168
        goto cleanup;
    }

5169 5170 5171
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

5172
    def = qemuParseCommandLineString(caps, driver->xmlopt, config,
5173
                                     NULL, NULL, NULL);
5174 5175 5176
    if (!def)
        goto cleanup;

5177 5178 5179 5180 5181 5182
    if (!def->name &&
        !(def->name = strdup("unnamed"))) {
        virReportOOMError();
        goto cleanup;
    }

5183
    xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE);
5184 5185 5186

cleanup:
    virDomainDefFree(def);
5187
    virObjectUnref(caps);
5188 5189 5190
    return xml;
}

5191 5192 5193 5194
static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
                                          const char *format,
                                          const char *xmlData,
                                          unsigned int flags)
E
Eric Blake 已提交
5195
{
5196
    virQEMUDriverPtr driver = conn->privateData;
5197
    virDomainDefPtr def = NULL;
5198
    virDomainChrSourceDef monConfig;
5199
    virQEMUCapsPtr qemuCaps = NULL;
T
tangchen 已提交
5200
    bool monitor_json = false;
E
Eric Blake 已提交
5201
    virCommandPtr cmd = NULL;
5202 5203
    char *ret = NULL;
    int i;
5204
    virQEMUDriverConfigPtr cfg;
5205
    virCapsPtr caps = NULL;
5206

E
Eric Blake 已提交
5207 5208
    virCheckFlags(0, NULL);

5209
    cfg = virQEMUDriverGetConfig(driver);
5210

5211
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
5212 5213
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
5214 5215 5216
        goto cleanup;
    }

5217 5218 5219
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

5220
    def = virDomainDefParseString(xmlData, caps, driver->xmlopt,
M
Matthias Bolte 已提交
5221
                                  QEMU_EXPECTED_VIRT_TYPES, 0);
5222 5223 5224
    if (!def)
        goto cleanup;

5225
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
5226 5227
        goto cleanup;

5228 5229
    /* Since we're just exporting args, we can't do bridge/network/direct
     * setups, since libvirt will normally create TAP/macvtap devices
5230 5231 5232
     * directly. We convert those configs into generic 'ethernet'
     * config and assume the user has suitable 'ifup-qemu' scripts
     */
5233
    for (i = 0; i < def->nnets; i++) {
5234
        virDomainNetDefPtr net = def->nets[i];
5235
        int bootIndex = net->info.bootIndex;
5236 5237
        char *model = net->model;

5238 5239 5240 5241
        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
            int actualType = virDomainNetGetActualType(net);
            const char *brname;

5242
            VIR_FREE(net->data.network.name);
5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254
            VIR_FREE(net->data.network.portgroup);
            if ((actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
                (brname = virDomainNetGetActualBridgeName(net))) {

                char *brnamecopy = strdup(brname);
                if (!brnamecopy) {
                    virReportOOMError();
                    goto cleanup;
                }

                virDomainActualNetDefFree(net->data.network.actual);

5255
                memset(net, 0, sizeof(*net));
5256 5257

                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5258
                net->script = NULL;
5259 5260 5261 5262 5263 5264 5265
                net->data.ethernet.dev = brnamecopy;
                net->data.ethernet.ipaddr = NULL;
            } else {
                /* actualType is either NETWORK or DIRECT. In either
                 * case, the best we can do is NULL everything out.
                 */
                virDomainActualNetDefFree(net->data.network.actual);
5266
                memset(net, 0, sizeof(*net));
5267 5268

                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5269
                net->script = NULL;
5270 5271 5272 5273 5274
                net->data.ethernet.dev = NULL;
                net->data.ethernet.ipaddr = NULL;
            }
        } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
            VIR_FREE(net->data.direct.linkdev);
5275

5276
            memset(net, 0, sizeof(*net));
5277 5278

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5279
            net->script = NULL;
5280 5281 5282
            net->data.ethernet.dev = NULL;
            net->data.ethernet.ipaddr = NULL;
        } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
5283
            char *script = net->script;
5284 5285 5286
            char *brname = net->data.bridge.brname;
            char *ipaddr = net->data.bridge.ipaddr;

5287
            memset(net, 0, sizeof(*net));
5288 5289

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5290
            net->script = script;
5291 5292 5293
            net->data.ethernet.dev = brname;
            net->data.ethernet.ipaddr = ipaddr;
        }
5294

5295
        VIR_FREE(net->virtPortProfile);
5296
        net->info.bootIndex = bootIndex;
5297
        net->model = model;
5298 5299
    }

5300
    monitor_json = virQEMUCapsGet(qemuCaps, QEMU_CAPS_MONITOR_JSON);
T
tangchen 已提交
5301

5302
    if (qemuProcessPrepareMonitorChr(cfg, &monConfig, def->name) < 0)
5303
        goto cleanup;
5304

5305
    if (qemuAssignDeviceAliases(def, qemuCaps) < 0)
5306 5307
        goto cleanup;

5308 5309 5310
    if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
        goto cleanup;

5311
    /* do fake auto-alloc of graphics ports, if such config is used */
5312
    for (i = 0; i < def->ngraphics; ++i) {
5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324
        virDomainGraphicsDefPtr graphics = def->graphics[i];
        if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
            !graphics->data.vnc.socket && graphics->data.vnc.autoport) {
            graphics->data.vnc.port = 5900;
        } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
            int j;
            bool needTLSPort = false;
            bool needPort = false;
            int defaultMode = graphics->data.spice.defaultMode;

            if (graphics->data.spice.autoport) {
                /* check if tlsPort or port need allocation */
5325
                for (j = 0; j < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST; j++) {
5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362
                    switch (graphics->data.spice.channels[j]) {
                    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
                        needTLSPort = true;
                        break;

                    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
                        needPort = true;
                        break;

                    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
                        switch (defaultMode) {
                        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
                            needTLSPort = true;
                            break;

                        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
                            needPort = true;
                            break;

                        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
                            needTLSPort = true;
                            needPort = true;
                            break;
                        }
                        break;
                    }
                }
            }

            if (needPort || graphics->data.spice.port == -1)
                graphics->data.spice.port = 5901;

            if (needTLSPort || graphics->data.spice.tlsPort == -1)
                graphics->data.spice.tlsPort = 5902;
        }
    }

5363
    if (!(cmd = qemuBuildCommandLine(conn, driver, def,
5364
                                     &monConfig, monitor_json, qemuCaps,
5365 5366
                                     NULL, -1, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
                                     &buildCommandLineCallbacks)))
5367 5368
        goto cleanup;

E
Eric Blake 已提交
5369
    ret = virCommandToString(cmd);
5370 5371 5372

cleanup:

5373
    virObjectUnref(qemuCaps);
E
Eric Blake 已提交
5374
    virCommandFree(cmd);
5375
    virDomainDefFree(def);
5376
    virObjectUnref(caps);
5377
    virObjectUnref(cfg);
5378 5379 5380 5381
    return ret;
}


5382 5383
static int qemuConnectListDefinedDomains(virConnectPtr conn,
                                         char **const names, int nnames) {
5384
    virQEMUDriverPtr driver = conn->privateData;
5385
    int n;
5386

5387
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames);
5388
    return n;
D
Daniel P. Berrange 已提交
5389 5390
}

5391
static int qemuConnectNumOfDefinedDomains(virConnectPtr conn) {
5392
    virQEMUDriverPtr driver = conn->privateData;
5393
    int n;
5394

5395
    n = virDomainObjListNumOfDomains(driver->domains, 0);
5396

5397
    return n;
D
Daniel P. Berrange 已提交
5398 5399 5400
}


5401 5402
static int
qemuDomainObjStart(virConnectPtr conn,
5403
                   virQEMUDriverPtr driver,
5404
                   virDomainObjPtr vm,
5405
                   unsigned int flags)
J
Jiri Denemark 已提交
5406 5407 5408
{
    int ret = -1;
    char *managed_save;
5409 5410 5411 5412
    bool start_paused = (flags & VIR_DOMAIN_START_PAUSED) != 0;
    bool autodestroy = (flags & VIR_DOMAIN_START_AUTODESTROY) != 0;
    bool bypass_cache = (flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0;
    bool force_boot = (flags & VIR_DOMAIN_START_FORCE_BOOT) != 0;
5413 5414 5415
    unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;

    start_flags |= start_paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
5416
    start_flags |= autodestroy ? VIR_QEMU_PROCESS_START_AUTODESTROY : 0;
J
Jiri Denemark 已提交
5417 5418 5419

    /*
     * If there is a managed saved state restore it instead of starting
5420
     * from scratch. The old state is removed once the restoring succeeded.
J
Jiri Denemark 已提交
5421 5422
     */
    managed_save = qemuDomainManagedSavePath(driver, vm);
5423 5424 5425 5426

    if (!managed_save)
        goto cleanup;

E
Eric Blake 已提交
5427
    if (virFileExists(managed_save)) {
5428 5429 5430 5431 5432 5433 5434
        if (force_boot) {
            if (unlink(managed_save) < 0) {
                virReportSystemError(errno,
                                     _("cannot remove managed save file %s"),
                                     managed_save);
                goto cleanup;
            }
5435
            vm->hasManagedSave = false;
5436 5437
        } else {
            ret = qemuDomainObjRestore(conn, driver, vm, managed_save,
5438
                                       start_paused, bypass_cache);
J
Jiri Denemark 已提交
5439

5440 5441 5442 5443 5444 5445 5446
            if (ret == 0) {
                if (unlink(managed_save) < 0)
                    VIR_WARN("Failed to remove the managed state %s", managed_save);
                else
                    vm->hasManagedSave = false;
            }

E
Eric Blake 已提交
5447 5448 5449 5450
            if (ret > 0)
                VIR_WARN("Ignoring incomplete managed state %s", managed_save);
            else
                goto cleanup;
5451
        }
J
Jiri Denemark 已提交
5452 5453
    }

5454 5455
    ret = qemuProcessStart(conn, driver, vm, NULL, -1, NULL, NULL,
                           VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
5456
    virDomainAuditStart(vm, "booted", ret >= 0);
5457
    if (ret >= 0) {
J
Jiri Denemark 已提交
5458 5459 5460 5461
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
5462
        if (event) {
J
Jiri Denemark 已提交
5463
            qemuDomainEventQueue(driver, event);
5464 5465 5466 5467 5468 5469 5470 5471
            if (start_paused) {
                event = virDomainEventNewFromObj(vm,
                                                 VIR_DOMAIN_EVENT_SUSPENDED,
                                                 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
                if (event)
                    qemuDomainEventQueue(driver, event);
            }
        }
J
Jiri Denemark 已提交
5472 5473 5474 5475 5476 5477 5478
    }

cleanup:
    VIR_FREE(managed_save);
    return ret;
}

5479
static int
5480
qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
5481
{
5482
    virQEMUDriverPtr driver = dom->conn->privateData;
5483 5484
    virDomainObjPtr vm;
    int ret = -1;
5485

5486
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
5487
                  VIR_DOMAIN_START_AUTODESTROY |
5488 5489
                  VIR_DOMAIN_START_BYPASS_CACHE |
                  VIR_DOMAIN_START_FORCE_BOOT, -1);
5490

5491 5492
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
5493

5494
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5495 5496 5497
        goto cleanup;

    if (virDomainObjIsActive(vm)) {
5498 5499
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is already running"));
5500 5501 5502
        goto endjob;
    }

5503
    if (qemuDomainObjStart(dom->conn, driver, vm, flags) < 0)
5504 5505 5506
        goto endjob;

    ret = 0;
5507

5508
endjob:
5509
    if (qemuDomainObjEndJob(driver, vm) == 0)
5510
        vm = NULL;
5511

5512
cleanup:
5513
    if (vm)
5514
        virObjectUnlock(vm);
5515
    return ret;
D
Daniel P. Berrange 已提交
5516 5517
}

5518
static int
5519
qemuDomainCreate(virDomainPtr dom)
5520
{
5521
    return qemuDomainCreateWithFlags(dom, 0);
5522 5523
}

5524
static virDomainPtr qemuDomainDefineXML(virConnectPtr conn, const char *xml) {
5525
    virQEMUDriverPtr driver = conn->privateData;
5526
    virDomainDefPtr def = NULL;
5527
    virDomainDefPtr oldDef = NULL;
5528
    virDomainObjPtr vm = NULL;
5529
    virDomainPtr dom = NULL;
5530
    virDomainEventPtr event = NULL;
5531
    virQEMUCapsPtr qemuCaps = NULL;
5532
    virQEMUDriverConfigPtr cfg;
5533
    virCapsPtr caps = NULL;
5534

5535
    cfg = virQEMUDriverGetConfig(driver);
5536 5537 5538 5539

    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

5540
    if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
M
Matthias Bolte 已提交
5541
                                        QEMU_EXPECTED_VIRT_TYPES,
5542
                                        VIR_DOMAIN_XML_INACTIVE)))
5543
        goto cleanup;
5544

5545
    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
5546 5547
        goto cleanup;

5548
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
5549 5550
        goto cleanup;

5551
    if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
5552 5553
        goto cleanup;

5554
    if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
5555 5556
        goto cleanup;

5557
    if (!(vm = virDomainObjListAdd(driver->domains, def,
5558
                                   driver->xmlopt,
5559
                                   0, &oldDef)))
5560 5561
        goto cleanup;

5562
    def = NULL;
E
Eric Blake 已提交
5563 5564 5565
    if (virDomainHasDiskMirror(vm)) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, "%s",
                       _("domain has active block copy job"));
5566
        virDomainObjAssignDef(vm, NULL, false, NULL);
E
Eric Blake 已提交
5567 5568
        goto cleanup;
    }
5569
    vm->persistent = 1;
5570

5571
    if (virDomainSaveConfig(cfg->configDir,
5572
                            vm->newDef ? vm->newDef : vm->def) < 0) {
5573
        if (oldDef) {
M
Michal Privoznik 已提交
5574 5575 5576 5577
            /* There is backup so this VM was defined before.
             * Just restore the backup. */
            VIR_INFO("Restoring domain '%s' definition", vm->def->name);
            if (virDomainObjIsActive(vm))
5578
                vm->newDef = oldDef;
M
Michal Privoznik 已提交
5579
            else
5580 5581
                vm->def = oldDef;
            oldDef = NULL;
M
Michal Privoznik 已提交
5582 5583 5584 5585 5586 5587
        } else {
            /* Brand new domain. Remove it */
            VIR_INFO("Deleting domain '%s'", vm->def->name);
            qemuDomainRemoveInactive(driver, vm);
            vm = NULL;
        }
5588
        goto cleanup;
5589 5590
    }

5591 5592
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
5593
                                     !oldDef ?
5594 5595
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
5596

5597
    VIR_INFO("Creating domain '%s'", vm->def->name);
5598
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
5599
    if (dom) dom->id = vm->def->id;
5600 5601

cleanup:
5602
    virDomainDefFree(oldDef);
5603
    virDomainDefFree(def);
5604
    if (vm)
5605
        virObjectUnlock(vm);
5606 5607
    if (event)
        qemuDomainEventQueue(driver, event);
5608
    virObjectUnref(qemuCaps);
5609
    virObjectUnref(caps);
5610
    virObjectUnref(cfg);
5611
    return dom;
D
Daniel P. Berrange 已提交
5612 5613
}

5614 5615
static int
qemuDomainUndefineFlags(virDomainPtr dom,
5616
                        unsigned int flags)
5617
{
5618
    virQEMUDriverPtr driver = dom->conn->privateData;
5619
    virDomainObjPtr vm;
5620
    virDomainEventPtr event = NULL;
5621
    char *name = NULL;
5622
    int ret = -1;
5623
    int nsnapshots;
5624
    virQEMUDriverConfigPtr cfg = NULL;
D
Daniel P. Berrange 已提交
5625

5626 5627
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
5628

5629 5630
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
5631

5632
    cfg = virQEMUDriverGetConfig(driver);
D
Daniel P. Berrange 已提交
5633

5634
    if (!vm->persistent) {
5635 5636
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
5637 5638 5639
        goto cleanup;
    }

5640
    if (!virDomainObjIsActive(vm) &&
5641
        (nsnapshots = virDomainSnapshotObjListNum(vm->snapshots, NULL, 0))) {
5642
        if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
5643 5644 5645 5646
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("cannot delete inactive domain with %d "
                             "snapshots"),
                           nsnapshots);
5647 5648
            goto cleanup;
        }
5649
        if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0)
5650
            goto cleanup;
5651 5652
    }

5653 5654 5655 5656 5657 5658 5659
    name = qemuDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
5660 5661 5662
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed "
                                 "save image"));
5663 5664 5665
                goto cleanup;
            }
        } else {
5666 5667 5668
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
5669 5670 5671 5672
            goto cleanup;
        }
    }

5673
    if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
5674
        goto cleanup;
D
Daniel P. Berrange 已提交
5675

5676 5677 5678
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
5679

5680
    VIR_INFO("Undefining domain '%s'", vm->def->name);
5681 5682 5683 5684 5685 5686 5687 5688

    /* If the domain is active, keep it running but set it as transient.
     * domainDestroy and domainShutdown will take care of removing the
     * domain obj from the hash table.
     */
    if (virDomainObjIsActive(vm)) {
        vm->persistent = 0;
    } else {
5689
        qemuDomainRemoveInactive(driver, vm);
5690 5691 5692
        vm = NULL;
    }

5693
    ret = 0;
D
Daniel P. Berrange 已提交
5694

5695
cleanup:
5696
    VIR_FREE(name);
5697
    if (vm)
5698
        virObjectUnlock(vm);
5699 5700
    if (event)
        qemuDomainEventQueue(driver, event);
5701
    virObjectUnref(cfg);
5702
    return ret;
D
Daniel P. Berrange 已提交
5703 5704
}

5705
static int
5706
qemuDomainUndefine(virDomainPtr dom)
5707 5708 5709 5710
{
    return qemuDomainUndefineFlags(dom, 0);
}

5711
static int
5712
qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
5713
                               virQEMUDriverPtr driver,
5714
                               virDomainObjPtr vm,
5715
                               virDomainDeviceDefPtr dev)
5716 5717
{
    virDomainDiskDefPtr disk = dev->data.disk;
5718 5719 5720
    virDomainDiskDefPtr orig_disk = NULL;
    virDomainDeviceDefPtr dev_copy = NULL;
    virDomainDiskDefPtr tmp = NULL;
5721
    virCgroupPtr cgroup = NULL;
5722
    virCapsPtr caps = NULL;
5723
    int ret = -1;
5724

5725
    if (disk->driverName != NULL && !STREQ(disk->driverName, "qemu")) {
5726 5727 5728
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported driver name '%s' for disk '%s'"),
                       disk->driverName, disk->src);
5729 5730 5731
        goto end;
    }

5732 5733 5734
    if (qemuTranslateDiskSourcePool(conn, disk) < 0)
        goto end;

5735
    if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
5736 5737
        goto end;

5738
    if (qemuSetUnprivSGIO(dev) < 0)
5739 5740
        goto end;

5741 5742 5743
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
        goto end;

5744 5745
    if (qemuSetupDiskCgroup(vm, disk) < 0)
        goto end;
5746

5747 5748 5749
    switch (disk->device)  {
    case VIR_DOMAIN_DISK_DEVICE_CDROM:
    case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764
        if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
                                                       disk->bus, disk->dst))) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("No device with bus '%s' and target '%s'"),
                           virDomainDiskBusTypeToString(disk->bus),
                           disk->dst);
            goto end;
        }

        if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
            goto end;

        tmp = dev->data.disk;
        dev->data.disk = orig_disk;

5765 5766
        if (!(dev_copy = virDomainDeviceDefCopy(dev, vm->def,
                                                caps, driver->xmlopt))) {
5767 5768 5769 5770 5771 5772
            dev->data.disk = tmp;
            goto end;
        }
        dev->data.disk = tmp;

        ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, false);
5773 5774 5775
        /* 'disk' must not be accessed now - it has been free'd.
         * 'orig_disk' now points to the new disk, while 'dev_copy'
         * now points to the old disk */
5776 5777 5778 5779

        /* Need to remove the shared disk entry for the original disk src
         * if the operation is either ejecting or updating.
         */
5780
        if (ret == 0)
5781 5782
            ignore_value(qemuRemoveSharedDevice(driver, dev_copy,
                                                vm->def->name));
5783 5784
        break;
    case VIR_DOMAIN_DISK_DEVICE_DISK:
5785
    case VIR_DOMAIN_DISK_DEVICE_LUN:
5786 5787
        if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
5788 5789
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("disk device='lun' is not supported for usb bus"));
5790 5791
                break;
            }
5792
            ret = qemuDomainAttachUsbMassstorageDevice(conn, driver, vm,
5793
                                                       disk);
5794
        } else if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
5795
            ret = qemuDomainAttachVirtioDiskDevice(conn, driver, vm, disk);
5796
        } else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
5797
            ret = qemuDomainAttachSCSIDisk(conn, driver, vm, disk);
5798
        } else {
5799 5800 5801
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk bus '%s' cannot be hotplugged."),
                           virDomainDiskBusTypeToString(disk->bus));
5802
        }
5803 5804
        break;
    default:
5805 5806 5807
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk device type '%s' cannot be hotplugged"),
                       virDomainDiskDeviceTypeToString(disk->device));
5808 5809 5810 5811
        break;
    }

    if (ret != 0 && cgroup) {
5812
        if (qemuTeardownDiskCgroup(vm, disk) < 0)
5813 5814 5815
            VIR_WARN("Failed to teardown cgroup for disk path %s",
                     NULLSTR(disk->src));
    }
5816

5817
end:
5818
    if (ret != 0)
5819
        ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
5820 5821
    virObjectUnref(caps);
    virDomainDeviceDefFree(dev_copy);
5822 5823 5824 5825
    return ret;
}

static int
5826
qemuDomainAttachDeviceControllerLive(virQEMUDriverPtr driver,
5827
                                     virDomainObjPtr vm,
5828
                                     virDomainDeviceDefPtr dev)
5829 5830 5831 5832 5833 5834
{
    virDomainControllerDefPtr cont = dev->data.controller;
    int ret = -1;

    switch (cont->type) {
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5835
        ret = qemuDomainAttachPciControllerDevice(driver, vm, cont);
5836 5837
        break;
    default:
5838
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5839
                       _("'%s' controller cannot be hotplugged."),
5840
                       virDomainControllerTypeToString(cont->type));
5841 5842 5843 5844 5845 5846 5847 5848
        break;
    }
    return ret;
}

static int
qemuDomainAttachDeviceLive(virDomainObjPtr vm,
                           virDomainDeviceDefPtr dev,
5849
                           virDomainPtr dom)
5850
{
5851
    virQEMUDriverPtr driver = dom->conn->privateData;
5852 5853 5854 5855
    int ret = -1;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
5856
        qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, -1);
5857
        ret = qemuDomainAttachDeviceDiskLive(dom->conn, driver, vm, dev);
5858 5859 5860 5861 5862
        if (!ret)
            dev->data.disk = NULL;
        break;

    case VIR_DOMAIN_DEVICE_CONTROLLER:
5863
        ret = qemuDomainAttachDeviceControllerLive(driver, vm, dev);
5864 5865 5866 5867
        if (!ret)
            dev->data.controller = NULL;
        break;

5868 5869 5870 5871 5872 5873 5874
    case VIR_DOMAIN_DEVICE_LEASE:
        ret = qemuDomainAttachLease(driver, vm,
                                    dev->data.lease);
        if (ret == 0)
            dev->data.lease = NULL;
        break;

5875
    case VIR_DOMAIN_DEVICE_NET:
5876
        qemuDomainObjCheckNetTaint(driver, vm, dev->data.net, -1);
5877
        ret = qemuDomainAttachNetDevice(dom->conn, driver, vm,
5878
                                        dev->data.net);
5879 5880 5881 5882 5883 5884
        if (!ret)
            dev->data.net = NULL;
        break;

    case VIR_DOMAIN_DEVICE_HOSTDEV:
        ret = qemuDomainAttachHostDevice(driver, vm,
5885
                                         dev->data.hostdev);
5886 5887 5888 5889
        if (!ret)
            dev->data.hostdev = NULL;
        break;

5890 5891 5892 5893 5894 5895 5896
    case VIR_DOMAIN_DEVICE_REDIRDEV:
        ret = qemuDomainAttachRedirdevDevice(driver, vm,
                                             dev->data.redirdev);
        if (!ret)
            dev->data.redirdev = NULL;
        break;

5897
    default:
5898 5899 5900
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("device type '%s' cannot be attached"),
                       virDomainDeviceTypeToString(dev->type));
5901 5902 5903 5904 5905 5906 5907
        break;
    }

    return ret;
}

static int
5908
qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
5909
                               virDomainObjPtr vm,
5910
                               virDomainDeviceDefPtr dev)
5911 5912 5913 5914 5915 5916
{
    virDomainDiskDefPtr disk = dev->data.disk;
    int ret = -1;

    switch (disk->device) {
    case VIR_DOMAIN_DISK_DEVICE_DISK:
5917
    case VIR_DOMAIN_DISK_DEVICE_LUN:
5918
        if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)
5919
            ret = qemuDomainDetachVirtioDiskDevice(driver, vm, dev);
O
Osier Yang 已提交
5920 5921
        else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
                 disk->bus == VIR_DOMAIN_DISK_BUS_USB)
5922
            ret = qemuDomainDetachDiskDevice(driver, vm, dev);
5923
        else
5924 5925
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This type of disk cannot be hot unplugged"));
5926 5927
        break;
    default:
5928 5929
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk device type '%s' cannot be detached"),
5930
                       virDomainDiskDeviceTypeToString(disk->device));
5931 5932
        break;
    }
5933

5934
    if (ret == 0)
5935
        ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
5936

5937 5938 5939 5940
    return ret;
}

static int
5941
qemuDomainDetachDeviceControllerLive(virQEMUDriverPtr driver,
5942
                                     virDomainObjPtr vm,
5943
                                     virDomainDeviceDefPtr dev)
5944 5945 5946 5947 5948 5949
{
    virDomainControllerDefPtr cont = dev->data.controller;
    int ret = -1;

    switch (cont->type) {
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5950
        ret = qemuDomainDetachPciControllerDevice(driver, vm, dev);
5951 5952
        break;
    default :
5953
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5954
                       _("'%s' controller cannot be hotunplugged."),
5955
                       virDomainControllerTypeToString(cont->type));
5956 5957 5958 5959 5960 5961 5962
    }
    return ret;
}

static int
qemuDomainDetachDeviceLive(virDomainObjPtr vm,
                           virDomainDeviceDefPtr dev,
5963
                           virDomainPtr dom)
5964
{
5965
    virQEMUDriverPtr driver = dom->conn->privateData;
5966 5967 5968 5969
    int ret = -1;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
5970
        ret = qemuDomainDetachDeviceDiskLive(driver, vm, dev);
5971 5972
        break;
    case VIR_DOMAIN_DEVICE_CONTROLLER:
5973
        ret = qemuDomainDetachDeviceControllerLive(driver, vm, dev);
5974
        break;
5975 5976 5977
    case VIR_DOMAIN_DEVICE_LEASE:
        ret = qemuDomainDetachLease(driver, vm, dev->data.lease);
        break;
5978
    case VIR_DOMAIN_DEVICE_NET:
5979
        ret = qemuDomainDetachNetDevice(driver, vm, dev);
5980 5981
        break;
    case VIR_DOMAIN_DEVICE_HOSTDEV:
5982
        ret = qemuDomainDetachHostDevice(driver, vm, dev);
5983 5984
        break;
    default:
5985 5986
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("This type of device cannot be hot unplugged"));
5987 5988 5989 5990 5991 5992
        break;
    }

    return ret;
}

5993
static int
5994 5995
qemuDomainChangeDiskMediaLive(virConnectPtr conn,
                              virDomainObjPtr vm,
5996
                              virDomainDeviceDefPtr dev,
5997
                              virQEMUDriverPtr driver,
5998 5999 6000
                              bool force)
{
    virDomainDiskDefPtr disk = dev->data.disk;
6001 6002 6003 6004
    virDomainDiskDefPtr orig_disk = NULL;
    virDomainDiskDefPtr tmp = NULL;
    virDomainDeviceDefPtr dev_copy = NULL;
    virCapsPtr caps = NULL;
6005
    int ret = -1;
6006

6007 6008 6009
    if (qemuTranslateDiskSourcePool(conn, disk) < 0)
        goto end;

6010 6011 6012
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
        goto end;

6013 6014
    if (qemuSetupDiskCgroup(vm, disk) < 0)
        goto end;
6015 6016 6017 6018

    switch (disk->device) {
    case VIR_DOMAIN_DISK_DEVICE_CDROM:
    case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033
        if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
                                                       disk->bus, disk->dst))) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("No device with bus '%s' and target '%s'"),
                           virDomainDiskBusTypeToString(disk->bus),
                           disk->dst);
            goto end;
        }

        if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
            goto end;

        tmp = dev->data.disk;
        dev->data.disk = orig_disk;

6034 6035
        if (!(dev_copy = virDomainDeviceDefCopy(dev, vm->def,
                                                caps, driver->xmlopt))) {
6036 6037 6038 6039 6040
            dev->data.disk = tmp;
            goto end;
        }
        dev->data.disk = tmp;

6041
        /* Add the new disk src into shared disk hash table */
6042
        if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
6043 6044
            goto end;

6045
        ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, force);
6046 6047 6048 6049 6050 6051 6052
        /* 'disk' must not be accessed now - it has been freed.
         * 'orig_disk' now points to the new disk, while 'dev_copy'
         * now points to the old disk */

        /* Need to remove the shared disk entry for the original
         * disk src if the operation is either ejecting or updating.
         */
6053
        if (ret == 0) {
6054
            dev->data.disk = NULL;
6055 6056
            ignore_value(qemuRemoveSharedDevice(driver, dev_copy,
                                                vm->def->name));
6057
        }
6058 6059
        break;
    default:
6060 6061 6062
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk bus '%s' cannot be updated."),
                       virDomainDiskBusTypeToString(disk->bus));
6063 6064 6065
        break;
    }

6066 6067 6068 6069 6070
    if (ret != 0 &&
        qemuTeardownDiskCgroup(vm, disk) < 0)
        VIR_WARN("Failed to teardown cgroup for disk path %s",
                 NULLSTR(disk->src));

6071
end:
6072 6073
    virObjectUnref(caps);
    virDomainDeviceDefFree(dev_copy);
6074 6075 6076 6077
    return ret;
}

static int
6078 6079
qemuDomainUpdateDeviceLive(virConnectPtr conn,
                           virDomainObjPtr vm,
6080 6081 6082 6083
                           virDomainDeviceDefPtr dev,
                           virDomainPtr dom,
                           bool force)
{
6084
    virQEMUDriverPtr driver = dom->conn->privateData;
6085 6086 6087 6088
    int ret = -1;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
6089
        ret = qemuDomainChangeDiskMediaLive(conn, vm, dev, driver, force);
6090 6091 6092 6093
        break;
    case VIR_DOMAIN_DEVICE_GRAPHICS:
        ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
        break;
6094
    case VIR_DOMAIN_DEVICE_NET:
6095
        ret = qemuDomainChangeNet(driver, vm, dom, dev);
6096
        break;
6097
    default:
6098 6099 6100
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("device type '%s' cannot be updated"),
                       virDomainDeviceTypeToString(dev->type));
6101 6102 6103 6104 6105 6106
        break;
    }

    return ret;
}

6107
static int
6108
qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps,
6109
                             virDomainDefPtr vmdef,
6110 6111
                             virDomainDeviceDefPtr dev)
{
6112
    virDomainDiskDefPtr disk;
6113
    virDomainNetDefPtr net;
6114
    virDomainHostdevDefPtr hostdev;
6115
    virDomainLeaseDefPtr lease;
6116
    virDomainControllerDefPtr controller;
6117

6118
    switch (dev->type) {
6119 6120
    case VIR_DOMAIN_DEVICE_DISK:
        disk = dev->data.disk;
6121
        if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
6122 6123
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("target %s already exists"), disk->dst);
6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134
            return -1;
        }
        if (virDomainDiskInsert(vmdef, disk)) {
            virReportOOMError();
            return -1;
        }
        /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
        dev->data.disk = NULL;
        if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
            if (virDomainDefAddImplicitControllers(vmdef) < 0)
                return -1;
6135
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6136 6137 6138
            return -1;
        break;

6139 6140 6141 6142 6143 6144 6145
    case VIR_DOMAIN_DEVICE_NET:
        net = dev->data.net;
        if (virDomainNetInsert(vmdef, net)) {
            virReportOOMError();
            return -1;
        }
        dev->data.net = NULL;
6146
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6147 6148
            return -1;
        break;
6149

6150 6151 6152
    case VIR_DOMAIN_DEVICE_HOSTDEV:
        hostdev = dev->data.hostdev;
        if (virDomainHostdevFind(vmdef, hostdev, NULL) >= 0) {
6153
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6154
                           _("device is already in the domain configuration"));
6155 6156 6157 6158 6159 6160 6161
            return -1;
        }
        if (virDomainHostdevInsert(vmdef, hostdev)) {
            virReportOOMError();
            return -1;
        }
        dev->data.hostdev = NULL;
6162
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6163 6164 6165
            return -1;
        break;

6166 6167 6168
    case VIR_DOMAIN_DEVICE_LEASE:
        lease = dev->data.lease;
        if (virDomainLeaseIndex(vmdef, lease) >= 0) {
6169
            virReportError(VIR_ERR_OPERATION_INVALID,
6170 6171
                           _("Lease %s in lockspace %s already exists"),
                           lease->key, NULLSTR(lease->lockspace));
6172 6173 6174 6175 6176 6177 6178 6179 6180
            return -1;
        }
        if (virDomainLeaseInsert(vmdef, lease) < 0)
            return -1;

        /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
        dev->data.lease = NULL;
        break;

6181 6182 6183 6184
    case VIR_DOMAIN_DEVICE_CONTROLLER:
        controller = dev->data.controller;
        if (virDomainControllerFind(vmdef, controller->type,
                                    controller->idx) > 0) {
6185
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6186 6187 6188 6189 6190 6191 6192 6193
                           _("Target already exists"));
            return -1;
        }

        if (virDomainControllerInsert(vmdef, controller) < 0)
            return -1;
        dev->data.controller = NULL;

6194
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6195 6196 6197
            return -1;
        break;

6198
    default:
6199 6200
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("persistent attach of device is not supported"));
6201 6202 6203 6204 6205 6206 6207
         return -1;
    }
    return 0;
}


static int
6208
qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
6209 6210
                             virDomainDeviceDefPtr dev)
{
6211
    virDomainDiskDefPtr disk, det_disk;
6212
    virDomainNetDefPtr net;
6213
    virDomainHostdevDefPtr hostdev, det_hostdev;
6214
    virDomainLeaseDefPtr lease, det_lease;
6215 6216
    virDomainControllerDefPtr cont, det_cont;
    int idx;
6217
    char mac[VIR_MAC_STRING_BUFLEN];
6218

6219
    switch (dev->type) {
6220 6221
    case VIR_DOMAIN_DEVICE_DISK:
        disk = dev->data.disk;
6222
        if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
6223 6224
            virReportError(VIR_ERR_INVALID_ARG,
                           _("no target device %s"), disk->dst);
6225 6226
            return -1;
        }
6227
        virDomainDiskDefFree(det_disk);
6228
        break;
6229

6230 6231
    case VIR_DOMAIN_DEVICE_NET:
        net = dev->data.net;
6232 6233 6234 6235 6236 6237 6238 6239 6240
        idx = virDomainNetFindIdx(vmdef, net);
        if (idx == -2) {
            virReportError(VIR_ERR_OPERATION_FAILED,
                           _("multiple devices matching mac address %s found"),
                           virMacAddrFormat(&net->mac, mac));
            return -1;
        } else if (idx < 0) {
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("no matching network device was found"));
6241 6242
            return -1;
        }
6243 6244
        /* this is guaranteed to succeed */
        virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
6245
        break;
6246

6247 6248 6249
    case VIR_DOMAIN_DEVICE_HOSTDEV: {
        hostdev = dev->data.hostdev;
        if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
6250 6251
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("device not present in domain configuration"));
6252 6253 6254 6255 6256 6257 6258
            return -1;
        }
        virDomainHostdevRemove(vmdef, idx);
        virDomainHostdevDefFree(det_hostdev);
        break;
    }

6259 6260
    case VIR_DOMAIN_DEVICE_LEASE:
        lease = dev->data.lease;
6261
        if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
6262 6263 6264
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Lease %s in lockspace %s does not exist"),
                           lease->key, NULLSTR(lease->lockspace));
6265 6266
            return -1;
        }
6267
        virDomainLeaseDefFree(det_lease);
6268 6269
        break;

6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282
    case VIR_DOMAIN_DEVICE_CONTROLLER:
        cont = dev->data.controller;
        if ((idx = virDomainControllerFind(vmdef, cont->type,
                                           cont->idx)) < 0) {
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("device not present in domain configuration"));
            return -1;
        }
        det_cont = virDomainControllerRemove(vmdef, idx);
        virDomainControllerDefFree(det_cont);

        break;

6283
    default:
6284 6285
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("persistent detach of device is not supported"));
6286 6287 6288 6289 6290 6291
        return -1;
    }
    return 0;
}

static int
6292
qemuDomainUpdateDeviceConfig(virQEMUCapsPtr qemuCaps,
6293
                             virDomainDefPtr vmdef,
6294 6295
                             virDomainDeviceDefPtr dev)
{
6296
    virDomainDiskDefPtr orig, disk;
6297
    virDomainNetDefPtr net;
6298
    int pos;
6299 6300
    char mac[VIR_MAC_STRING_BUFLEN];

6301

6302
    switch (dev->type) {
6303 6304
    case VIR_DOMAIN_DEVICE_DISK:
        disk = dev->data.disk;
6305
        pos = virDomainDiskIndexByName(vmdef, disk->dst, false);
6306
        if (pos < 0) {
6307 6308
            virReportError(VIR_ERR_INVALID_ARG,
                           _("target %s doesn't exist."), disk->dst);
6309 6310 6311 6312 6313
            return -1;
        }
        orig = vmdef->disks[pos];
        if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
            !(orig->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) {
6314 6315
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("this disk doesn't support update"));
6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330
            return -1;
        }
        /*
         * Update 'orig'
         * We allow updating src/type//driverType/cachemode/
         */
        VIR_FREE(orig->src);
        orig->src = disk->src;
        orig->type = disk->type;
        orig->cachemode = disk->cachemode;
        if (disk->driverName) {
            VIR_FREE(orig->driverName);
            orig->driverName = disk->driverName;
            disk->driverName = NULL;
        }
6331 6332
        if (disk->format)
            orig->format = disk->format;
6333 6334
        disk->src = NULL;
        break;
6335 6336 6337

    case VIR_DOMAIN_DEVICE_NET:
        net = dev->data.net;
6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349
        pos = virDomainNetFindIdx(vmdef, net);
        if (pos == -2) {
            virMacAddrFormat(&net->mac, mac);
            virReportError(VIR_ERR_OPERATION_FAILED,
                           _("couldn't find matching device "
                             "with mac address %s"), mac);
            return -1;
        } else if (pos < 0) {
            virMacAddrFormat(&net->mac, mac);
            virReportError(VIR_ERR_OPERATION_FAILED,
                           _("couldn't find matching device "
                             "with mac address %s"), mac);
6350 6351 6352
            return -1;
        }

6353
        virDomainNetDefFree(vmdef->nets[pos]);
6354 6355 6356 6357

        vmdef->nets[pos] = net;
        dev->data.net = NULL;

6358
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6359 6360 6361
            return -1;
        break;

6362
    default:
6363 6364
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("persistent update of device is not supported"));
6365 6366 6367 6368 6369
        return -1;
    }
    return 0;
}

6370

6371 6372
static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                       unsigned int flags)
6373
{
6374
    virQEMUDriverPtr driver = dom->conn->privateData;
6375
    virDomainObjPtr vm = NULL;
6376
    virDomainDefPtr vmdef = NULL;
6377
    virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
6378
    int ret = -1;
6379
    unsigned int affect;
6380
    virQEMUCapsPtr qemuCaps = NULL;
6381
    qemuDomainObjPrivatePtr priv;
6382
    virQEMUDriverConfigPtr cfg = NULL;
6383
    virCapsPtr caps = NULL;
6384

6385
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6386
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
6387

6388 6389
    cfg = virQEMUDriverGetConfig(driver);

6390 6391
    affect = flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG);

6392 6393 6394
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

6395
    if (!(vm = qemuDomObjFromDomain(dom)))
6396
        goto cleanup;
6397

6398
    priv = vm->privateData;
6399

6400
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
6401
        goto cleanup;
6402

6403
    if (virDomainObjIsActive(vm)) {
6404
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
6405
            flags |= VIR_DOMAIN_AFFECT_LIVE;
6406
    } else {
6407
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
6408
            flags |= VIR_DOMAIN_AFFECT_CONFIG;
6409
        /* check consistency between flags and the vm state */
6410
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6411
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6412 6413
                           _("cannot do live update a device on "
                             "inactive domain"));
6414 6415
            goto endjob;
        }
6416
    }
6417

6418
    if ((flags & VIR_DOMAIN_AFFECT_CONFIG) && !vm->persistent) {
6419 6420
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                        _("cannot modify device on transient domain"));
6421 6422
         goto endjob;
    }
6423

6424 6425
    dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
                                             caps, driver->xmlopt,
6426 6427 6428 6429 6430 6431 6432 6433 6434 6435
                                             VIR_DOMAIN_XML_INACTIVE);
    if (dev == NULL)
        goto endjob;

    if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
        flags & VIR_DOMAIN_AFFECT_LIVE) {
        /* If we are affecting both CONFIG and LIVE
         * create a deep copy of device as adding
         * to CONFIG takes one instance.
         */
6436
        dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
6437
        if (!dev_copy)
6438
            goto endjob;
6439
    }
6440

6441 6442 6443
    if (priv->qemuCaps)
        qemuCaps = virObjectRef(priv->qemuCaps);
    else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, vm->def->emulator)))
6444 6445
        goto cleanup;

6446
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6447
        if (virDomainDefCompatibleDevice(vm->def, dev) < 0)
6448 6449
            goto endjob;

6450
        /* Make a copy for updated domain. */
6451
        vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
6452 6453
        if (!vmdef)
            goto endjob;
6454
        if ((ret = qemuDomainAttachDeviceConfig(qemuCaps, vmdef, dev)) < 0)
6455 6456 6457 6458
            goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6459 6460 6461
        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
            goto endjob;

6462
        if ((ret = qemuDomainAttachDeviceLive(vm, dev_copy, dom)) < 0)
6463
            goto endjob;
6464 6465
        /*
         * update domain status forcibly because the domain status may be
6466 6467
         * changed even if we failed to attach the device. For example,
         * a new controller may be created.
6468
         */
6469
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
6470
            ret = -1;
6471 6472
            goto endjob;
        }
6473
    }
6474

6475
    /* Finally, if no error until here, we can save config. */
6476
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6477
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
6478
        if (!ret) {
6479
            virDomainObjAssignDef(vm, vmdef, false, NULL);
6480 6481 6482
            vmdef = NULL;
        }
    }
6483 6484

endjob:
6485
    if (qemuDomainObjEndJob(driver, vm) == 0)
6486 6487 6488
        vm = NULL;

cleanup:
6489
    virObjectUnref(qemuCaps);
6490
    virDomainDefFree(vmdef);
6491 6492
    if (dev != dev_copy)
        virDomainDeviceDefFree(dev_copy);
6493 6494
    virDomainDeviceDefFree(dev);
    if (vm)
6495
        virObjectUnlock(vm);
6496
    virObjectUnref(caps);
6497
    virObjectUnref(cfg);
6498 6499 6500
    return ret;
}

6501 6502 6503
static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml)
{
    return qemuDomainAttachDeviceFlags(dom, xml,
6504
                                       VIR_DOMAIN_AFFECT_LIVE);
6505
}
6506

6507

6508 6509 6510 6511
static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
                                       const char *xml,
                                       unsigned int flags)
{
6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639
    virQEMUDriverPtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
    bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
    int ret = -1;
    unsigned int affect;
    virQEMUCapsPtr qemuCaps = NULL;
    qemuDomainObjPrivatePtr priv;
    virQEMUDriverConfigPtr cfg = NULL;
    virCapsPtr caps = NULL;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1);

    cfg = virQEMUDriverGetConfig(driver);

    affect = flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG);

    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    priv = vm->privateData;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (virDomainObjIsActive(vm)) {
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
            flags |= VIR_DOMAIN_AFFECT_LIVE;
    } else {
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
            flags |= VIR_DOMAIN_AFFECT_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot do live update a device on "
                             "inactive domain"));
            goto endjob;
        }
    }

    if ((flags & VIR_DOMAIN_AFFECT_CONFIG) && !vm->persistent) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                        _("cannot modify device on transient domain"));
         goto endjob;
    }

    dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
                                             caps, driver->xmlopt,
                                             VIR_DOMAIN_XML_INACTIVE);
    if (dev == NULL)
        goto endjob;

    if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
        flags & VIR_DOMAIN_AFFECT_LIVE) {
        /* If we are affecting both CONFIG and LIVE
         * create a deep copy of device as adding
         * to CONFIG takes one instance.
         */
        dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
        if (!dev_copy)
            goto endjob;
    }

    if (priv->qemuCaps)
        qemuCaps = virObjectRef(priv->qemuCaps);
    else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, vm->def->emulator)))
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        if (virDomainDefCompatibleDevice(vm->def, dev) < 0)
            goto endjob;

        /* Make a copy for updated domain. */
        vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
        if (!vmdef)
            goto endjob;

        if ((ret = qemuDomainUpdateDeviceConfig(qemuCaps, vmdef, dev)) < 0)
            goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
            goto endjob;

        if ((ret = qemuDomainUpdateDeviceLive(dom->conn, vm, dev_copy, dom, force)) < 0)
            goto endjob;
        /*
         * update domain status forcibly because the domain status may be
         * changed even if we failed to attach the device. For example,
         * a new controller may be created.
         */
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
            ret = -1;
            goto endjob;
        }
    }

    /* Finally, if no error until here, we can save config. */
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    virObjectUnref(qemuCaps);
    virDomainDefFree(vmdef);
    if (dev != dev_copy)
        virDomainDeviceDefFree(dev_copy);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(caps);
    virObjectUnref(cfg);
    return ret;
6640 6641
}

6642

6643 6644 6645
static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                       unsigned int flags)
{
6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770
    virQEMUDriverPtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
    int ret = -1;
    unsigned int affect;
    virQEMUCapsPtr qemuCaps = NULL;
    qemuDomainObjPrivatePtr priv;
    virQEMUDriverConfigPtr cfg = NULL;
    virCapsPtr caps = NULL;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    cfg = virQEMUDriverGetConfig(driver);

    affect = flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG);

    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    priv = vm->privateData;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (virDomainObjIsActive(vm)) {
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
            flags |= VIR_DOMAIN_AFFECT_LIVE;
    } else {
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
            flags |= VIR_DOMAIN_AFFECT_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot do live update a device on "
                             "inactive domain"));
            goto endjob;
        }
    }

    if ((flags & VIR_DOMAIN_AFFECT_CONFIG) && !vm->persistent) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                        _("cannot modify device on transient domain"));
         goto endjob;
    }

    dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
                                             caps, driver->xmlopt,
                                             VIR_DOMAIN_XML_INACTIVE);
    if (dev == NULL)
        goto endjob;

    if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
        flags & VIR_DOMAIN_AFFECT_LIVE) {
        /* If we are affecting both CONFIG and LIVE
         * create a deep copy of device as adding
         * to CONFIG takes one instance.
         */
        dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
        if (!dev_copy)
            goto endjob;
    }

    if (priv->qemuCaps)
        qemuCaps = virObjectRef(priv->qemuCaps);
    else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, vm->def->emulator)))
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        if (virDomainDefCompatibleDevice(vm->def, dev) < 0)
            goto endjob;

        /* Make a copy for updated domain. */
        vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
        if (!vmdef)
            goto endjob;
        if ((ret = qemuDomainDetachDeviceConfig(vmdef, dev)) < 0)
            goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
            goto endjob;

        if ((ret = qemuDomainDetachDeviceLive(vm, dev_copy, dom)) < 0)
            goto endjob;
        /*
         * update domain status forcibly because the domain status may be
         * changed even if we failed to attach the device. For example,
         * a new controller may be created.
         */
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
            ret = -1;
            goto endjob;
        }
    }

    /* Finally, if no error until here, we can save config. */
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    virObjectUnref(qemuCaps);
    virDomainDefFree(vmdef);
    if (dev != dev_copy)
        virDomainDeviceDefFree(dev_copy);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(caps);
    virObjectUnref(cfg);
    return ret;
6771 6772
}

6773 6774 6775
static int qemuDomainDetachDevice(virDomainPtr dom, const char *xml)
{
    return qemuDomainDetachDeviceFlags(dom, xml,
6776
                                       VIR_DOMAIN_AFFECT_LIVE);
6777 6778
}

6779 6780
static int qemuDomainGetAutostart(virDomainPtr dom,
                                  int *autostart) {
6781 6782
    virDomainObjPtr vm;
    int ret = -1;
6783

6784
    if (!(vm = qemuDomObjFromDomain(dom)))
6785
        goto cleanup;
6786 6787

    *autostart = vm->autostart;
6788
    ret = 0;
6789

6790
cleanup:
6791
    if (vm)
6792
        virObjectUnlock(vm);
6793
    return ret;
6794 6795
}

6796 6797
static int qemuDomainSetAutostart(virDomainPtr dom,
                                  int autostart) {
6798
    virQEMUDriverPtr driver = dom->conn->privateData;
6799
    virDomainObjPtr vm;
6800 6801
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
6802
    virQEMUDriverConfigPtr cfg = NULL;
6803

6804 6805 6806
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

6807
    cfg = virQEMUDriverGetConfig(driver);
6808

6809
    if (!vm->persistent) {
6810 6811
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
6812
        goto cleanup;
6813 6814
    }

6815 6816
    autostart = (autostart != 0);

6817
    if (vm->autostart != autostart) {
6818
        if ((configFile = virDomainConfigFile(cfg->configDir, vm->def->name)) == NULL)
6819
            goto cleanup;
6820
        if ((autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)) == NULL)
6821
            goto cleanup;
6822

6823
        if (autostart) {
6824
            if (virFileMakePath(cfg->autostartDir) < 0) {
6825
                virReportSystemError(errno,
6826
                                     _("cannot create autostart directory %s"),
6827
                                     cfg->autostartDir);
6828 6829
                goto cleanup;
            }
6830

6831
            if (symlink(configFile, autostartLink) < 0) {
6832
                virReportSystemError(errno,
6833 6834
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
6835 6836 6837 6838
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
6839
                virReportSystemError(errno,
6840 6841
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
6842 6843
                goto cleanup;
            }
6844 6845
        }

6846
        vm->autostart = autostart;
6847
    }
6848
    ret = 0;
6849

6850 6851 6852
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
6853
    if (vm)
6854
        virObjectUnlock(vm);
6855
    virObjectUnref(cfg);
6856
    return ret;
6857 6858
}

6859

6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892
/*
 * check whether the host supports CFS bandwidth
 *
 * Return 1 when CFS bandwidth is supported, 0 when CFS bandwidth is not
 * supported, -1 on error.
 */
static int qemuGetCpuBWStatus(virCgroupPtr cgroup)
{
    char *cfs_period_path = NULL;
    int ret = -1;

    if (!cgroup)
        return 0;

    if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
                                  "cpu.cfs_period_us", &cfs_period_path) < 0) {
        VIR_INFO("cannot get the path of cgroup CPU controller");
        ret = 0;
        goto cleanup;
    }

    if (access(cfs_period_path, F_OK) < 0) {
        ret = 0;
    } else {
        ret = 1;
    }

cleanup:
    VIR_FREE(cfs_period_path);
    return ret;
}


6893 6894
static char *qemuDomainGetSchedulerType(virDomainPtr dom,
                                        int *nparams)
6895
{
6896
    virQEMUDriverPtr driver = dom->conn->privateData;
6897
    char *ret = NULL;
6898
    int rc;
6899 6900 6901 6902 6903 6904 6905 6906 6907 6908
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;

    vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
    if (vm == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No such domain %s"), dom->uuid);
        goto cleanup;
    }
    priv = vm->privateData;
6909

6910
    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
6911 6912
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cgroup CPU controller is not mounted"));
6913
        goto cleanup;
6914 6915
    }

6916
    if (nparams) {
6917
        rc = qemuGetCpuBWStatus(priv->cgroup);
6918 6919 6920 6921 6922
        if (rc < 0)
            goto cleanup;
        else if (rc == 0)
            *nparams = 1;
        else
6923
            *nparams = 5;
6924
    }
6925 6926 6927

    ret = strdup("posix");
    if (!ret)
6928
        virReportOOMError();
6929 6930

cleanup:
6931 6932
    if (vm)
        virObjectUnlock(vm);
6933 6934 6935
    return ret;
}

6936 6937 6938 6939
/* deviceWeightStr in the form of /device/path,weight,/device/path,weight
 * for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800
 */
static int
6940 6941
qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
                               virBlkioDeviceWeightPtr *dw, size_t *size)
6942 6943 6944 6945 6946 6947 6948
{
    char *temp;
    int ndevices = 0;
    int nsep = 0;
    int i;
    virBlkioDeviceWeightPtr result = NULL;

6949 6950 6951 6952 6953 6954
    *dw = NULL;
    *size = 0;

    if (STREQ(deviceWeightStr, ""))
        return 0;

6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015
    temp = deviceWeightStr;
    while (temp) {
        temp = strchr(temp, ',');
        if (temp) {
            temp++;
            nsep++;
        }
    }

    /* A valid string must have even number of fields, hence an odd
     * number of commas.  */
    if (!(nsep & 1))
        goto error;

    ndevices = (nsep + 1) / 2;

    if (VIR_ALLOC_N(result, ndevices) < 0) {
        virReportOOMError();
        return -1;
    }

    i = 0;
    temp = deviceWeightStr;
    while (temp) {
        char *p = temp;

        /* device path */
        p = strchr(p, ',');
        if (!p)
            goto error;

        result[i].path = strndup(temp, p - temp);
        if (!result[i].path) {
            virReportOOMError();
            goto cleanup;
        }

        /* weight */
        temp = p + 1;

        if (virStrToLong_ui(temp, &p, 10, &result[i].weight) < 0)
            goto error;

        i++;

        if (*p == '\0')
            break;
        else if (*p != ',')
            goto error;
        temp = p + 1;
    }

    if (!i)
        VIR_FREE(result);

    *dw = result;
    *size = i;

    return 0;

error:
7016 7017
    virReportError(VIR_ERR_INVALID_ARG,
                   _("unable to parse device weight '%s'"), deviceWeightStr);
7018 7019 7020 7021 7022 7023
cleanup:
    virBlkioDeviceWeightArrayClear(result, ndevices);
    VIR_FREE(result);
    return -1;
}

7024 7025
/* Modify dest_array to reflect all device weight changes described in
 * src_array.  */
7026
static int
7027 7028 7029 7030
qemuDomainMergeDeviceWeights(virBlkioDeviceWeightPtr *dest_array,
                             size_t *dest_size,
                             virBlkioDeviceWeightPtr src_array,
                             size_t src_size)
7031 7032
{
    int i, j;
7033
    virBlkioDeviceWeightPtr dest, src;
7034

7035
    for (i = 0; i < src_size; i++) {
7036 7037
        bool found = false;

7038 7039 7040 7041
        src = &src_array[i];
        for (j = 0; j < *dest_size; j++) {
            dest = &(*dest_array)[j];
            if (STREQ(src->path, dest->path)) {
7042
                found = true;
7043
                dest->weight = src->weight;
7044 7045 7046 7047
                break;
            }
        }
        if (!found) {
7048
            if (!src->weight)
7049
                continue;
7050
            if (VIR_EXPAND_N(*dest_array, *dest_size, 1) < 0) {
7051 7052 7053
                virReportOOMError();
                return -1;
            }
7054 7055 7056 7057
            dest = &(*dest_array)[*dest_size - 1];
            dest->path = src->path;
            dest->weight = src->weight;
            src->path = NULL;
7058 7059 7060 7061 7062 7063
        }
    }

    return 0;
}

7064 7065 7066 7067 7068
static int
qemuDomainSetBlkioParameters(virDomainPtr dom,
                             virTypedParameterPtr params,
                             int nparams,
                             unsigned int flags)
7069
{
7070
    virQEMUDriverPtr driver = dom->conn->privateData;
7071 7072
    int i;
    virDomainObjPtr vm = NULL;
7073
    virDomainDefPtr persistentDef = NULL;
7074
    int ret = -1;
7075
    virQEMUDriverConfigPtr cfg = NULL;
7076
    virCapsPtr caps = NULL;
7077
    qemuDomainObjPrivatePtr priv;
7078

7079 7080
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
7081 7082 7083 7084 7085 7086 7087
    if (virTypedParameterArrayValidate(params, nparams,
                                       VIR_DOMAIN_BLKIO_WEIGHT,
                                       VIR_TYPED_PARAM_UINT,
                                       VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
                                       VIR_TYPED_PARAM_STRING,
                                       NULL) < 0)
        return -1;
7088

7089 7090 7091
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

7092
    priv = vm->privateData;
7093
    cfg = virQEMUDriverGetConfig(driver);
7094 7095
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;
7096

7097
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7098 7099
                                        &persistentDef) < 0)
        goto cleanup;
7100

7101
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7102
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
7103 7104
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("blkio cgroup isn't mounted"));
7105 7106 7107 7108
            goto cleanup;
        }
    }

7109
    ret = 0;
7110 7111
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        for (i = 0; i < nparams; i++) {
7112
            int rc;
7113 7114 7115 7116
            virTypedParameterPtr param = &params[i];

            if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
                if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
7117 7118
                    virReportError(VIR_ERR_INVALID_ARG, "%s",
                                   _("out of blkio weight range."));
7119 7120 7121
                    ret = -1;
                    continue;
                }
7122

7123
                rc = virCgroupSetBlkioWeight(priv->cgroup, params[i].value.ui);
7124 7125 7126 7127 7128
                if (rc != 0) {
                    virReportSystemError(-rc, "%s",
                                         _("unable to set blkio weight tunable"));
                    ret = -1;
                }
7129
            } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
7130
                size_t ndevices;
7131
                virBlkioDeviceWeightPtr devices = NULL;
7132 7133
                int j;

7134 7135 7136
                if (qemuDomainParseDeviceWeightStr(params[i].value.s,
                                                   &devices,
                                                   &ndevices) < 0) {
7137 7138 7139
                    ret = -1;
                    continue;
                }
7140
                for (j = 0; j < ndevices; j++) {
7141
                    rc = virCgroupSetBlkioDeviceWeight(priv->cgroup,
7142 7143
                                                       devices[j].path,
                                                       devices[j].weight);
7144 7145 7146 7147
                    if (rc < 0) {
                        virReportSystemError(-rc,
                                             _("Unable to set io device weight "
                                               "for path %s"),
7148
                                             devices[j].path);
7149 7150 7151
                        break;
                    }
                }
7152 7153
                if (j != ndevices ||
                    qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
7154 7155 7156 7157 7158
                                                 &vm->def->blkio.ndevices,
                                                 devices, ndevices) < 0)
                    ret = -1;
                virBlkioDeviceWeightArrayClear(devices, ndevices);
                VIR_FREE(devices);
7159
            }
7160
        }
E
Eric Blake 已提交
7161 7162 7163 7164
    }
    if (ret < 0)
        goto cleanup;
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
E
Eric Blake 已提交
7165 7166 7167
        /* Clang can't see that if we get here, persistentDef was set.  */
        sa_assert(persistentDef);

7168 7169 7170 7171 7172
        for (i = 0; i < nparams; i++) {
            virTypedParameterPtr param = &params[i];

            if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
                if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
7173 7174
                    virReportError(VIR_ERR_INVALID_ARG, "%s",
                                   _("out of blkio weight range."));
7175 7176 7177 7178 7179
                    ret = -1;
                    continue;
                }

                persistentDef->blkio.weight = params[i].value.ui;
7180 7181
            } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
                virBlkioDeviceWeightPtr devices = NULL;
7182
                size_t ndevices;
7183

7184 7185 7186
                if (qemuDomainParseDeviceWeightStr(params[i].value.s,
                                                   &devices,
                                                   &ndevices) < 0) {
7187 7188 7189
                    ret = -1;
                    continue;
                }
7190 7191
                if (qemuDomainMergeDeviceWeights(&persistentDef->blkio.devices,
                                                 &persistentDef->blkio.ndevices,
7192 7193 7194 7195
                                                 devices, ndevices) < 0)
                    ret = -1;
                virBlkioDeviceWeightArrayClear(devices, ndevices);
                VIR_FREE(devices);
7196 7197
            }
        }
A
Alex Jia 已提交
7198

7199
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
A
Alex Jia 已提交
7200
            ret = -1;
7201 7202 7203 7204
    }

cleanup:
    if (vm)
7205
        virObjectUnlock(vm);
7206
    virObjectUnref(caps);
7207
    virObjectUnref(cfg);
7208 7209 7210
    return ret;
}

7211 7212 7213 7214 7215
static int
qemuDomainGetBlkioParameters(virDomainPtr dom,
                             virTypedParameterPtr params,
                             int *nparams,
                             unsigned int flags)
7216
{
7217
    virQEMUDriverPtr driver = dom->conn->privateData;
7218
    int i, j;
7219
    virDomainObjPtr vm = NULL;
7220
    virDomainDefPtr persistentDef = NULL;
7221 7222 7223
    unsigned int val;
    int ret = -1;
    int rc;
7224
    virCapsPtr caps = NULL;
7225
    qemuDomainObjPrivatePtr priv;
7226

7227
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
7228 7229
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
7230

7231 7232 7233
    /* We blindly return a string, and let libvirt.c and
     * remote_driver.c do the filtering on behalf of older clients
     * that can't parse it.  */
7234 7235
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

7236 7237
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7238

7239 7240
    priv = vm->privateData;

7241 7242 7243
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

7244 7245 7246 7247 7248 7249 7250
    if ((*nparams) == 0) {
        /* Current number of blkio parameters supported by cgroups */
        *nparams = QEMU_NB_BLKIO_PARAM;
        ret = 0;
        goto cleanup;
    }

7251
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7252 7253
                                        &persistentDef) < 0)
        goto cleanup;
7254

7255
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7256
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
7257 7258
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("blkio cgroup isn't mounted"));
7259 7260 7261 7262 7263
            goto cleanup;
        }
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7264
        for (i = 0; i < *nparams && i < QEMU_NB_BLKIO_PARAM; i++) {
7265 7266 7267 7268 7269
            virTypedParameterPtr param = &params[i];
            val = 0;

            switch (i) {
            case 0: /* fill blkio weight here */
7270
                rc = virCgroupGetBlkioWeight(priv->cgroup, &val);
7271 7272 7273 7274 7275
                if (rc != 0) {
                    virReportSystemError(-rc, "%s",
                                         _("unable to get blkio weight"));
                    goto cleanup;
                }
7276 7277
                if (virTypedParameterAssign(param, VIR_DOMAIN_BLKIO_WEIGHT,
                                            VIR_TYPED_PARAM_UINT, val) < 0)
7278 7279
                    goto cleanup;
                break;
7280 7281 7282 7283
            case 1: /* blkiotune.device_weight */
                if (vm->def->blkio.ndevices > 0) {
                    virBuffer buf = VIR_BUFFER_INITIALIZER;
                    bool comma = false;
7284

7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301
                    for (j = 0; j < vm->def->blkio.ndevices; j++) {
                        if (!vm->def->blkio.devices[j].weight)
                            continue;
                        if (comma)
                            virBufferAddChar(&buf, ',');
                        else
                            comma = true;
                        virBufferAsprintf(&buf, "%s,%u",
                                          vm->def->blkio.devices[j].path,
                                          vm->def->blkio.devices[j].weight);
                    }
                    if (virBufferError(&buf)) {
                        virReportOOMError();
                        goto cleanup;
                    }
                    param->value.s = virBufferContentAndReset(&buf);
                }
7302 7303 7304 7305
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
                                            VIR_TYPED_PARAM_STRING,
                                            param->value.s) < 0)
7306 7307
                    goto cleanup;
                break;
7308 7309 7310 7311

            default:
                break;
                /* should not hit here */
7312
            }
7313 7314
        }
    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7315
        for (i = 0; i < *nparams && i < QEMU_NB_BLKIO_PARAM; i++) {
7316 7317 7318 7319 7320 7321 7322 7323
            virTypedParameterPtr param = &params[i];
            val = 0;
            param->value.ui = 0;
            param->type = VIR_TYPED_PARAM_UINT;

            switch (i) {
            case 0: /* fill blkio weight here */
                if (virStrcpyStatic(param->field, VIR_DOMAIN_BLKIO_WEIGHT) == NULL) {
7324 7325 7326
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Field name '%s' too long"),
                                   VIR_DOMAIN_BLKIO_WEIGHT);
7327 7328 7329 7330
                    goto cleanup;
                }
                param->value.ui = persistentDef->blkio.weight;
                break;
7331

7332 7333 7334
            case 1: /* blkiotune.device_weight */
                if (persistentDef->blkio.ndevices > 0) {
                    virBuffer buf = VIR_BUFFER_INITIALIZER;
7335 7336
                    bool comma = false;

7337
                    for (j = 0; j < persistentDef->blkio.ndevices; j++) {
7338 7339 7340
                        if (!persistentDef->blkio.devices[j].weight)
                            continue;
                        if (comma)
7341
                            virBufferAddChar(&buf, ',');
7342 7343
                        else
                            comma = true;
7344 7345 7346 7347 7348 7349 7350 7351 7352
                        virBufferAsprintf(&buf, "%s,%u",
                                          persistentDef->blkio.devices[j].path,
                                          persistentDef->blkio.devices[j].weight);
                    }
                    if (virBufferError(&buf)) {
                        virReportOOMError();
                        goto cleanup;
                    }
                    param->value.s = virBufferContentAndReset(&buf);
7353 7354
                }
                if (!param->value.s) {
7355 7356 7357 7358 7359 7360 7361 7362 7363
                    param->value.s = strdup("");
                    if (!param->value.s) {
                        virReportOOMError();
                        goto cleanup;
                    }
                }
                param->type = VIR_TYPED_PARAM_STRING;
                if (virStrcpyStatic(param->field,
                                    VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) == NULL) {
7364 7365 7366
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Field name '%s' too long"),
                                   VIR_DOMAIN_BLKIO_DEVICE_WEIGHT);
7367 7368 7369 7370
                    goto cleanup;
                }
                break;

7371 7372 7373 7374
            default:
                break;
                /* should not hit here */
            }
7375 7376 7377
        }
    }

7378 7379
    if (QEMU_NB_BLKIO_PARAM < *nparams)
        *nparams = QEMU_NB_BLKIO_PARAM;
7380 7381 7382 7383
    ret = 0;

cleanup:
    if (vm)
7384
        virObjectUnlock(vm);
7385
    virObjectUnref(caps);
7386 7387
    return ret;
}
7388

7389 7390 7391 7392 7393
static int
qemuDomainSetMemoryParameters(virDomainPtr dom,
                              virTypedParameterPtr params,
                              int nparams,
                              unsigned int flags)
7394
{
7395
    virQEMUDriverPtr driver = dom->conn->privateData;
7396
    virDomainDefPtr persistentDef = NULL;
7397
    virDomainObjPtr vm = NULL;
7398
    unsigned long long swap_hard_limit;
7399 7400
    unsigned long long hard_limit = 0;
    unsigned long long soft_limit = 0;
7401
    bool set_swap_hard_limit = false;
7402 7403
    bool set_hard_limit = false;
    bool set_soft_limit = false;
7404
    virQEMUDriverConfigPtr cfg = NULL;
7405
    int ret = -1;
7406
    int rc;
7407
    virCapsPtr caps = NULL;
7408
    qemuDomainObjPrivatePtr priv;
7409

7410 7411
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
7412

7413 7414 7415 7416 7417 7418 7419 7420 7421
    if (virTypedParameterArrayValidate(params, nparams,
                                       VIR_DOMAIN_MEMORY_HARD_LIMIT,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_MEMORY_SOFT_LIMIT,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
                                       VIR_TYPED_PARAM_ULLONG,
                                       NULL) < 0)
        return -1;
7422 7423


7424 7425
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7426

7427
    priv = vm->privateData;
7428 7429
    cfg = virQEMUDriverGetConfig(driver);

7430 7431 7432
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

7433
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7434 7435
                                        &persistentDef) < 0)
        goto cleanup;
7436

7437
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7438
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
7439 7440
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup memory controller is not mounted"));
7441 7442 7443 7444
            goto cleanup;
        }
    }

7445
#define VIR_GET_LIMIT_PARAMETER(PARAM, VALUE)                                \
7446
    if ((rc = virTypedParamsGetULLong(params, nparams, PARAM, &VALUE)) < 0)  \
7447 7448 7449 7450 7451 7452
        goto cleanup;                                                        \
                                                                             \
    if (rc == 1)                                                             \
        set_ ## VALUE = true;

    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit)
7453 7454
    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit)
    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit)
7455 7456 7457

#undef VIR_GET_LIMIT_PARAMETER

7458 7459 7460 7461 7462
    /* Swap hard limit must be greater than hard limit.
     * Note that limit of 0 denotes unlimited */
    if (set_swap_hard_limit || set_hard_limit) {
        unsigned long long mem_limit = vm->def->mem.hard_limit;
        unsigned long long swap_limit = vm->def->mem.swap_hard_limit;
7463

7464 7465
        if (set_swap_hard_limit)
            swap_limit = swap_hard_limit;
7466

7467 7468 7469 7470 7471 7472 7473 7474
        if (set_hard_limit)
            mem_limit = hard_limit;

        if (virCompareLimitUlong(mem_limit, swap_limit) > 0) {
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("memory hard_limit tunable value must be lower "
                             "than swap_hard_limit"));
            goto cleanup;
7475
        }
7476
    }
7477

7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491
#define QEMU_SET_MEM_PARAMETER(FUNC, VALUE)                                     \
    if (set_ ## VALUE) {                                                        \
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {                                   \
            if ((rc = FUNC(priv->cgroup, VALUE)) < 0) {                         \
                virReportSystemError(-rc, _("unable to set memory %s tunable"), \
                                     #VALUE);                                   \
                                                                                \
                goto cleanup;                                                   \
            }                                                                   \
            vm->def->mem.VALUE = VALUE;                                         \
        }                                                                       \
                                                                                \
        if (flags & VIR_DOMAIN_AFFECT_CONFIG)                                   \
            persistentDef->mem.VALUE = VALUE;                                   \
7492 7493
    }

7494 7495
    /* Soft limit doesn't clash with the others */
    QEMU_SET_MEM_PARAMETER(virCgroupSetMemorySoftLimit, soft_limit);
7496

7497 7498 7499 7500 7501
    /* set hard limit before swap hard limit if decreasing it */
    if (virCompareLimitUlong(vm->def->mem.hard_limit, hard_limit) > 0) {
        QEMU_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
        /* inhibit changing the limit a second time */
        set_hard_limit = false;
7502
    }
7503

7504
    QEMU_SET_MEM_PARAMETER(virCgroupSetMemSwapHardLimit, swap_hard_limit);
7505

7506 7507 7508 7509
    /* otherwise increase it after swap hard limit */
    QEMU_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);

#undef QEMU_SET_MEM_PARAMETER
7510

7511 7512 7513 7514 7515 7516
    if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
        virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
        goto cleanup;

    ret = 0;

7517
cleanup:
7518
    virObjectUnlock(vm);
7519
    virObjectUnref(caps);
7520
    virObjectUnref(cfg);
7521 7522 7523
    return ret;
}

7524 7525 7526 7527 7528
static int
qemuDomainGetMemoryParameters(virDomainPtr dom,
                              virTypedParameterPtr params,
                              int *nparams,
                              unsigned int flags)
7529
{
7530
    virQEMUDriverPtr driver = dom->conn->privateData;
7531 7532
    int i;
    virDomainObjPtr vm = NULL;
7533
    virDomainDefPtr persistentDef = NULL;
7534 7535
    int ret = -1;
    int rc;
7536
    virCapsPtr caps = NULL;
7537
    qemuDomainObjPrivatePtr priv;
7538

7539
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
7540 7541
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
7542

7543 7544 7545
    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

7546 7547
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7548

7549
    priv = vm->privateData;
7550 7551 7552
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

7553
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7554 7555
                                        &persistentDef) < 0)
        goto cleanup;
7556

7557
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7558
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
7559 7560
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup memory controller is not mounted"));
7561 7562 7563 7564
            goto cleanup;
        }
    }

7565 7566 7567 7568 7569 7570 7571
    if ((*nparams) == 0) {
        /* Current number of memory parameters supported by cgroups */
        *nparams = QEMU_NB_MEM_PARAM;
        ret = 0;
        goto cleanup;
    }

7572
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7573
        for (i = 0; i < *nparams && i < QEMU_NB_MEM_PARAM; i++) {
7574 7575 7576 7577
            virMemoryParameterPtr param = &params[i];

            switch (i) {
            case 0: /* fill memory hard limit here */
7578 7579 7580 7581
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_MEMORY_HARD_LIMIT,
                                            VIR_TYPED_PARAM_ULLONG,
                                            persistentDef->mem.hard_limit) < 0)
7582 7583 7584 7585
                    goto cleanup;
                break;

            case 1: /* fill memory soft limit here */
7586 7587 7588 7589
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_MEMORY_SOFT_LIMIT,
                                            VIR_TYPED_PARAM_ULLONG,
                                            persistentDef->mem.soft_limit) < 0)
7590 7591 7592 7593
                    goto cleanup;
                break;

            case 2: /* fill swap hard limit here */
7594 7595 7596 7597
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
                                            VIR_TYPED_PARAM_ULLONG,
                                            persistentDef->mem.swap_hard_limit) < 0)
7598 7599 7600 7601 7602 7603 7604 7605 7606
                    goto cleanup;
                break;

            default:
                break;
                /* should not hit here */
            }
        }
        goto out;
7607 7608
    }

7609
    for (i = 0; i < *nparams && i < QEMU_NB_MEM_PARAM; i++) {
7610
        virTypedParameterPtr param = &params[i];
7611
        unsigned long long val = 0;
7612

7613
        switch (i) {
7614
        case 0: /* fill memory hard limit here */
7615
            rc = virCgroupGetMemoryHardLimit(priv->cgroup, &val);
7616 7617 7618
            if (rc != 0) {
                virReportSystemError(-rc, "%s",
                                     _("unable to get memory hard limit"));
7619
                goto cleanup;
7620
            }
7621 7622 7623
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_MEMORY_HARD_LIMIT,
                                        VIR_TYPED_PARAM_ULLONG, val) < 0)
7624
                goto cleanup;
7625 7626 7627
            break;

        case 1: /* fill memory soft limit here */
7628
            rc = virCgroupGetMemorySoftLimit(priv->cgroup, &val);
7629 7630 7631
            if (rc != 0) {
                virReportSystemError(-rc, "%s",
                                     _("unable to get memory soft limit"));
7632
                goto cleanup;
7633
            }
7634 7635 7636
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_MEMORY_SOFT_LIMIT,
                                        VIR_TYPED_PARAM_ULLONG, val) < 0)
7637
                goto cleanup;
7638 7639 7640
            break;

        case 2: /* fill swap hard limit here */
7641
            rc = virCgroupGetMemSwapHardLimit(priv->cgroup, &val);
7642
            if (rc != 0) {
7643 7644 7645 7646 7647 7648
                if (rc != -ENOENT) {
                    virReportSystemError(-rc, "%s",
                                         _("unable to get swap hard limit"));
                    goto cleanup;
                }
                val = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
7649
            }
7650 7651 7652
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
                                        VIR_TYPED_PARAM_ULLONG, val) < 0)
7653
                goto cleanup;
7654 7655 7656 7657 7658 7659 7660 7661
            break;

        default:
            break;
            /* should not hit here */
        }
    }

7662
out:
7663 7664
    if (QEMU_NB_MEM_PARAM < *nparams)
        *nparams = QEMU_NB_MEM_PARAM;
7665 7666
    ret = 0;

7667 7668
cleanup:
    if (vm)
7669
        virObjectUnlock(vm);
7670
    virObjectUnref(caps);
7671 7672 7673
    return ret;
}

7674 7675 7676 7677 7678 7679
static int
qemuDomainSetNumaParameters(virDomainPtr dom,
                            virTypedParameterPtr params,
                            int nparams,
                            unsigned int flags)
{
7680
    virQEMUDriverPtr driver = dom->conn->privateData;
7681 7682 7683 7684
    int i;
    virDomainDefPtr persistentDef = NULL;
    virDomainObjPtr vm = NULL;
    int ret = -1;
7685
    virQEMUDriverConfigPtr cfg = NULL;
7686
    virCapsPtr caps = NULL;
7687
    qemuDomainObjPrivatePtr priv;
7688 7689 7690

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
7691 7692 7693 7694 7695 7696 7697
    if (virTypedParameterArrayValidate(params, nparams,
                                       VIR_DOMAIN_NUMA_MODE,
                                       VIR_TYPED_PARAM_INT,
                                       VIR_DOMAIN_NUMA_NODESET,
                                       VIR_TYPED_PARAM_STRING,
                                       NULL) < 0)
        return -1;
7698

7699 7700
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7701

7702
    priv = vm->privateData;
7703
    cfg = virQEMUDriverGetConfig(driver);
7704

7705 7706 7707
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

7708
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7709 7710 7711 7712
                                        &persistentDef) < 0)
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7713
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
7714 7715
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup cpuset controller is not mounted"));
7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726
            goto cleanup;
        }
    }

    ret = 0;
    for (i = 0; i < nparams; i++) {
        virTypedParameterPtr param = &params[i];

        if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) {
            if ((flags & VIR_DOMAIN_AFFECT_LIVE) &&
                vm->def->numatune.memory.mode != params[i].value.i) {
7727 7728
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("can't change numa mode for running domain"));
7729 7730 7731 7732 7733 7734 7735 7736 7737
                ret = -1;
                goto cleanup;
            }

            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
                persistentDef->numatune.memory.mode = params[i].value.i;
            }
        } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
            int rc;
7738
            virBitmapPtr nodeset = NULL;
7739 7740
            char *nodeset_str = NULL;

7741 7742 7743
            if (virBitmapParse(params[i].value.s,
                               0, &nodeset,
                               VIR_DOMAIN_CPUMASK_LEN) < 0) {
7744 7745 7746 7747 7748
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to parse nodeset"));
                ret = -1;
                continue;
            }
7749 7750 7751 7752

            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
                if (vm->def->numatune.memory.mode !=
                    VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
7753 7754 7755
                    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                                   _("change of nodeset for running domain "
                                     "requires strict numa mode"));
7756
                    virBitmapFree(nodeset);
7757 7758 7759
                    ret = -1;
                    continue;
                }
7760 7761

                /* Ensure the cpuset string is formated before passing to cgroup */
7762
                if (!(nodeset_str = virBitmapFormat(nodeset))) {
7763 7764
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("Failed to format nodeset"));
7765
                    virBitmapFree(nodeset);
7766 7767 7768 7769
                    ret = -1;
                    continue;
                }

O
Osier Yang 已提交
7770
                if ((rc = virCgroupSetCpusetMems(priv->cgroup, nodeset_str)) != 0) {
7771 7772
                    virReportSystemError(-rc, "%s",
                                         _("unable to set numa tunable"));
7773
                    virBitmapFree(nodeset);
7774
                    VIR_FREE(nodeset_str);
7775 7776 7777
                    ret = -1;
                    continue;
                }
7778
                VIR_FREE(nodeset_str);
7779 7780 7781

                /* update vm->def here so that dumpxml can read the new
                 * values from vm->def. */
7782
                virBitmapFree(vm->def->numatune.memory.nodemask);
7783

7784
                vm->def->numatune.memory.placement_mode =
G
Gao feng 已提交
7785
                    VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_STATIC;
7786
                vm->def->numatune.memory.nodemask = virBitmapNewCopy(nodeset);
7787 7788 7789
            }

            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7790
                virBitmapFree(persistentDef->numatune.memory.nodemask);
7791 7792

                persistentDef->numatune.memory.nodemask = nodeset;
7793
                persistentDef->numatune.memory.placement_mode =
G
Gao feng 已提交
7794
                    VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_STATIC;
7795
                nodeset = NULL;
7796
            }
7797
            virBitmapFree(nodeset);
7798 7799 7800 7801
        }
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7802 7803
        if (!persistentDef->numatune.memory.placement_mode)
            persistentDef->numatune.memory.placement_mode =
G
Gao feng 已提交
7804
                VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_AUTO;
7805
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
7806 7807 7808 7809 7810
            ret = -1;
    }

cleanup:
    if (vm)
7811
        virObjectUnlock(vm);
7812
    virObjectUnref(caps);
7813
    virObjectUnref(cfg);
7814 7815 7816 7817 7818 7819 7820 7821 7822
    return ret;
}

static int
qemuDomainGetNumaParameters(virDomainPtr dom,
                            virTypedParameterPtr params,
                            int *nparams,
                            unsigned int flags)
{
7823
    virQEMUDriverPtr driver = dom->conn->privateData;
7824 7825 7826 7827 7828 7829
    int i;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr persistentDef = NULL;
    char *nodeset = NULL;
    int ret = -1;
    int rc;
7830
    virCapsPtr caps = NULL;
7831
    qemuDomainObjPrivatePtr priv;
7832 7833 7834 7835 7836 7837 7838 7839 7840 7841

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    /* We blindly return a string, and let libvirt.c and
     * remote_driver.c do the filtering on behalf of older clients
     * that can't parse it.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

7842 7843
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7844

7845 7846
    priv = vm->privateData;

7847 7848 7849
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

7850
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7851 7852 7853 7854 7855 7856 7857 7858 7859 7860
                                        &persistentDef) < 0)
        goto cleanup;

    if ((*nparams) == 0) {
        *nparams = QEMU_NB_NUMA_PARAM;
        ret = 0;
        goto cleanup;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7861
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
7862 7863
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup memory controller is not mounted"));
7864 7865 7866 7867 7868 7869 7870 7871 7872
            goto cleanup;
        }
    }

    for (i = 0; i < QEMU_NB_NUMA_PARAM && i < *nparams; i++) {
        virMemoryParameterPtr param = &params[i];

        switch (i) {
        case 0: /* fill numa mode here */
7873 7874
            if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
                                        VIR_TYPED_PARAM_INT, 0) < 0)
7875 7876 7877 7878 7879 7880 7881 7882 7883
                goto cleanup;
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                param->value.i = persistentDef->numatune.memory.mode;
            else
                param->value.i = vm->def->numatune.memory.mode;
            break;

        case 1: /* fill numa nodeset here */
            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7884 7885
                nodeset = virBitmapFormat(persistentDef->numatune.memory.nodemask);
                if (!nodeset)
7886 7887
                    nodeset = strdup("");
            } else {
7888
                rc = virCgroupGetCpusetMems(priv->cgroup, &nodeset);
7889 7890 7891 7892 7893 7894
                if (rc != 0) {
                    virReportSystemError(-rc, "%s",
                                         _("unable to get numa nodeset"));
                    goto cleanup;
                }
            }
7895 7896
            if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
                                        VIR_TYPED_PARAM_STRING, nodeset) < 0)
7897
                goto cleanup;
S
Stefan Berger 已提交
7898 7899 7900

            nodeset = NULL;

7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913
            break;

        default:
            break;
            /* should not hit here */
        }
    }

    if (*nparams > QEMU_NB_NUMA_PARAM)
        *nparams = QEMU_NB_NUMA_PARAM;
    ret = 0;

cleanup:
S
Stefan Berger 已提交
7914
    VIR_FREE(nodeset);
7915
    if (vm)
7916
        virObjectUnlock(vm);
7917
    virObjectUnref(caps);
7918 7919 7920
    return ret;
}

7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932
static int
qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
                   unsigned long long period, long long quota)
{
    int i;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virCgroupPtr cgroup_vcpu = NULL;
    int rc;

    if (period == 0 && quota == 0)
        return 0;

W
Wen Congyang 已提交
7933 7934 7935 7936 7937 7938
    /* If we does not know VCPU<->PID mapping or all vcpu runs in the same
     * thread, we cannot control each vcpu. So we only modify cpu bandwidth
     * when each vcpu has a separated thread.
     */
    if (priv->nvcpupids != 0 && priv->vcpupids[0] != vm->pid) {
        for (i = 0; i < priv->nvcpupids; i++) {
7939
            rc = virCgroupNewVcpu(cgroup, i, false, &cgroup_vcpu);
W
Wen Congyang 已提交
7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952
            if (rc < 0) {
                virReportSystemError(-rc,
                                     _("Unable to find vcpu cgroup for %s(vcpu:"
                                       " %d)"),
                                     vm->def->name, i);
                goto cleanup;
            }

            if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
                goto cleanup;

            virCgroupFree(&cgroup_vcpu);
        }
7953 7954 7955 7956 7957 7958 7959 7960 7961
    }

    return 0;

cleanup:
    virCgroupFree(&cgroup_vcpu);
    return -1;
}

7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976
static int
qemuSetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
                             unsigned long long period, long long quota)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virCgroupPtr cgroup_emulator = NULL;
    int rc;

    if (period == 0 && quota == 0)
        return 0;

    if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
        return 0;
    }

7977
    rc = virCgroupNewEmulator(cgroup, false, &cgroup_emulator);
7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995
    if (rc < 0) {
        virReportSystemError(-rc,
                             _("Unable to find emulator cgroup for %s"),
                             vm->def->name);
        goto cleanup;
    }

    if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
        goto cleanup;

    virCgroupFree(&cgroup_emulator);
    return 0;

cleanup:
    virCgroupFree(&cgroup_emulator);
    return -1;
}

7996 7997 7998 7999 8000 8001 8002 8003 8004
#define SCHED_RANGE_CHECK(VAR, NAME, MIN, MAX)                              \
    if (((VAR) > 0 && (VAR) < (MIN)) || (VAR) > (MAX)) {                    \
        virReportError(VIR_ERR_INVALID_ARG,                                 \
                       _("value of '%s' is out of range [%lld, %lld]"),     \
                       NAME, MIN, MAX);                                     \
        rc = -1;                                                            \
        goto cleanup;                                                       \
    }

8005
static int
8006 8007 8008 8009
qemuDomainSetSchedulerParametersFlags(virDomainPtr dom,
                                      virTypedParameterPtr params,
                                      int nparams,
                                      unsigned int flags)
8010
{
8011
    virQEMUDriverPtr driver = dom->conn->privateData;
8012 8013
    int i;
    virDomainObjPtr vm = NULL;
8014
    virDomainDefPtr vmdef = NULL;
8015 8016
    unsigned long long value_ul;
    long long value_l;
8017
    int ret = -1;
8018
    int rc;
8019
    virQEMUDriverConfigPtr cfg = NULL;
8020
    virCapsPtr caps = NULL;
8021
    qemuDomainObjPrivatePtr priv;
8022

8023 8024
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
8025 8026 8027 8028 8029 8030 8031
    if (virTypedParameterArrayValidate(params, nparams,
                                       VIR_DOMAIN_SCHEDULER_CPU_SHARES,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
                                       VIR_TYPED_PARAM_LLONG,
8032 8033 8034 8035
                                       VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
                                       VIR_TYPED_PARAM_LLONG,
8036 8037
                                       NULL) < 0)
        return -1;
8038

8039 8040
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
8041

8042
    priv = vm->privateData;
8043 8044
    cfg = virQEMUDriverGetConfig(driver);

8045 8046 8047
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

8048
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
8049 8050
                                        &vmdef) < 0)
        goto cleanup;
8051

8052 8053
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        /* Make a copy for updated domain. */
8054
        vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
8055 8056
        if (!vmdef)
            goto cleanup;
8057 8058
    }

8059
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
8060
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
8061 8062
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup CPU controller is not mounted"));
8063 8064 8065 8066
            goto cleanup;
        }
    }

8067
    for (i = 0; i < nparams; i++) {
8068
        virTypedParameterPtr param = &params[i];
8069 8070
        value_ul = param->value.ul;
        value_l = param->value.l;
8071

8072
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
8073
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
8074
                if ((rc = virCgroupSetCpuShares(priv->cgroup, value_ul))) {
8075 8076 8077 8078
                    virReportSystemError(-rc, "%s",
                                         _("unable to set cpu shares tunable"));
                    goto cleanup;
                }
8079
                vm->def->cputune.shares = value_ul;
8080
            }
8081

8082 8083 8084
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.shares = value_ul;

8085
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
8086 8087 8088
            SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
                              QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);

8089
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
8090
                if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, value_ul, 0)))
8091
                    goto cleanup;
8092

8093
                vm->def->cputune.period = value_ul;
8094 8095
            }

8096
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
8097
                vmdef->cputune.period = params[i].value.ul;
8098

8099
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
8100 8101 8102
            SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
                              QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);

8103
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
8104
                if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, 0, value_l)))
8105
                    goto cleanup;
8106

8107
                vm->def->cputune.quota = value_l;
8108 8109
            }

8110 8111 8112
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.quota = value_l;

8113
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD)) {
8114 8115 8116
            SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
                              QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);

8117
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
8118 8119
                if ((rc = qemuSetEmulatorBandwidthLive(vm, priv->cgroup,
                                                       value_ul, 0)))
8120 8121
                    goto cleanup;

8122
                vm->def->cputune.emulator_period = value_ul;
8123 8124
            }

8125 8126 8127
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.emulator_period = value_ul;

8128
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA)) {
8129 8130 8131
            SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
                              QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);

8132
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
8133 8134
                if ((rc = qemuSetEmulatorBandwidthLive(vm, priv->cgroup,
                                                       0, value_l)))
8135 8136
                    goto cleanup;

8137
                vm->def->cputune.emulator_quota = value_l;
8138 8139
            }

8140 8141
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.emulator_quota = value_l;
8142 8143
        }
    }
8144

8145
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
8146 8147 8148 8149
        goto cleanup;


    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8150
        rc = virDomainSaveConfig(cfg->configDir, vmdef);
8151 8152 8153
        if (rc < 0)
            goto cleanup;

8154
        virDomainObjAssignDef(vm, vmdef, false, NULL);
8155 8156 8157
        vmdef = NULL;
    }

8158 8159 8160
    ret = 0;

cleanup:
8161
    virDomainDefFree(vmdef);
8162
    if (vm)
8163
        virObjectUnlock(vm);
8164
    virObjectUnref(caps);
8165
    virObjectUnref(cfg);
8166 8167
    return ret;
}
8168
#undef SCHED_RANGE_CHECK
8169

8170
static int
8171 8172 8173
qemuDomainSetSchedulerParameters(virDomainPtr dom,
                                 virTypedParameterPtr params,
                                 int nparams)
8174
{
8175 8176 8177 8178
    return qemuDomainSetSchedulerParametersFlags(dom,
                                                 params,
                                                 nparams,
                                                 VIR_DOMAIN_AFFECT_CURRENT);
8179 8180
}

8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204
static int
qemuGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
                  long long *quota)
{
    int rc;

    rc = virCgroupGetCpuCfsPeriod(cgroup, period);
    if (rc < 0) {
        virReportSystemError(-rc, "%s",
                             _("unable to get cpu bandwidth period tunable"));
        return -1;
    }

    rc = virCgroupGetCpuCfsQuota(cgroup, quota);
    if (rc < 0) {
        virReportSystemError(-rc, "%s",
                             _("unable to get cpu bandwidth tunable"));
        return -1;
    }

    return 0;
}

static int
8205
qemuGetVcpusBWLive(virDomainObjPtr vm,
8206 8207 8208 8209 8210 8211 8212 8213 8214 8215
                   unsigned long long *period, long long *quota)
{
    virCgroupPtr cgroup_vcpu = NULL;
    qemuDomainObjPrivatePtr priv = NULL;
    int rc;
    int ret = -1;

    priv = vm->privateData;
    if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
        /* We do not create sub dir for each vcpu */
8216
        rc = qemuGetVcpuBWLive(priv->cgroup, period, quota);
8217 8218 8219 8220 8221 8222 8223 8224 8225
        if (rc < 0)
            goto cleanup;

        if (*quota > 0)
            *quota /= vm->def->vcpus;
        goto out;
    }

    /* get period and quota for vcpu0 */
8226
    rc = virCgroupNewVcpu(priv->cgroup, 0, false, &cgroup_vcpu);
8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245
    if (!cgroup_vcpu) {
        virReportSystemError(-rc,
                             _("Unable to find vcpu cgroup for %s(vcpu: 0)"),
                             vm->def->name);
        goto cleanup;
    }

    rc = qemuGetVcpuBWLive(cgroup_vcpu, period, quota);
    if (rc < 0)
        goto cleanup;

out:
    ret = 0;

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

8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263
static int
qemuGetEmulatorBandwidthLive(virDomainObjPtr vm, virCgroupPtr cgroup,
                             unsigned long long *period, long long *quota)
{
    virCgroupPtr cgroup_emulator = NULL;
    qemuDomainObjPrivatePtr priv = NULL;
    int rc;
    int ret = -1;

    priv = vm->privateData;
    if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
        /* We don't create sub dir for each vcpu */
        *period = 0;
        *quota = 0;
        return 0;
    }

    /* get period and quota for emulator */
8264
    rc = virCgroupNewEmulator(cgroup, false, &cgroup_emulator);
8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282
    if (!cgroup_emulator) {
        virReportSystemError(-rc,
                             _("Unable to find emulator cgroup for %s"),
                             vm->def->name);
        goto cleanup;
    }

    rc = qemuGetVcpuBWLive(cgroup_emulator, period, quota);
    if (rc < 0)
        goto cleanup;

    ret = 0;

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

8283
static int
8284 8285 8286 8287
qemuDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                      virTypedParameterPtr params,
                                      int *nparams,
                                      unsigned int flags)
8288
{
8289
    virQEMUDriverPtr driver = dom->conn->privateData;
8290
    virDomainObjPtr vm = NULL;
8291 8292 8293
    unsigned long long shares;
    unsigned long long period;
    long long quota;
8294 8295
    unsigned long long emulator_period;
    long long emulator_quota;
8296 8297
    int ret = -1;
    int rc;
8298
    bool cpu_bw_status = false;
8299
    int saved_nparams = 0;
8300
    virDomainDefPtr persistentDef;
8301
    virCapsPtr caps = NULL;
8302
    qemuDomainObjPrivatePtr priv;
8303

8304
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8305 8306
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
8307

8308 8309 8310
    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

8311 8312 8313 8314 8315
    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    priv = vm->privateData;

8316
    if (*nparams > 1) {
8317
        rc = qemuGetCpuBWStatus(priv->cgroup);
8318 8319 8320 8321 8322
        if (rc < 0)
            goto cleanup;
        cpu_bw_status = !!rc;
    }

8323 8324 8325
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

8326
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
8327 8328
                                        &persistentDef) < 0)
        goto cleanup;
8329

8330
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8331 8332 8333 8334
        shares = persistentDef->cputune.shares;
        if (*nparams > 1 && cpu_bw_status) {
            period = persistentDef->cputune.period;
            quota = persistentDef->cputune.quota;
8335 8336
            emulator_period = persistentDef->cputune.emulator_period;
            emulator_quota = persistentDef->cputune.emulator_quota;
8337
        }
8338
        goto out;
8339 8340
    }

8341
    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
8342 8343
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cgroup CPU controller is not mounted"));
8344 8345 8346
        goto cleanup;
    }

8347
    rc = virCgroupGetCpuShares(priv->cgroup, &shares);
8348
    if (rc != 0) {
8349
        virReportSystemError(-rc, "%s",
8350 8351 8352
                             _("unable to get cpu shares tunable"));
        goto cleanup;
    }
8353 8354

    if (*nparams > 1 && cpu_bw_status) {
8355
        rc = qemuGetVcpusBWLive(vm, &period, &quota);
8356 8357 8358
        if (rc != 0)
            goto cleanup;
    }
8359 8360

    if (*nparams > 3 && cpu_bw_status) {
8361
        rc = qemuGetEmulatorBandwidthLive(vm, priv->cgroup, &emulator_period,
8362 8363 8364 8365 8366
                                          &emulator_quota);
        if (rc != 0)
            goto cleanup;
    }

8367
out:
8368 8369
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CPU_SHARES,
                                VIR_TYPED_PARAM_ULLONG, shares) < 0)
C
Chris Lalancette 已提交
8370
        goto cleanup;
8371 8372 8373 8374
    saved_nparams++;

    if (cpu_bw_status) {
        if (*nparams > saved_nparams) {
8375 8376 8377
            if (virTypedParameterAssign(&params[1],
                                        VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
                                        VIR_TYPED_PARAM_ULLONG, period) < 0)
8378 8379 8380 8381 8382
                goto cleanup;
            saved_nparams++;
        }

        if (*nparams > saved_nparams) {
8383 8384 8385
            if (virTypedParameterAssign(&params[2],
                                        VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
                                        VIR_TYPED_PARAM_LLONG, quota) < 0)
8386 8387 8388
                goto cleanup;
            saved_nparams++;
        }
8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406

        if (*nparams > saved_nparams) {
            if (virTypedParameterAssign(&params[3],
                                        VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
                                        VIR_TYPED_PARAM_ULLONG,
                                        emulator_period) < 0)
                goto cleanup;
            saved_nparams++;
        }

        if (*nparams > saved_nparams) {
            if (virTypedParameterAssign(&params[4],
                                        VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
                                        VIR_TYPED_PARAM_LLONG,
                                        emulator_quota) < 0)
                goto cleanup;
            saved_nparams++;
        }
8407 8408 8409 8410
    }

    *nparams = saved_nparams;

8411 8412 8413 8414
    ret = 0;

cleanup:
    if (vm)
8415
        virObjectUnlock(vm);
8416
    virObjectUnref(caps);
8417 8418 8419
    return ret;
}

8420
static int
8421 8422 8423
qemuDomainGetSchedulerParameters(virDomainPtr dom,
                                 virTypedParameterPtr params,
                                 int *nparams)
8424
{
8425 8426
    return qemuDomainGetSchedulerParametersFlags(dom, params, nparams,
                                                 VIR_DOMAIN_AFFECT_CURRENT);
8427
}
8428

8429 8430 8431 8432 8433 8434 8435
/**
 * Resize a block device while a guest is running. Resize to a lower size
 * is supported, but should be used with extreme caution.  Note that it
 * only supports to resize image files, it can't resize block devices
 * like LVM volumes.
 */
static int
E
Eric Blake 已提交
8436 8437 8438 8439
qemuDomainBlockResize(virDomainPtr dom,
                      const char *path,
                      unsigned long long size,
                      unsigned int flags)
8440
{
8441
    virQEMUDriverPtr driver = dom->conn->privateData;
8442 8443 8444 8445 8446 8447
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1, i;
    char *device = NULL;
    virDomainDiskDefPtr disk = NULL;

E
Eric Blake 已提交
8448
    virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
8449 8450

    if (path[0] == '\0') {
8451 8452
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("empty path"));
8453 8454 8455
        return -1;
    }

E
Eric Blake 已提交
8456 8457 8458
    /* We prefer operating on bytes.  */
    if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) {
        if (size > ULLONG_MAX / 1024) {
8459 8460 8461
            virReportError(VIR_ERR_OVERFLOW,
                           _("size must be less than %llu"),
                           ULLONG_MAX / 1024);
E
Eric Blake 已提交
8462 8463 8464
            return -1;
        }
        size *= 1024;
8465 8466
    }

8467
    if (!(vm = qemuDomObjFromDomain(dom)))
8468 8469 8470 8471 8472 8473 8474 8475
        goto cleanup;

    priv = vm->privateData;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
8476 8477
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8478 8479 8480 8481
        goto endjob;
    }

    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
8482 8483
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
8484
        goto endjob;
8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509
    }
    disk = vm->def->disks[i];

    if (virAsprintf(&device, "%s%s", QEMU_DRIVE_HOST_PREFIX,
                    disk->info.alias) < 0) {
        virReportOOMError();
        goto endjob;
    }

    qemuDomainObjEnterMonitor(driver, vm);
    if (qemuMonitorBlockResize(priv->mon, device, size) < 0) {
        qemuDomainObjExitMonitor(driver, vm);
        goto endjob;
    }
    qemuDomainObjExitMonitor(driver, vm);

    ret = 0;

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    VIR_FREE(device);
    if (vm)
8510
        virObjectUnlock(vm);
8511 8512 8513
    return ret;
}

8514 8515 8516 8517 8518
/* 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
8519 8520 8521
qemuDomainBlockStats(virDomainPtr dom,
                     const char *path,
                     struct _virDomainBlockStats *stats)
8522
{
8523
    virQEMUDriverPtr driver = dom->conn->privateData;
8524
    int i, ret = -1;
8525
    virDomainObjPtr vm;
8526
    virDomainDiskDefPtr disk = NULL;
8527
    qemuDomainObjPrivatePtr priv;
8528

8529
    if (!(vm = qemuDomObjFromDomain(dom)))
8530
        goto cleanup;
8531

8532
    if (!virDomainObjIsActive(vm)) {
8533 8534
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8535 8536 8537
        goto cleanup;
    }

8538
    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
8539 8540
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
8541
        goto cleanup;
8542
    }
8543
    disk = vm->def->disks[i];
8544

8545
    if (!disk->info.alias) {
8546 8547
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("missing disk device alias name for %s"), disk->dst);
8548
        goto cleanup;
8549
    }
8550

8551
    priv = vm->privateData;
8552 8553
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
        goto cleanup;
8554

8555
    if (!virDomainObjIsActive(vm)) {
8556 8557
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8558 8559
        goto endjob;
    }
8560

8561
    qemuDomainObjEnterMonitor(driver, vm);
8562 8563 8564 8565
    ret = qemuMonitorGetBlockStatsInfo(priv->mon,
                                       disk->info.alias,
                                       &stats->rd_req,
                                       &stats->rd_bytes,
8566
                                       NULL,
8567 8568
                                       &stats->wr_req,
                                       &stats->wr_bytes,
8569 8570 8571
                                       NULL,
                                       NULL,
                                       NULL,
8572 8573
                                       &stats->errs);
    qemuDomainObjExitMonitor(driver, vm);
8574

8575
endjob:
8576 8577
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;
8578

8579
cleanup:
8580
    if (vm)
8581
        virObjectUnlock(vm);
8582
    return ret;
8583 8584
}

8585
static int
8586 8587 8588 8589 8590
qemuDomainBlockStatsFlags(virDomainPtr dom,
                          const char *path,
                          virTypedParameterPtr params,
                          int *nparams,
                          unsigned int flags)
8591
{
8592
    virQEMUDriverPtr driver = dom->conn->privateData;
8593 8594 8595 8596 8597 8598
    int i, tmp, ret = -1;
    virDomainObjPtr vm;
    virDomainDiskDefPtr disk = NULL;
    qemuDomainObjPrivatePtr priv;
    long long rd_req, rd_bytes, wr_req, wr_bytes, rd_total_times;
    long long wr_total_times, flush_req, flush_total_times, errs;
8599
    virTypedParameterPtr param;
8600

8601 8602 8603 8604
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
8605

8606
    if (!(vm = qemuDomObjFromDomain(dom)))
8607 8608
        goto cleanup;

8609 8610 8611
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
        goto cleanup;

8612
    if (!virDomainObjIsActive(vm)) {
8613 8614
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8615
        goto endjob;
8616 8617 8618
    }

    if (*nparams != 0) {
8619
        if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
8620 8621
            virReportError(VIR_ERR_INVALID_ARG,
                           _("invalid path: %s"), path);
8622
            goto endjob;
8623
        }
8624
        disk = vm->def->disks[i];
8625 8626

        if (!disk->info.alias) {
8627 8628 8629
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("missing disk device alias name for %s"),
                            disk->dst);
8630
             goto endjob;
8631 8632 8633 8634 8635 8636 8637 8638 8639 8640
        }
    }

    priv = vm->privateData;
    VIR_DEBUG("priv=%p, params=%p, flags=%x", priv, params, flags);

    qemuDomainObjEnterMonitor(driver, vm);
    tmp = *nparams;
    ret = qemuMonitorGetBlockStatsParamsNumber(priv->mon, nparams);

8641
    if (tmp == 0 || ret < 0) {
8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662
        qemuDomainObjExitMonitor(driver, vm);
        goto endjob;
    }

    ret = qemuMonitorGetBlockStatsInfo(priv->mon,
                                       disk->info.alias,
                                       &rd_req,
                                       &rd_bytes,
                                       &rd_total_times,
                                       &wr_req,
                                       &wr_bytes,
                                       &wr_total_times,
                                       &flush_req,
                                       &flush_total_times,
                                       &errs);

    qemuDomainObjExitMonitor(driver, vm);

    if (ret < 0)
        goto endjob;

8663 8664
    tmp = 0;
    ret = -1;
8665

8666 8667
    if (tmp < *nparams && wr_bytes != -1) {
        param = &params[tmp];
8668 8669
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES,
                                    VIR_TYPED_PARAM_LLONG, wr_bytes) < 0)
8670 8671 8672
            goto endjob;
        tmp++;
    }
8673

8674
    if (tmp < *nparams && wr_req != -1) {
8675
        param = &params[tmp];
8676 8677
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ,
                                    VIR_TYPED_PARAM_LLONG, wr_req) < 0)
8678 8679 8680
            goto endjob;
        tmp++;
    }
8681

8682
    if (tmp < *nparams && rd_bytes != -1) {
8683
        param = &params[tmp];
8684 8685
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_READ_BYTES,
                                    VIR_TYPED_PARAM_LLONG, rd_bytes) < 0)
8686 8687 8688
            goto endjob;
        tmp++;
    }
8689

8690
    if (tmp < *nparams && rd_req != -1) {
8691
        param = &params[tmp];
8692 8693
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_READ_REQ,
                                    VIR_TYPED_PARAM_LLONG, rd_req) < 0)
8694 8695 8696
            goto endjob;
        tmp++;
    }
8697

8698
    if (tmp < *nparams && flush_req != -1) {
8699
        param = &params[tmp];
8700 8701
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ,
                                    VIR_TYPED_PARAM_LLONG, flush_req) < 0)
8702 8703 8704
            goto endjob;
        tmp++;
    }
8705

8706
    if (tmp < *nparams && wr_total_times != -1) {
8707
        param = &params[tmp];
8708 8709 8710
        if (virTypedParameterAssign(param,
                                    VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES,
                                    VIR_TYPED_PARAM_LLONG, wr_total_times) < 0)
8711 8712 8713
            goto endjob;
        tmp++;
    }
8714

8715
    if (tmp < *nparams && rd_total_times != -1) {
8716
        param = &params[tmp];
8717 8718 8719
        if (virTypedParameterAssign(param,
                                    VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES,
                                    VIR_TYPED_PARAM_LLONG, rd_total_times) < 0)
8720 8721 8722
            goto endjob;
        tmp++;
    }
8723

8724
    if (tmp < *nparams && flush_total_times != -1) {
8725
        param = &params[tmp];
8726 8727 8728 8729
        if (virTypedParameterAssign(param,
                                    VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES,
                                    VIR_TYPED_PARAM_LLONG,
                                    flush_total_times) < 0)
8730 8731
            goto endjob;
        tmp++;
8732 8733
    }

8734 8735 8736 8737 8738
    /* Field 'errs' is meaningless for QEMU, won't set it. */

    ret = 0;
    *nparams = tmp;

8739 8740 8741 8742 8743 8744
endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    if (vm)
8745
        virObjectUnlock(vm);
8746 8747 8748
    return ret;
}

8749
#ifdef __linux__
8750
static int
8751 8752 8753
qemuDomainInterfaceStats(virDomainPtr dom,
                         const char *path,
                         struct _virDomainInterfaceStats *stats)
8754
{
8755
    virDomainObjPtr vm;
8756
    int i;
8757
    int ret = -1;
8758

8759
    if (!(vm = qemuDomObjFromDomain(dom)))
8760
        goto cleanup;
8761

D
Daniel P. Berrange 已提交
8762
    if (!virDomainObjIsActive(vm)) {
8763 8764
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8765
        goto cleanup;
8766 8767 8768
    }

    /* Check the path is one of the domain's network interfaces. */
8769
    for (i = 0; i < vm->def->nnets; i++) {
8770
        if (vm->def->nets[i]->ifname &&
8771
            STREQ(vm->def->nets[i]->ifname, path)) {
8772 8773 8774
            ret = 0;
            break;
        }
8775 8776
    }

8777
    if (ret == 0)
8778
        ret = linuxDomainInterfaceStats(path, stats);
8779
    else
8780 8781
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
8782

8783
cleanup:
8784
    if (vm)
8785
        virObjectUnlock(vm);
8786 8787
    return ret;
}
8788
#else
8789
static int
E
Eric Blake 已提交
8790
qemuDomainInterfaceStats(virDomainPtr dom ATTRIBUTE_UNUSED,
8791 8792
                         const char *path ATTRIBUTE_UNUSED,
                         struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
8793
{
8794 8795
    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                   _("interface stats not implemented on this platform"));
8796 8797
    return -1;
}
8798
#endif
8799

8800 8801 8802 8803 8804 8805 8806
static int
qemuDomainSetInterfaceParameters(virDomainPtr dom,
                                 const char *device,
                                 virTypedParameterPtr params,
                                 int nparams,
                                 unsigned int flags)
{
8807
    virQEMUDriverPtr driver = dom->conn->privateData;
8808 8809 8810 8811 8812
    int i;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr persistentDef = NULL;
    int ret = -1;
    virDomainNetDefPtr net = NULL, persistentNet = NULL;
8813
    virNetDevBandwidthPtr bandwidth = NULL, newBandwidth = NULL;
8814
    virQEMUDriverConfigPtr cfg = NULL;
8815
    virCapsPtr caps = NULL;
8816 8817 8818

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833
    if (virTypedParameterArrayValidate(params, nparams,
                                       VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
                                       VIR_TYPED_PARAM_UINT,
                                       VIR_DOMAIN_BANDWIDTH_IN_PEAK,
                                       VIR_TYPED_PARAM_UINT,
                                       VIR_DOMAIN_BANDWIDTH_IN_BURST,
                                       VIR_TYPED_PARAM_UINT,
                                       VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
                                       VIR_TYPED_PARAM_UINT,
                                       VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
                                       VIR_TYPED_PARAM_UINT,
                                       VIR_DOMAIN_BANDWIDTH_OUT_BURST,
                                       VIR_TYPED_PARAM_UINT,
                                       NULL) < 0)
        return -1;
8834

8835 8836
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
8837

8838 8839
    cfg = virQEMUDriverGetConfig(driver);

8840 8841 8842
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

8843
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
8844 8845 8846 8847 8848 8849
                                        &persistentDef) < 0)
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        net = virDomainNetFind(vm->def, device);
        if (!net) {
8850 8851
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Can't find device %s"), device);
8852 8853 8854 8855 8856 8857
            goto cleanup;
        }
    }
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        persistentNet = virDomainNetFind(persistentDef, device);
        if (!persistentNet) {
8858 8859
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Can't find device %s"), device);
8860 8861 8862 8863
            goto cleanup;
        }
    }

8864 8865 8866
    if ((VIR_ALLOC(bandwidth) < 0) ||
        (VIR_ALLOC(bandwidth->in) < 0) ||
        (VIR_ALLOC(bandwidth->out) < 0)) {
8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888
        virReportOOMError();
        goto cleanup;
    }

    for (i = 0; i < nparams; i++) {
        virTypedParameterPtr param = &params[i];

        if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE)) {
            bandwidth->in->average = params[i].value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_PEAK)) {
            bandwidth->in->peak = params[i].value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_BURST)) {
            bandwidth->in->burst = params[i].value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE)) {
            bandwidth->out->average = params[i].value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK)) {
            bandwidth->out->peak = params[i].value.ui;
        } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_BURST)) {
            bandwidth->out->burst = params[i].value.ui;
        }
    }

8889
    /* average is mandatory, peak and burst are optional. So if no
8890
     * average is given, we free inbound/outbound here which causes
8891
     * inbound/outbound to not be set. */
8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906
    if (!bandwidth->in->average) {
        VIR_FREE(bandwidth->in);
    }
    if (!bandwidth->out->average) {
        VIR_FREE(bandwidth->out);
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        if (VIR_ALLOC(newBandwidth) < 0) {
            virReportOOMError();
            goto cleanup;
        }

        /* virNetDevBandwidthSet() will clear any previous value of
         * bandwidth parameters, so merge with old bandwidth parameters
8907
         * here to prevent them from being lost. */
8908 8909
        if (bandwidth->in ||
            (net->bandwidth && net->bandwidth->in)) {
8910 8911 8912 8913
            if (VIR_ALLOC(newBandwidth->in) < 0) {
                virReportOOMError();
                goto cleanup;
            }
8914 8915 8916 8917 8918 8919 8920

            memcpy(newBandwidth->in,
                   bandwidth->in ? bandwidth->in : net->bandwidth->in,
                   sizeof(*newBandwidth->in));
        }
        if (bandwidth->out ||
            (net->bandwidth && net->bandwidth->out)) {
8921 8922 8923 8924
            if (VIR_ALLOC(newBandwidth->out) < 0) {
                virReportOOMError();
                goto cleanup;
            }
8925 8926 8927 8928

            memcpy(newBandwidth->out,
                   bandwidth->out ? bandwidth->out : net->bandwidth->out,
                   sizeof(*newBandwidth->out));
8929 8930
        }

8931
        if (virNetDevBandwidthSet(net->ifname, newBandwidth, false) < 0) {
8932 8933 8934
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("cannot set bandwidth limits on %s"),
                           device);
8935 8936 8937 8938 8939
            goto cleanup;
        }

        virNetDevBandwidthFree(net->bandwidth);
        net->bandwidth = newBandwidth;
E
Eric Blake 已提交
8940
        newBandwidth = NULL;
8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958
    }
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        if (!persistentNet->bandwidth) {
            persistentNet->bandwidth = bandwidth;
            bandwidth = NULL;
        } else {
            if (bandwidth->in) {
                VIR_FREE(persistentNet->bandwidth->in);
                persistentNet->bandwidth->in = bandwidth->in;
                bandwidth->in = NULL;
            }
            if (bandwidth->out) {
                VIR_FREE(persistentNet->bandwidth->out);
                persistentNet->bandwidth->out = bandwidth->out;
                bandwidth->out = NULL;
            }
        }

8959
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
8960 8961 8962 8963 8964 8965
            goto cleanup;
    }

    ret = 0;
cleanup:
    virNetDevBandwidthFree(bandwidth);
8966
    virNetDevBandwidthFree(newBandwidth);
8967
    if (vm)
8968
        virObjectUnlock(vm);
8969
    virObjectUnref(caps);
8970
    virObjectUnref(cfg);
8971 8972 8973 8974 8975 8976 8977 8978 8979 8980
    return ret;
}

static int
qemuDomainGetInterfaceParameters(virDomainPtr dom,
                                 const char *device,
                                 virTypedParameterPtr params,
                                 int *nparams,
                                 unsigned int flags)
{
8981
    virQEMUDriverPtr driver = dom->conn->privateData;
8982 8983 8984 8985 8986 8987
    int i;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainDefPtr persistentDef = NULL;
    virDomainNetDefPtr net = NULL;
    int ret = -1;
8988
    virCapsPtr caps = NULL;
8989 8990 8991 8992 8993 8994 8995

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

8996 8997
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
8998

8999 9000 9001
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

9002
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017
                                        &persistentDef) < 0)
        goto cleanup;

    if ((*nparams) == 0) {
        *nparams = QEMU_NB_BANDWIDTH_PARAM;
        ret = 0;
        goto cleanup;
    }

    def = persistentDef;
    if (!def)
        def = vm->def;

    net = virDomainNetFind(def, device);
    if (!net) {
9018 9019
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Can't find device %s"), device);
9020 9021 9022 9023
        goto cleanup;
    }

    for (i = 0; i < *nparams && i < QEMU_NB_BANDWIDTH_PARAM; i++) {
9024
        switch (i) {
9025
        case 0: /* inbound.average */
9026 9027 9028
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
9029 9030 9031 9032 9033
                goto cleanup;
            if (net->bandwidth && net->bandwidth->in)
                params[i].value.ui = net->bandwidth->in->average;
            break;
        case 1: /* inbound.peak */
9034 9035 9036
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_IN_PEAK,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
9037 9038 9039 9040 9041
                goto cleanup;
            if (net->bandwidth && net->bandwidth->in)
                params[i].value.ui = net->bandwidth->in->peak;
            break;
        case 2: /* inbound.burst */
9042 9043 9044
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_IN_BURST,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
9045 9046 9047 9048 9049
                goto cleanup;
            if (net->bandwidth && net->bandwidth->in)
                params[i].value.ui = net->bandwidth->in->burst;
            break;
        case 3: /* outbound.average */
9050 9051 9052
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
9053 9054 9055 9056 9057
                goto cleanup;
            if (net->bandwidth && net->bandwidth->out)
                params[i].value.ui = net->bandwidth->out->average;
            break;
        case 4: /* outbound.peak */
9058 9059 9060
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
9061 9062 9063 9064 9065
                goto cleanup;
            if (net->bandwidth && net->bandwidth->out)
                params[i].value.ui = net->bandwidth->out->peak;
            break;
        case 5: /* outbound.burst */
9066 9067 9068
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_OUT_BURST,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084
                goto cleanup;
            if (net->bandwidth && net->bandwidth->out)
                params[i].value.ui = net->bandwidth->out->burst;
            break;
        default:
            break;
            /* should not hit here */
        }
    }

    if (*nparams > QEMU_NB_BANDWIDTH_PARAM)
        *nparams = QEMU_NB_BANDWIDTH_PARAM;
    ret = 0;

cleanup:
    if (vm)
9085
        virObjectUnlock(vm);
9086
    virObjectUnref(caps);
9087 9088 9089
    return ret;
}

9090
static int
9091 9092 9093 9094
qemuDomainMemoryStats(virDomainPtr dom,
                      struct _virDomainMemoryStat *stats,
                      unsigned int nr_stats,
                      unsigned int flags)
9095
{
9096
    virQEMUDriverPtr driver = dom->conn->privateData;
9097
    virDomainObjPtr vm;
M
Martin Kletzander 已提交
9098
    int ret = -1;
9099

9100 9101
    virCheckFlags(0, -1);

9102
    if (!(vm = qemuDomObjFromDomain(dom)))
9103 9104
        goto cleanup;

9105
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
9106 9107
        goto cleanup;

M
Martin Kletzander 已提交
9108
    if (!virDomainObjIsActive(vm)) {
9109 9110
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
M
Martin Kletzander 已提交
9111
    } else {
9112
        qemuDomainObjPrivatePtr priv = vm->privateData;
9113
        qemuDomainObjEnterMonitor(driver, vm);
9114
        ret = qemuMonitorGetMemoryStats(priv->mon, stats, nr_stats);
9115
        qemuDomainObjExitMonitor(driver, vm);
M
Martin Kletzander 已提交
9116 9117 9118

        if (ret >= 0 && ret < nr_stats) {
            long rss;
9119
            if (qemuGetProcessInfo(NULL, NULL, &rss, vm->pid, 0) < 0) {
9120 9121
                virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                               _("cannot get RSS for domain"));
M
Martin Kletzander 已提交
9122 9123 9124 9125 9126 9127 9128
            } else {
                stats[ret].tag = VIR_DOMAIN_MEMORY_STAT_RSS;
                stats[ret].val = rss;
                ret++;
            }

        }
9129 9130
    }

9131
    if (qemuDomainObjEndJob(driver, vm) == 0)
9132 9133
        vm = NULL;

9134 9135
cleanup:
    if (vm)
9136
        virObjectUnlock(vm);
9137 9138 9139
    return ret;
}

9140
static int
9141 9142 9143 9144 9145
qemuDomainBlockPeek(virDomainPtr dom,
                    const char *path,
                    unsigned long long offset, size_t size,
                    void *buffer,
                    unsigned int flags)
9146
{
9147
    virDomainObjPtr vm;
9148 9149
    int fd = -1, ret = -1;
    const char *actual;
9150

E
Eric Blake 已提交
9151 9152
    virCheckFlags(0, -1);

9153
    if (!(vm = qemuDomObjFromDomain(dom)))
9154
        goto cleanup;
9155 9156

    if (!path || path[0] == '\0') {
9157 9158
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("NULL or empty path"));
9159
        goto cleanup;
9160 9161
    }

9162 9163
    /* Check the path belongs to this domain.  */
    if (!(actual = virDomainDiskPathByName(vm->def, path))) {
9164 9165
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path '%s'"), path);
9166
        goto cleanup;
9167
    }
9168
    path = actual;
9169

9170 9171 9172 9173 9174 9175 9176
    /* The path is correct, now try to open it and get its size. */
    fd = open(path, O_RDONLY);
    if (fd == -1) {
        virReportSystemError(errno,
                             _("%s: failed to open"), path);
        goto cleanup;
    }
9177

9178 9179 9180 9181 9182 9183 9184 9185 9186
    /* 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) {
        virReportSystemError(errno,
                             _("%s: failed to seek or read"), path);
        goto cleanup;
9187 9188
    }

9189 9190
    ret = 0;

9191
cleanup:
9192
    VIR_FORCE_CLOSE(fd);
9193
    if (vm)
9194
        virObjectUnlock(vm);
9195 9196 9197
    return ret;
}

R
Richard W.M. Jones 已提交
9198
static int
9199 9200 9201 9202
qemuDomainMemoryPeek(virDomainPtr dom,
                     unsigned long long offset, size_t size,
                     void *buffer,
                     unsigned int flags)
R
Richard W.M. Jones 已提交
9203
{
9204
    virQEMUDriverPtr driver = dom->conn->privateData;
9205
    virDomainObjPtr vm;
9206
    char *tmp = NULL;
R
Richard W.M. Jones 已提交
9207
    int fd = -1, ret = -1;
9208
    qemuDomainObjPrivatePtr priv;
9209
    virQEMUDriverConfigPtr cfg = NULL;
R
Richard W.M. Jones 已提交
9210

9211 9212
    virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);

9213
    if (!(vm = qemuDomObjFromDomain(dom)))
9214 9215
        goto cleanup;

9216 9217
    cfg = virQEMUDriverGetConfig(driver);

9218
    if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
9219 9220
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
9221
        goto cleanup;
R
Richard W.M. Jones 已提交
9222 9223
    }

9224
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
9225 9226
        goto cleanup;

D
Daniel P. Berrange 已提交
9227
    if (!virDomainObjIsActive(vm)) {
9228 9229
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
9230
        goto endjob;
R
Richard W.M. Jones 已提交
9231 9232
    }

9233
    if (virAsprintf(&tmp, "%s/qemu.mem.XXXXXX", cfg->cacheDir) < 0) {
9234
        virReportOOMError();
9235
        goto endjob;
9236 9237
    }

R
Richard W.M. Jones 已提交
9238
    /* Create a temporary filename. */
9239
    if ((fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
9240
        virReportSystemError(errno,
9241
                             _("mkostemp(\"%s\") failed"), tmp);
9242
        goto endjob;
R
Richard W.M. Jones 已提交
9243 9244
    }

9245
    virSecurityManagerSetSavedStateLabel(qemu_driver->securityManager, vm->def, tmp);
9246

9247
    priv = vm->privateData;
9248
    qemuDomainObjEnterMonitor(driver, vm);
9249
    if (flags == VIR_MEMORY_VIRTUAL) {
9250
        if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
9251
            qemuDomainObjExitMonitor(driver, vm);
9252
            goto endjob;
9253
        }
9254
    } else {
9255
        if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
9256
            qemuDomainObjExitMonitor(driver, vm);
9257
            goto endjob;
9258
        }
R
Richard W.M. Jones 已提交
9259
    }
9260
    qemuDomainObjExitMonitor(driver, vm);
R
Richard W.M. Jones 已提交
9261 9262

    /* Read the memory file into buffer. */
9263
    if (saferead(fd, buffer, size) == (ssize_t) -1) {
9264 9265 9266
        virReportSystemError(errno,
                             _("failed to read temporary file "
                               "created with template %s"), tmp);
9267
        goto endjob;
R
Richard W.M. Jones 已提交
9268 9269 9270
    }

    ret = 0;
9271

9272
endjob:
9273
    if (qemuDomainObjEndJob(driver, vm) == 0)
9274
        vm = NULL;
9275

9276
cleanup:
9277
    VIR_FORCE_CLOSE(fd);
9278 9279
    if (tmp)
        unlink(tmp);
W
Wen Congyang 已提交
9280
    VIR_FREE(tmp);
9281
    if (vm)
9282
        virObjectUnlock(vm);
9283
    virObjectUnref(cfg);
R
Richard W.M. Jones 已提交
9284 9285 9286
    return ret;
}

9287

9288 9289 9290 9291
static int qemuDomainGetBlockInfo(virDomainPtr dom,
                                  const char *path,
                                  virDomainBlockInfoPtr info,
                                  unsigned int flags) {
9292
    virQEMUDriverPtr driver = dom->conn->privateData;
9293 9294 9295 9296
    virDomainObjPtr vm;
    int ret = -1;
    int fd = -1;
    off_t end;
9297
    virStorageFileMetadata *meta = NULL;
9298
    virDomainDiskDefPtr disk = NULL;
9299
    struct stat sb;
9300
    int i;
9301
    int format;
9302
    virQEMUDriverConfigPtr cfg = NULL;
9303 9304 9305

    virCheckFlags(0, -1);

9306
    if (!(vm = qemuDomObjFromDomain(dom)))
9307 9308
        goto cleanup;

9309 9310
    cfg = virQEMUDriverGetConfig(driver);

9311
    if (!path || path[0] == '\0') {
9312 9313
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("NULL or empty path"));
9314 9315 9316 9317
        goto cleanup;
    }

    /* Check the path belongs to this domain. */
9318
    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
9319 9320
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path %s not assigned to domain"), path);
9321 9322
        goto cleanup;
    }
9323 9324
    disk = vm->def->disks[i];
    if (!disk->src) {
9325 9326 9327
        virReportError(VIR_ERR_INVALID_ARG,
                       _("disk %s does not currently have a source assigned"),
                       path);
9328 9329 9330
        goto cleanup;
    }
    path = disk->src;
9331 9332

    /* The path is correct, now try to open it and get its size. */
9333
    fd = open(path, O_RDONLY);
9334 9335 9336 9337 9338 9339 9340
    if (fd == -1) {
        virReportSystemError(errno,
                             _("failed to open path '%s'"), path);
        goto cleanup;
    }

    /* Probe for magic formats */
9341 9342
    if (disk->format) {
        format = disk->format;
9343
    } else {
9344 9345 9346 9347
        if (cfg->allowDiskFormatProbing) {
            if ((format = virStorageFileProbeFormat(disk->src,
                                                    cfg->user,
                                                    cfg->group)) < 0)
9348 9349
                goto cleanup;
        } else {
9350 9351 9352
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("no disk format for %s and probing is disabled"),
                           disk->src);
9353
            goto cleanup;
9354
        }
9355 9356
    }

9357
    if (!(meta = virStorageFileGetMetadataFromFD(path, fd, format)))
9358 9359 9360 9361 9362 9363 9364 9365 9366 9367
        goto cleanup;

    /* Get info for normal formats */
    if (fstat(fd, &sb) < 0) {
        virReportSystemError(errno,
                             _("cannot stat file '%s'"), path);
        goto cleanup;
    }

    if (S_ISREG(sb.st_mode)) {
9368
#ifndef WIN32
9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381
        info->physical = (unsigned long long)sb.st_blocks *
            (unsigned long long)DEV_BSIZE;
#else
        info->physical = sb.st_size;
#endif
        /* Regular files may be sparse, so logical size (capacity) is not same
         * as actual physical above
         */
        info->capacity = sb.st_size;
    } else {
        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
         * be 64 bits on all platforms.
         */
9382
        end = lseek(fd, 0, SEEK_END);
9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393
        if (end == (off_t)-1) {
            virReportSystemError(errno,
                                 _("failed to seek to end of %s"), path);
            goto cleanup;
        }
        info->physical = end;
        info->capacity = end;
    }

    /* If the file we probed has a capacity set, then override
     * what we calculated from file/block extents */
9394 9395
    if (meta->capacity)
        info->capacity = meta->capacity;
9396

9397
    /* Set default value .. */
9398 9399
    info->allocation = info->physical;

9400 9401 9402
    /* ..but if guest is running & not using raw
       disk format and on a block device, then query
       highest allocated extent from QEMU */
9403
    if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
9404
        format != VIR_STORAGE_FILE_RAW &&
9405 9406
        S_ISBLK(sb.st_mode) &&
        virDomainObjIsActive(vm)) {
9407
        qemuDomainObjPrivatePtr priv = vm->privateData;
9408

9409 9410
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
            goto cleanup;
9411

9412
        if (virDomainObjIsActive(vm)) {
9413
            qemuDomainObjEnterMonitor(driver, vm);
9414 9415 9416 9417
            ret = qemuMonitorGetBlockExtent(priv->mon,
                                            disk->info.alias,
                                            &info->allocation);
            qemuDomainObjExitMonitor(driver, vm);
9418
        } else {
9419
            ret = 0;
9420
        }
9421 9422 9423

        if (qemuDomainObjEndJob(driver, vm) == 0)
            vm = NULL;
9424 9425 9426
    } else {
        ret = 0;
    }
9427 9428

cleanup:
9429
    virStorageFileFreeMetadata(meta);
9430
    VIR_FORCE_CLOSE(fd);
9431
    if (vm)
9432
        virObjectUnlock(vm);
9433
    virObjectUnref(cfg);
9434 9435 9436 9437
    return ret;
}


9438
static int
9439 9440 9441 9442
qemuConnectDomainEventRegister(virConnectPtr conn,
                               virConnectDomainEventCallback callback,
                               void *opaque,
                               virFreeCallback freecb)
9443
{
9444
    virQEMUDriverPtr driver = conn->privateData;
9445 9446
    int ret;

9447 9448 9449
    ret = virDomainEventStateRegister(conn,
                                      driver->domainEventState,
                                      callback, opaque, freecb);
9450

9451
    return ret;
9452 9453
}

9454

9455
static int
9456 9457
qemuConnectDomainEventDeregister(virConnectPtr conn,
                                 virConnectDomainEventCallback callback)
9458
{
9459
    virQEMUDriverPtr driver = conn->privateData;
9460 9461
    int ret;

9462 9463 9464
    ret = virDomainEventStateDeregister(conn,
                                        driver->domainEventState,
                                        callback);
9465

9466
    return ret;
9467 9468
}

9469 9470

static int
9471 9472 9473 9474 9475 9476
qemuConnectDomainEventRegisterAny(virConnectPtr conn,
                                  virDomainPtr dom,
                                  int eventID,
                                  virConnectDomainEventGenericCallback callback,
                                  void *opaque,
                                  virFreeCallback freecb)
9477
{
9478
    virQEMUDriverPtr driver = conn->privateData;
9479 9480
    int ret;

9481 9482 9483 9484
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
9485
        ret = -1;
9486 9487 9488 9489 9490 9491

    return ret;
}


static int
9492 9493
qemuConnectDomainEventDeregisterAny(virConnectPtr conn,
                                    int callbackID)
9494
{
9495
    virQEMUDriverPtr driver = conn->privateData;
9496 9497
    int ret;

9498 9499 9500
    ret = virDomainEventStateDeregisterID(conn,
                                          driver->domainEventState,
                                          callbackID);
9501 9502 9503 9504 9505

    return ret;
}


9506 9507 9508
/*******************************************************************
 * Migration Protocol Version 2
 *******************************************************************/
D
Daniel Veillard 已提交
9509

C
Chris Lalancette 已提交
9510 9511 9512 9513 9514 9515
/* 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
9516 9517 9518 9519 9520 9521
qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
                               virStreamPtr st,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource ATTRIBUTE_UNUSED,
                               const char *dom_xml)
C
Chris Lalancette 已提交
9522
{
9523
    virQEMUDriverPtr driver = dconn->privateData;
9524 9525
    virCapsPtr caps = NULL;
    virDomainDefPtr def = NULL;
C
Chris Lalancette 已提交
9526
    int ret = -1;
9527

9528
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9529

C
Chris Lalancette 已提交
9530
    if (!dom_xml) {
9531 9532
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
C
Chris Lalancette 已提交
9533 9534 9535
        goto cleanup;
    }
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
9536 9537
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
C
Chris Lalancette 已提交
9538 9539 9540
        goto cleanup;
    }
    if (st == NULL) {
9541 9542
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("tunnelled migration requested but NULL stream passed"));
C
Chris Lalancette 已提交
9543 9544 9545
        goto cleanup;
    }

9546
    if (virLockManagerPluginUsesState(driver->lockManager)) {
9547 9548 9549
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Cannot use migrate v2 protocol with lock manager %s"),
                       virLockManagerPluginGetName(driver->lockManager));
9550 9551 9552
        goto cleanup;
    }

9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt,
                                        QEMU_EXPECTED_VIRT_TYPES,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

    if (dname) {
        VIR_FREE(def->name);
        if (!(def->name = strdup(dname))) {
            virReportOOMError();
            goto cleanup;
        }
    }

9569 9570
    ret = qemuMigrationPrepareTunnel(driver, dconn,
                                     NULL, 0, NULL, NULL, /* No cookies in v2 */
9571 9572
                                     st, def, flags);
    def = NULL;
9573

C
Chris Lalancette 已提交
9574
cleanup:
9575 9576
    virDomainDefFree(def);
    virObjectUnref(caps);
C
Chris Lalancette 已提交
9577 9578 9579
    return ret;
}

D
Daniel Veillard 已提交
9580 9581 9582 9583
/* Prepare is the first step, and it runs on the destination host.
 *
 * This starts an empty VM listening on a TCP port.
 */
9584
static int ATTRIBUTE_NONNULL(5)
9585 9586 9587 9588 9589 9590 9591 9592 9593
qemuDomainMigratePrepare2(virConnectPtr dconn,
                          char **cookie ATTRIBUTE_UNUSED,
                          int *cookielen ATTRIBUTE_UNUSED,
                          const char *uri_in,
                          char **uri_out,
                          unsigned long flags,
                          const char *dname,
                          unsigned long resource ATTRIBUTE_UNUSED,
                          const char *dom_xml)
D
Daniel Veillard 已提交
9594
{
9595
    virQEMUDriverPtr driver = dconn->privateData;
9596 9597
    virCapsPtr caps = NULL;
    virDomainDefPtr def = NULL;
9598
    int ret = -1;
9599

9600
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
C
Chris Lalancette 已提交
9601

9602
    *uri_out = NULL;
D
Daniel Veillard 已提交
9603

9604
    if (virLockManagerPluginUsesState(driver->lockManager)) {
9605 9606 9607
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Cannot use migrate v2 protocol with lock manager %s"),
                       virLockManagerPluginGetName(driver->lockManager));
9608 9609 9610
        goto cleanup;
    }

C
Chris Lalancette 已提交
9611 9612 9613 9614
    if (flags & VIR_MIGRATE_TUNNELLED) {
        /* this is a logical error; we never should have gotten here with
         * VIR_MIGRATE_TUNNELLED set
         */
9615 9616
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Tunnelled migration requested but invalid RPC method called"));
C
Chris Lalancette 已提交
9617 9618 9619
        goto cleanup;
    }

D
Daniel Veillard 已提交
9620
    if (!dom_xml) {
9621 9622
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
9623
        goto cleanup;
D
Daniel Veillard 已提交
9624 9625
    }

9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt,
                                        QEMU_EXPECTED_VIRT_TYPES,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

    if (dname) {
        VIR_FREE(def->name);
        if (!(def->name = strdup(dname))) {
            virReportOOMError();
            goto cleanup;
        }
    }

9642 9643 9644 9645
    /* Do not use cookies in v2 protocol, since the cookie
     * length was not sufficiently large, causing failures
     * migrating between old & new libvirtd
     */
9646
    ret = qemuMigrationPrepareDirect(driver, dconn,
9647
                                     NULL, 0, NULL, NULL, /* No cookies */
9648
                                     uri_in, uri_out,
9649 9650
                                     def, flags);
    def = NULL;
D
Daniel Veillard 已提交
9651

9652
cleanup:
9653 9654
    virDomainDefFree(def);
    virObjectUnref(caps);
9655 9656
    return ret;
}
C
Chris Lalancette 已提交
9657

D
Daniel Veillard 已提交
9658

9659 9660
/* Perform is the second step, and it runs on the source host. */
static int
9661 9662 9663 9664 9665 9666 9667
qemuDomainMigratePerform(virDomainPtr dom,
                         const char *cookie,
                         int cookielen,
                         const char *uri,
                         unsigned long flags,
                         const char *dname,
                         unsigned long resource)
9668
{
9669
    virQEMUDriverPtr driver = dom->conn->privateData;
9670 9671
    virDomainObjPtr vm;
    int ret = -1;
9672
    const char *dconnuri = NULL;
9673

9674
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
C
Chris Lalancette 已提交
9675

9676
    if (virLockManagerPluginUsesState(driver->lockManager)) {
9677 9678 9679
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Cannot use migrate v2 protocol with lock manager %s"),
                       virLockManagerPluginGetName(driver->lockManager));
9680 9681 9682
        goto cleanup;
    }

9683
    if (!(vm = qemuDomObjFromDomain(dom)))
9684
        goto cleanup;
D
Daniel Veillard 已提交
9685

9686 9687 9688 9689 9690
    if (flags & VIR_MIGRATE_PEER2PEER) {
        dconnuri = uri;
        uri = NULL;
    }

9691 9692 9693 9694 9695 9696
    /* Do not output cookies in v2 protocol, since the cookie
     * length was not sufficiently large, causing failures
     * migrating between old & new libvirtd.
     *
     * Consume any cookie we were able to decode though
     */
9697
    ret = qemuMigrationPerform(driver, dom->conn, vm,
9698
                               NULL, dconnuri, uri, cookie, cookielen,
9699
                               NULL, NULL, /* No output cookies in v2 */
9700
                               flags, dname, resource, false);
9701

9702
cleanup:
9703
    return ret;
D
Daniel Veillard 已提交
9704 9705
}

9706

D
Daniel Veillard 已提交
9707 9708
/* Finish is the third and final step, and it runs on the destination host. */
static virDomainPtr
9709 9710 9711 9712 9713 9714 9715
qemuDomainMigrateFinish2(virConnectPtr dconn,
                         const char *dname,
                         const char *cookie ATTRIBUTE_UNUSED,
                         int cookielen ATTRIBUTE_UNUSED,
                         const char *uri ATTRIBUTE_UNUSED,
                         unsigned long flags,
                         int retcode)
D
Daniel Veillard 已提交
9716
{
9717
    virQEMUDriverPtr driver = dconn->privateData;
9718 9719
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
D
Daniel Veillard 已提交
9720

9721
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
C
Chris Lalancette 已提交
9722

9723
    vm = virDomainObjListFindByName(driver->domains, dname);
D
Daniel Veillard 已提交
9724
    if (!vm) {
9725 9726
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching name '%s'"), dname);
9727
        goto cleanup;
D
Daniel Veillard 已提交
9728 9729
    }

9730 9731 9732 9733
    /* Do not use cookies in v2 protocol, since the cookie
     * length was not sufficiently large, causing failures
     * migrating between old & new libvirtd
     */
9734
    dom = qemuMigrationFinish(driver, dconn, vm,
9735
                              NULL, 0, NULL, NULL, /* No cookies */
9736
                              flags, retcode, false);
9737

9738 9739
cleanup:
    return dom;
D
Daniel Veillard 已提交
9740 9741
}

9742

9743 9744 9745 9746 9747 9748
/*******************************************************************
 * Migration Protocol Version 3
 *******************************************************************/

static char *
qemuDomainMigrateBegin3(virDomainPtr domain,
9749
                        const char *xmlin,
9750 9751 9752
                        char **cookieout,
                        int *cookieoutlen,
                        unsigned long flags,
9753
                        const char *dname,
9754 9755
                        unsigned long resource ATTRIBUTE_UNUSED)
{
9756
    virQEMUDriverPtr driver = domain->conn->privateData;
9757 9758
    virDomainObjPtr vm;
    char *xml = NULL;
9759
    enum qemuDomainAsyncJob asyncJob;
9760

9761
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
9762

9763 9764
    if (!(vm = qemuDomObjFromDomain(domain)))
        return NULL;
9765

9766 9767 9768
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            goto cleanup;
9769
        asyncJob = QEMU_ASYNC_JOB_MIGRATION_OUT;
9770
    } else {
9771
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9772
            goto cleanup;
9773
        asyncJob = QEMU_ASYNC_JOB_NONE;
9774 9775
    }

L
liguang 已提交
9776
    if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
9777 9778
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
9779 9780 9781
        goto endjob;
    }

9782 9783 9784
    /* Check if there is any ejected media.
     * We don't want to require them on the destination.
     */
L
liguang 已提交
9785 9786
    if (!(flags & VIR_MIGRATE_OFFLINE) &&
        qemuDomainCheckEjectableMedia(driver, vm, asyncJob) < 0)
9787 9788
        goto endjob;

9789
    if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname,
9790 9791
                                   cookieout, cookieoutlen,
                                   flags)))
9792 9793 9794 9795 9796 9797 9798
        goto endjob;

    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        /* We keep the job active across API calls until the confirm() call.
         * This prevents any other APIs being invoked while migration is taking
         * place.
         */
9799 9800
        if (virQEMUCloseCallbacksSet(driver->closeCallbacks, vm, domain->conn,
                                     qemuMigrationCleanup) < 0)
9801
            goto endjob;
9802 9803
        if (qemuMigrationJobContinue(vm) == 0) {
            vm = NULL;
9804 9805
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("domain disappeared"));
9806 9807 9808 9809 9810 9811 9812
            VIR_FREE(xml);
            if (cookieout)
                VIR_FREE(*cookieout);
        }
    } else {
        goto endjob;
    }
9813 9814

cleanup:
9815
    if (vm)
9816
        virObjectUnlock(vm);
9817
    return xml;
9818 9819 9820 9821 9822 9823 9824 9825 9826 9827

endjob:
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobFinish(driver, vm) == 0)
            vm = NULL;
    } else {
        if (qemuDomainObjEndJob(driver, vm) == 0)
            vm = NULL;
    }
    goto cleanup;
9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842
}

static int
qemuDomainMigratePrepare3(virConnectPtr dconn,
                          const char *cookiein,
                          int cookieinlen,
                          char **cookieout,
                          int *cookieoutlen,
                          const char *uri_in,
                          char **uri_out,
                          unsigned long flags,
                          const char *dname,
                          unsigned long resource ATTRIBUTE_UNUSED,
                          const char *dom_xml)
{
9843
    virQEMUDriverPtr driver = dconn->privateData;
9844 9845
    virCapsPtr caps = NULL;
    virDomainDefPtr def = NULL;
9846 9847
    int ret = -1;

9848
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9849 9850 9851 9852 9853 9854 9855

    *uri_out = NULL;

    if (flags & VIR_MIGRATE_TUNNELLED) {
        /* this is a logical error; we never should have gotten here with
         * VIR_MIGRATE_TUNNELLED set
         */
9856 9857
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Tunnelled migration requested but invalid RPC method called"));
9858 9859 9860 9861
        goto cleanup;
    }

    if (!dom_xml) {
9862 9863
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
9864 9865 9866
        goto cleanup;
    }

9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt,
                                        QEMU_EXPECTED_VIRT_TYPES,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

    if (dname) {
        VIR_FREE(def->name);
        if (!(def->name = strdup(dname))) {
            virReportOOMError();
            goto cleanup;
        }
    }

9883 9884 9885 9886
    ret = qemuMigrationPrepareDirect(driver, dconn,
                                     cookiein, cookieinlen,
                                     cookieout, cookieoutlen,
                                     uri_in, uri_out,
9887 9888
                                     def, flags);
    def = NULL;
9889 9890

cleanup:
9891 9892
    virDomainDefFree(def);
    virObjectUnref(caps);
9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908
    return ret;
}


static int
qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
                                virStreamPtr st,
                                const char *cookiein,
                                int cookieinlen,
                                char **cookieout,
                                int *cookieoutlen,
                                unsigned long flags,
                                const char *dname,
                                unsigned long resource ATTRIBUTE_UNUSED,
                                const char *dom_xml)
{
9909
    virQEMUDriverPtr driver = dconn->privateData;
9910 9911
    virCapsPtr caps = NULL;
    virDomainDefPtr def = NULL;
9912 9913
    int ret = -1;

9914
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9915 9916

    if (!dom_xml) {
9917 9918
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
9919 9920 9921
        goto cleanup;
    }
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
9922 9923
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
9924 9925 9926
        goto cleanup;
    }
    if (st == NULL) {
9927 9928
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("tunnelled migration requested but NULL stream passed"));
9929 9930 9931
        goto cleanup;
    }

9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!(def = virDomainDefParseString(dom_xml, caps, driver->xmlopt,
                                        QEMU_EXPECTED_VIRT_TYPES,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

    if (dname) {
        VIR_FREE(def->name);
        if (!(def->name = strdup(dname))) {
            virReportOOMError();
            goto cleanup;
        }
    }

9948 9949 9950
    ret = qemuMigrationPrepareTunnel(driver, dconn,
                                     cookiein, cookieinlen,
                                     cookieout, cookieoutlen,
9951 9952
                                     st, def, flags);
    def = NULL;
9953 9954

cleanup:
9955 9956
    virDomainDefFree(def);
    virObjectUnref(caps);
9957 9958 9959 9960 9961 9962
    return ret;
}


static int
qemuDomainMigratePerform3(virDomainPtr dom,
9963
                          const char *xmlin,
9964 9965 9966 9967
                          const char *cookiein,
                          int cookieinlen,
                          char **cookieout,
                          int *cookieoutlen,
9968
                          const char *dconnuri,
9969 9970 9971 9972 9973
                          const char *uri,
                          unsigned long flags,
                          const char *dname,
                          unsigned long resource)
{
9974
    virQEMUDriverPtr driver = dom->conn->privateData;
9975 9976
    virDomainObjPtr vm;

9977
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9978

9979 9980
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
9981

9982 9983 9984 9985
    return qemuMigrationPerform(driver, dom->conn, vm, xmlin,
                                dconnuri, uri, cookiein, cookieinlen,
                                cookieout, cookieoutlen,
                                flags, dname, resource, true);
9986 9987 9988
}


9989
static virDomainPtr
9990 9991 9992 9993 9994 9995
qemuDomainMigrateFinish3(virConnectPtr dconn,
                         const char *dname,
                         const char *cookiein,
                         int cookieinlen,
                         char **cookieout,
                         int *cookieoutlen,
9996
                         const char *dconnuri ATTRIBUTE_UNUSED,
9997 9998
                         const char *uri ATTRIBUTE_UNUSED,
                         unsigned long flags,
9999
                         int cancelled)
10000
{
10001
    virQEMUDriverPtr driver = dconn->privateData;
10002
    virDomainObjPtr vm;
10003
    virDomainPtr dom = NULL;
10004

10005
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
10006

10007
    vm = virDomainObjListFindByName(driver->domains, dname);
10008
    if (!vm) {
10009 10010
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching name '%s'"), dname);
10011 10012 10013
        goto cleanup;
    }

10014 10015 10016 10017
    dom = qemuMigrationFinish(driver, dconn, vm,
                              cookiein, cookieinlen,
                              cookieout, cookieoutlen,
                              flags, cancelled, true);
10018 10019

cleanup:
10020
    return dom;
10021 10022 10023 10024 10025 10026 10027 10028 10029
}

static int
qemuDomainMigrateConfirm3(virDomainPtr domain,
                          const char *cookiein,
                          int cookieinlen,
                          unsigned long flags,
                          int cancelled)
{
10030
    virQEMUDriverPtr driver = domain->conn->privateData;
10031 10032
    virDomainObjPtr vm;
    int ret = -1;
10033
    enum qemuMigrationJobPhase phase;
10034
    virQEMUDriverConfigPtr cfg = NULL;
10035

10036
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
10037

10038 10039
    if (!(vm = qemuDomObjFromDomain(domain)))
        return -1;
10040

10041 10042
    cfg = virQEMUDriverGetConfig(driver);

10043
    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT))
10044 10045
        goto cleanup;

10046 10047 10048 10049 10050 10051
    if (cancelled)
        phase = QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED;
    else
        phase = QEMU_MIGRATION_PHASE_CONFIRM3;

    qemuMigrationJobStartPhase(driver, vm, phase);
10052 10053
    virQEMUCloseCallbacksUnset(driver->closeCallbacks, vm,
                               qemuMigrationCleanup);
10054

10055 10056
    ret = qemuMigrationConfirm(driver, domain->conn, vm,
                               cookiein, cookieinlen,
10057 10058
                               flags, cancelled);

10059
    if (qemuMigrationJobFinish(driver, vm) == 0) {
10060 10061 10062 10063
        vm = NULL;
    } else if (!virDomainObjIsActive(vm) &&
               (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) {
        if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
10064
            virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
10065
        qemuDomainRemoveInactive(driver, vm);
10066 10067 10068
        vm = NULL;
    }

10069
cleanup:
10070
    if (vm)
10071
        virObjectUnlock(vm);
10072
    virObjectUnref(cfg);
10073 10074 10075 10076
    return ret;
}


10077
static int
10078 10079 10080 10081 10082
qemuNodeDeviceGetPciInfo(virNodeDevicePtr dev,
                         unsigned *domain,
                         unsigned *bus,
                         unsigned *slot,
                         unsigned *function)
10083 10084 10085 10086 10087 10088 10089 10090 10091 10092
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

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

10093
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
10094 10095 10096 10097 10098 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110
    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) {
10111 10112
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123
        goto out;
    }

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

static int
10124 10125 10126
qemuNodeDeviceDetachFlags(virNodeDevicePtr dev,
                          const char *driverName,
                          unsigned int flags)
10127
{
10128
    virQEMUDriverPtr driver = dev->conn->privateData;
10129
    virPCIDevicePtr pci;
10130 10131
    unsigned domain, bus, slot, function;
    int ret = -1;
10132
    bool in_inactive_list = false;
10133

10134 10135
    virCheckFlags(0, -1);

10136
    if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
10137 10138
        return -1;

10139
    pci = virPCIDeviceNew(domain, bus, slot, function);
10140 10141 10142
    if (!pci)
        return -1;

10143 10144 10145 10146 10147 10148 10149 10150 10151 10152
    if (!driverName || STREQ(driverName, "kvm")) {
        virPCIDeviceSetStubDriver(pci, "pci-stub");
    } else if (STREQ(driverName, "vfio")) {
        virPCIDeviceSetStubDriver(pci, "vfio-pci");
    } else {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unknown driver name '%s'"), driverName);
        goto out;
    }

10153 10154
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);
10155
    in_inactive_list = virPCIDeviceListFind(driver->inactivePciHostdevs, pci);
10156

10157
    if (virPCIDeviceDetach(pci, driver->activePciHostdevs,
10158
                           driver->inactivePciHostdevs, NULL) < 0)
10159 10160 10161 10162
        goto out;

    ret = 0;
out:
10163 10164
    virObjectUnlock(driver->inactivePciHostdevs);
    virObjectUnlock(driver->activePciHostdevs);
10165
    if (in_inactive_list)
10166
        virPCIDeviceFree(pci);
10167 10168 10169
    return ret;
}

10170 10171 10172 10173 10174 10175
static int
qemuNodeDeviceDettach(virNodeDevicePtr dev)
{
    return qemuNodeDeviceDetachFlags(dev, NULL, 0);
}

10176
static int
10177
qemuNodeDeviceReAttach(virNodeDevicePtr dev)
10178
{
10179
    virQEMUDriverPtr driver = dev->conn->privateData;
10180 10181
    virPCIDevicePtr pci;
    virPCIDevicePtr other;
10182 10183 10184
    unsigned domain, bus, slot, function;
    int ret = -1;

10185
    if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
10186 10187
        return -1;

10188
    pci = virPCIDeviceNew(domain, bus, slot, function);
10189 10190 10191
    if (!pci)
        return -1;

10192 10193
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);
10194
    other = virPCIDeviceListFind(driver->activePciHostdevs, pci);
10195
    if (other) {
10196
        const char *other_name = virPCIDeviceGetUsedBy(other);
10197 10198

        if (other_name)
10199 10200
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("PCI device %s is still in use by domain %s"),
10201
                           virPCIDeviceGetName(pci), other_name);
10202
        else
10203 10204
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("PCI device %s is still in use"),
10205
                           virPCIDeviceGetName(pci));
10206
        goto out;
10207 10208
    }

10209
    virPCIDeviceReattachInit(pci);
10210

10211
    if (virPCIDeviceReattach(pci, driver->activePciHostdevs,
10212
                             driver->inactivePciHostdevs) < 0)
10213 10214 10215 10216
        goto out;

    ret = 0;
out:
10217 10218
    virObjectUnlock(driver->inactivePciHostdevs);
    virObjectUnlock(driver->activePciHostdevs);
10219
    virPCIDeviceFree(pci);
10220 10221 10222 10223
    return ret;
}

static int
10224
qemuNodeDeviceReset(virNodeDevicePtr dev)
10225
{
10226
    virQEMUDriverPtr driver = dev->conn->privateData;
10227
    virPCIDevicePtr pci;
10228 10229 10230
    unsigned domain, bus, slot, function;
    int ret = -1;

10231
    if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
10232 10233
        return -1;

10234
    pci = virPCIDeviceNew(domain, bus, slot, function);
10235 10236 10237
    if (!pci)
        return -1;

10238 10239
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);
10240

10241 10242
    if (virPCIDeviceReset(pci, driver->activePciHostdevs,
                          driver->inactivePciHostdevs) < 0)
10243 10244 10245 10246
        goto out;

    ret = 0;
out:
10247 10248
    virObjectUnlock(driver->inactivePciHostdevs);
    virObjectUnlock(driver->activePciHostdevs);
10249
    virPCIDeviceFree(pci);
10250 10251 10252
    return ret;
}

10253
static int
10254 10255 10256
qemuConnectCompareCPU(virConnectPtr conn,
                      const char *xmlDesc,
                      unsigned int flags)
10257
{
10258
    virQEMUDriverPtr driver = conn->privateData;
10259
    int ret = VIR_CPU_COMPARE_ERROR;
10260
    virCapsPtr caps = NULL;
10261

E
Eric Blake 已提交
10262 10263
    virCheckFlags(0, VIR_CPU_COMPARE_ERROR);

10264 10265 10266 10267 10268
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!caps->host.cpu ||
        !caps->host.cpu->model) {
10269 10270
        VIR_WARN("cannot get host CPU capabilities");
        ret = VIR_CPU_COMPARE_INCOMPATIBLE;
E
Eric Blake 已提交
10271
    } else {
10272
        ret = cpuCompareXML(caps->host.cpu, xmlDesc);
E
Eric Blake 已提交
10273
    }
10274

10275 10276
cleanup:
    virObjectUnref(caps);
10277 10278 10279
    return ret;
}

10280

10281
static char *
10282 10283 10284 10285
qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
                       const char **xmlCPUs,
                       unsigned int ncpus,
                       unsigned int flags)
10286 10287 10288
{
    char *cpu;

E
Eric Blake 已提交
10289 10290
    virCheckFlags(0, NULL);

10291 10292 10293 10294 10295
    cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0);

    return cpu;
}

10296 10297 10298 10299 10300 10301 10302

static int qemuDomainGetJobInfo(virDomainPtr dom,
                                virDomainJobInfoPtr info) {
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

10303
    if (!(vm = qemuDomObjFromDomain(dom)))
10304 10305 10306 10307 10308
        goto cleanup;

    priv = vm->privateData;

    if (virDomainObjIsActive(vm)) {
10309
        if (priv->job.asyncJob && !priv->job.dump_memory_only) {
10310
            memcpy(info, &priv->job.info, sizeof(*info));
10311 10312 10313 10314 10315 10316

            /* Refresh elapsed time again just to ensure it
             * is fully updated. This is primarily for benefit
             * of incoming migration which we don't currently
             * monitor actively in the background thread
             */
10317
            if (virTimeMillisNow(&info->timeElapsed) < 0)
10318
                goto cleanup;
10319
            info->timeElapsed -= priv->job.start;
10320 10321 10322 10323 10324
        } else {
            memset(info, 0, sizeof(*info));
            info->type = VIR_DOMAIN_JOB_NONE;
        }
    } else {
10325 10326
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
10327 10328 10329 10330 10331 10332 10333
        goto cleanup;
    }

    ret = 0;

cleanup:
    if (vm)
10334
        virObjectUnlock(vm);
10335 10336 10337 10338
    return ret;
}


10339 10340 10341 10342 10343 10344 10345 10346 10347 10348 10349 10350 10351 10352 10353 10354 10355 10356 10357 10358 10359 10360 10361 10362 10363 10364 10365 10366 10367 10368 10369 10370 10371 10372 10373 10374 10375 10376 10377 10378 10379 10380 10381 10382 10383 10384 10385 10386 10387 10388 10389 10390 10391 10392 10393 10394 10395 10396 10397 10398 10399 10400 10401 10402 10403 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 10442 10443 10444 10445 10446 10447 10448 10449 10450 10451 10452 10453 10454 10455 10456 10457 10458 10459 10460 10461 10462 10463 10464 10465 10466 10467 10468 10469 10470 10471 10472 10473 10474 10475 10476 10477 10478
static int
qemuDomainGetJobStats(virDomainPtr dom,
                      int *type,
                      virTypedParameterPtr *params,
                      int *nparams,
                      unsigned int flags)
{
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    virTypedParameterPtr par = NULL;
    int maxpar = 0;
    int npar = 0;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    priv = vm->privateData;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    if (!priv->job.asyncJob || priv->job.dump_memory_only) {
        *type = VIR_DOMAIN_JOB_NONE;
        *params = NULL;
        *nparams = 0;
        ret = 0;
        goto cleanup;
    }

    /* Refresh elapsed time again just to ensure it
     * is fully updated. This is primarily for benefit
     * of incoming migration which we don't currently
     * monitor actively in the background thread
     */
    if (virTimeMillisNow(&priv->job.info.timeElapsed) < 0)
        goto cleanup;
    priv->job.info.timeElapsed -= priv->job.start;

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_TIME_ELAPSED,
                                priv->job.info.timeElapsed) < 0)
        goto cleanup;

    if (priv->job.info.type == VIR_DOMAIN_JOB_BOUNDED &&
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_TIME_REMAINING,
                                priv->job.info.timeRemaining) < 0)
        goto cleanup;

    if (priv->job.status.downtime_set &&
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DOWNTIME,
                                priv->job.status.downtime) < 0)
        goto cleanup;

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DATA_TOTAL,
                                priv->job.info.dataTotal) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DATA_PROCESSED,
                                priv->job.info.dataProcessed) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DATA_REMAINING,
                                priv->job.info.dataRemaining) < 0)
        goto cleanup;

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_MEMORY_TOTAL,
                                priv->job.info.memTotal) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_MEMORY_PROCESSED,
                                priv->job.info.memProcessed) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_MEMORY_REMAINING,
                                priv->job.info.memRemaining) < 0)
        goto cleanup;

    if (priv->job.status.ram_duplicate_set) {
        if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_MEMORY_CONSTANT,
                                    priv->job.status.ram_duplicate) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_MEMORY_NORMAL,
                                    priv->job.status.ram_normal) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES,
                                    priv->job.status.ram_normal_bytes) < 0)
            goto cleanup;
    }

    if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DISK_TOTAL,
                                priv->job.info.fileTotal) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DISK_PROCESSED,
                                priv->job.info.fileProcessed) < 0 ||
        virTypedParamsAddULLong(&par, &npar, &maxpar,
                                VIR_DOMAIN_JOB_DISK_REMAINING,
                                priv->job.info.fileRemaining) < 0)
        goto cleanup;

    if (priv->job.status.xbzrle_set) {
        if (virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_CACHE,
                                    priv->job.status.xbzrle_cache_size) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_BYTES,
                                    priv->job.status.xbzrle_bytes) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_PAGES,
                                    priv->job.status.xbzrle_pages) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES,
                                    priv->job.status.xbzrle_cache_miss) < 0 ||
            virTypedParamsAddULLong(&par, &npar, &maxpar,
                                    VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW,
                                    priv->job.status.xbzrle_overflow) < 0)
            goto cleanup;
    }

    *type = priv->job.info.type;
    *params = par;
    *nparams = npar;
    ret = 0;

cleanup:
    if (vm)
        virObjectUnlock(vm);
    if (ret < 0)
        virTypedParamsFree(par, npar);
    return ret;
}


10479
static int qemuDomainAbortJob(virDomainPtr dom) {
10480
    virQEMUDriverPtr driver = dom->conn->privateData;
10481 10482 10483 10484
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

10485
    if (!(vm = qemuDomObjFromDomain(dom)))
10486 10487
        goto cleanup;

10488 10489
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_ABORT) < 0)
        goto cleanup;
10490

10491
    if (!virDomainObjIsActive(vm)) {
10492 10493
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
10494
        goto endjob;
10495 10496
    }

10497 10498
    priv = vm->privateData;

10499
    if (!priv->job.asyncJob || priv->job.dump_memory_only) {
10500 10501
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("no job is active on the domain"));
10502 10503
        goto endjob;
    } else if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
10504 10505 10506
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot abort incoming migration;"
                         " use virDomainDestroy instead"));
10507 10508 10509 10510
        goto endjob;
    }

    VIR_DEBUG("Cancelling job at client request");
10511
    qemuDomainObjAbortAsyncJob(vm);
10512
    qemuDomainObjEnterMonitor(driver, vm);
10513 10514 10515 10516 10517 10518
    ret = qemuMonitorMigrateCancel(priv->mon);
    qemuDomainObjExitMonitor(driver, vm);

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;
10519 10520 10521

cleanup:
    if (vm)
10522
        virObjectUnlock(vm);
10523 10524 10525 10526
    return ret;
}


10527 10528 10529 10530 10531
static int
qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
                                unsigned long long downtime,
                                unsigned int flags)
{
10532
    virQEMUDriverPtr driver = dom->conn->privateData;
10533 10534 10535 10536
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

10537
    virCheckFlags(0, -1);
10538

10539 10540
    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;
10541

10542 10543 10544
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
        goto cleanup;

10545
    if (!virDomainObjIsActive(vm)) {
10546 10547
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
10548
        goto endjob;
10549 10550 10551 10552
    }

    priv = vm->privateData;

10553
    if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) {
10554 10555
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not being migrated"));
10556
        goto endjob;
10557 10558
    }

10559
    VIR_DEBUG("Setting migration downtime to %llums", downtime);
10560
    qemuDomainObjEnterMonitor(driver, vm);
10561 10562 10563 10564 10565 10566
    ret = qemuMonitorSetMigrationDowntime(priv->mon, downtime);
    qemuDomainObjExitMonitor(driver, vm);

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;
10567 10568 10569

cleanup:
    if (vm)
10570
        virObjectUnlock(vm);
10571 10572 10573
    return ret;
}

10574 10575 10576 10577 10578 10579 10580 10581 10582 10583 10584 10585 10586 10587 10588 10589 10590 10591 10592 10593 10594 10595 10596 10597 10598 10599 10600 10601 10602 10603 10604 10605 10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618 10619 10620 10621 10622 10623 10624 10625 10626 10627 10628 10629 10630 10631 10632 10633 10634 10635 10636 10637 10638 10639 10640 10641 10642 10643 10644 10645 10646 10647 10648 10649 10650 10651 10652 10653 10654 10655 10656 10657 10658 10659 10660 10661 10662 10663 10664 10665 10666 10667 10668 10669 10670 10671 10672 10673 10674 10675 10676 10677 10678
static int
qemuDomainMigrateGetCompressionCache(virDomainPtr dom,
                                     unsigned long long *cacheSize,
                                     unsigned int flags)
{
    virQEMUDriverPtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto endjob;
    }

    priv = vm->privateData;

    qemuDomainObjEnterMonitor(driver, vm);

    ret = qemuMonitorGetMigrationCapability(
                priv->mon,
                QEMU_MONITOR_MIGRATION_CAPS_XBZRLE);
    if (ret == 0) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("Compressed migration is not supported by "
                         "QEMU binary"));
        ret = -1;
    } else if (ret > 0) {
        ret = qemuMonitorGetMigrationCacheSize(priv->mon, cacheSize);
    }

    qemuDomainObjExitMonitor(driver, vm);

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

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

static int
qemuDomainMigrateSetCompressionCache(virDomainPtr dom,
                                     unsigned long long cacheSize,
                                     unsigned int flags)
{
    virQEMUDriverPtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto endjob;
    }

    priv = vm->privateData;

    qemuDomainObjEnterMonitor(driver, vm);

    ret = qemuMonitorGetMigrationCapability(
                priv->mon,
                QEMU_MONITOR_MIGRATION_CAPS_XBZRLE);
    if (ret == 0) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("Compressed migration is not supported by "
                         "QEMU binary"));
        ret = -1;
    } else if (ret > 0) {
        VIR_DEBUG("Setting compression cache to %llu B", cacheSize);
        ret = qemuMonitorSetMigrationCacheSize(priv->mon, cacheSize);
    }

    qemuDomainObjExitMonitor(driver, vm);

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

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

10679 10680 10681 10682 10683
static int
qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
                             unsigned long bandwidth,
                             unsigned int flags)
{
10684
    virQEMUDriverPtr driver = dom->conn->privateData;
10685 10686 10687 10688 10689 10690
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(0, -1);

10691 10692
    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;
10693 10694

    priv = vm->privateData;
10695 10696 10697
    if (virDomainObjIsActive(vm)) {
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
            goto cleanup;
10698

10699
        if (!virDomainObjIsActive(vm)) {
10700 10701
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is not running"));
10702 10703 10704
            goto endjob;
        }

10705 10706 10707 10708
        VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
        qemuDomainObjEnterMonitor(driver, vm);
        ret = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
        qemuDomainObjExitMonitor(driver, vm);
10709

10710 10711
        if (ret == 0)
            priv->migMaxBandwidth = bandwidth;
10712

10713
endjob:
10714 10715 10716 10717 10718 10719
        if (qemuDomainObjEndJob(driver, vm) == 0)
            vm = NULL;
    } else {
        priv->migMaxBandwidth = bandwidth;
        ret = 0;
    }
10720 10721 10722

cleanup:
    if (vm)
10723
        virObjectUnlock(vm);
10724 10725 10726
    return ret;
}

10727 10728 10729 10730 10731 10732
static int
qemuDomainMigrateGetMaxSpeed(virDomainPtr dom,
                             unsigned long *bandwidth,
                             unsigned int flags)
{
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
10733
    qemuDomainObjPrivatePtr priv;
10734 10735 10736 10737
    int ret = -1;

    virCheckFlags(0, -1);

10738
    if (!(vm = qemuDomObjFromDomain(dom)))
10739 10740
        goto cleanup;

J
Jim Fehlig 已提交
10741 10742
    priv = vm->privateData;
    *bandwidth = priv->migMaxBandwidth;
10743 10744 10745 10746
    ret = 0;

cleanup:
    if (vm)
10747
        virObjectUnlock(vm);
10748 10749 10750
    return ret;
}

10751 10752 10753 10754 10755 10756 10757 10758 10759 10760 10761 10762
typedef enum {
    VIR_DISK_CHAIN_NO_ACCESS,
    VIR_DISK_CHAIN_READ_ONLY,
    VIR_DISK_CHAIN_READ_WRITE,
} qemuDomainDiskChainMode;

/* Several operations end up adding or removing a single element of a
 * disk backing file chain; this helper function ensures that the lock
 * manager, cgroup device controller, and security manager labelling
 * are all aware of each new file before it is added to a chain, and
 * can revoke access to a file no longer needed in a chain.  */
static int
10763
qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
10764 10765
                                  virDomainObjPtr vm,
                                  virDomainDiskDefPtr disk,
10766
                                  const char *file,
10767 10768 10769 10770 10771 10772 10773 10774 10775 10776
                                  qemuDomainDiskChainMode mode)
{
    /* The easiest way to label a single file with the same
     * permissions it would have as if part of the disk chain is to
     * temporarily modify the disk in place.  */
    char *origsrc = disk->src;
    int origformat = disk->format;
    virStorageFileMetadataPtr origchain = disk->backingChain;
    bool origreadonly = disk->readonly;
    int ret = -1;
10777
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
10778

10779
    disk->src = (char *) file; /* casting away const is safe here */
10780 10781 10782 10783 10784 10785 10786 10787
    disk->format = VIR_STORAGE_FILE_RAW;
    disk->backingChain = NULL;
    disk->readonly = mode == VIR_DISK_CHAIN_READ_ONLY;

    if (mode == VIR_DISK_CHAIN_NO_ACCESS) {
        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
                                                vm->def, disk) < 0)
            VIR_WARN("Unable to restore security label on %s", disk->src);
10788
        if (qemuTeardownDiskCgroup(vm, disk) < 0)
10789 10790 10791
            VIR_WARN("Failed to teardown cgroup for disk path %s", disk->src);
        if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
            VIR_WARN("Unable to release lock on %s", disk->src);
10792
    } else if (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
10793
                                       vm, disk) < 0 ||
10794
               qemuSetupDiskCgroup(vm, disk) < 0 ||
10795 10796 10797 10798 10799 10800 10801 10802 10803 10804 10805 10806
               virSecurityManagerSetImageLabel(driver->securityManager,
                                               vm->def, disk) < 0) {
        goto cleanup;
    }

    ret = 0;

cleanup:
    disk->src = origsrc;
    disk->format = origformat;
    disk->backingChain = origchain;
    disk->readonly = origreadonly;
10807
    virObjectUnref(cfg);
10808 10809 10810 10811
    return ret;
}


10812
static int
10813
qemuDomainSnapshotFSFreeze(virDomainObjPtr vm) {
10814 10815 10816 10817
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int freezed;

    if (priv->agentError) {
10818
        virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
10819 10820
                       _("QEMU guest agent is not "
                         "available due to an error"));
10821 10822 10823
        return -1;
    }
    if (!priv->agent) {
10824 10825
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("QEMU guest agent is not configured"));
10826 10827 10828
        return -1;
    }

10829
    qemuDomainObjEnterAgent(vm);
10830
    freezed = qemuAgentFSFreeze(priv->agent);
10831
    qemuDomainObjExitAgent(vm);
10832 10833 10834 10835 10836

    return freezed;
}

static int
10837
qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report)
E
Eric Blake 已提交
10838
{
10839 10840
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int thawed;
E
Eric Blake 已提交
10841
    virErrorPtr err = NULL;
10842 10843

    if (priv->agentError) {
E
Eric Blake 已提交
10844
        if (report)
10845
            virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
10846 10847
                           _("QEMU guest agent is not "
                             "available due to an error"));
10848 10849 10850
        return -1;
    }
    if (!priv->agent) {
E
Eric Blake 已提交
10851
        if (report)
10852 10853
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("QEMU guest agent is not configured"));
10854 10855 10856
        return -1;
    }

10857
    qemuDomainObjEnterAgent(vm);
E
Eric Blake 已提交
10858
    if (!report)
10859
        err = virSaveLastError();
10860
    thawed = qemuAgentFSThaw(priv->agent);
10861 10862
    if (!report)
        virSetError(err);
10863
    qemuDomainObjExitAgent(vm);
10864

10865
    virFreeError(err);
10866 10867 10868
    return thawed;
}

10869 10870
/* The domain is expected to be locked and inactive. */
static int
10871
qemuDomainSnapshotCreateInactiveInternal(virQEMUDriverPtr driver,
10872 10873
                                         virDomainObjPtr vm,
                                         virDomainSnapshotObjPtr snap)
10874
{
E
Eric Blake 已提交
10875
    return qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-c", false);
10876 10877
}

10878 10879
/* The domain is expected to be locked and inactive. */
static int
10880
qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
10881 10882 10883 10884 10885 10886 10887 10888 10889
                                         virDomainObjPtr vm,
                                         virDomainSnapshotObjPtr snap,
                                         bool reuse)
{
    int i;
    virDomainSnapshotDiskDefPtr snapdisk;
    virDomainDiskDefPtr defdisk;
    virCommandPtr cmd = NULL;
    const char *qemuImgPath;
10890 10891
    virBitmapPtr created = NULL;
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
10892 10893 10894
    int ret = -1;

    if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
10895
        goto cleanup;
10896 10897 10898

    if (!(created = virBitmapNew(snap->def->ndisks))) {
        virReportOOMError();
10899
        goto cleanup;
10900 10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918 10919 10920 10921 10922 10923 10924 10925 10926 10927 10928
    }

    /* If reuse is true, then qemuDomainSnapshotPrepare already
     * ensured that the new files exist, and it was up to the user to
     * create them correctly.  */
    for (i = 0; i < snap->def->ndisks && !reuse; i++) {
        snapdisk = &(snap->def->disks[i]);
        defdisk = snap->def->dom->disks[snapdisk->index];
        if (snapdisk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL)
            continue;

        if (!snapdisk->format)
            snapdisk->format = VIR_STORAGE_FILE_QCOW2;

        /* creates cmd line args: qemu-img create -f qcow2 -o */
        if (!(cmd = virCommandNewArgList(qemuImgPath,
                                         "create",
                                         "-f",
                                         virStorageFileFormatTypeToString(snapdisk->format),
                                         "-o",
                                         NULL)))
            goto cleanup;

        if (defdisk->format > 0) {
            /* adds cmd line arg: backing_file=/path/to/backing/file,backing_fmd=format */
            virCommandAddArgFormat(cmd, "backing_file=%s,backing_fmt=%s",
                                   defdisk->src,
                                   virStorageFileFormatTypeToString(defdisk->format));
        } else {
10929
            if (!cfg->allowDiskFormatProbing) {
10930 10931 10932 10933 10934 10935 10936 10937 10938 10939 10940 10941 10942 10943 10944 10945 10946 10947 10948 10949 10950 10951 10952 10953 10954 10955 10956 10957 10958 10959 10960 10961 10962 10963 10964 10965 10966 10967 10968 10969 10970 10971 10972 10973 10974 10975 10976
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unknown image format of '%s' and "
                                 "format probing is disabled"),
                               defdisk->src);
                goto cleanup;
            }

            /* adds cmd line arg: backing_file=/path/to/backing/file */
            virCommandAddArgFormat(cmd, "backing_file=%s", defdisk->src);
        }

        /* adds cmd line args: /path/to/target/file */
        virCommandAddArg(cmd, snapdisk->file);

        /* If the target does not exist, we're going to create it possibly */
        if (!virFileExists(snapdisk->file))
            ignore_value(virBitmapSetBit(created, i));

        if (virCommandRun(cmd, NULL) < 0)
            goto cleanup;

        virCommandFree(cmd);
        cmd = NULL;
    }

    /* update disk definitions */
    for (i = 0; i < snap->def->ndisks; i++) {
        snapdisk = &(snap->def->disks[i]);
        defdisk = vm->def->disks[snapdisk->index];

        if (snapdisk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            VIR_FREE(defdisk->src);
            if (!(defdisk->src = strdup(snapdisk->file))) {
                /* we cannot rollback here in a sane way */
                virReportOOMError();
                goto cleanup;
            }
            defdisk->format = snapdisk->format;
        }
    }

    ret = 0;

cleanup:
    virCommandFree(cmd);

    /* unlink images if creation has failed */
10977
    if (ret < 0 && created) {
10978 10979 10980 10981 10982 10983 10984 10985 10986
        ssize_t bit = -1;
        while ((bit = virBitmapNextSetBit(created, bit)) >= 0) {
            snapdisk = &(snap->def->disks[bit]);
            if (unlink(snapdisk->file) < 0)
                VIR_WARN("Failed to remove snapshot image '%s'",
                         snapdisk->file);
        }
    }
    virBitmapFree(created);
10987
    virObjectUnref(cfg);
10988 10989 10990 10991

    return ret;
}

10992

10993 10994
/* The domain is expected to be locked and active. */
static int
10995
qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
10996
                                       virQEMUDriverPtr driver,
10997 10998 10999
                                       virDomainObjPtr *vmptr,
                                       virDomainSnapshotObjPtr snap,
                                       unsigned int flags)
11000 11001 11002
{
    virDomainObjPtr vm = *vmptr;
    qemuDomainObjPrivatePtr priv = vm->privateData;
11003
    virDomainEventPtr event = NULL;
11004 11005
    bool resume = false;
    int ret = -1;
11006

11007
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
11008 11009
        return -1;

11010
    if (!virDomainObjIsActive(vm)) {
11011 11012
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
11013 11014 11015
        goto endjob;
    }

J
Jiri Denemark 已提交
11016
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
11017 11018 11019 11020
        /* savevm monitor command pauses the domain emitting an event which
         * confuses libvirt since it's not notified when qemu resumes the
         * domain. Thus we stop and start CPUs ourselves.
         */
11021 11022
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
                                QEMU_ASYNC_JOB_NONE) < 0)
11023 11024 11025 11026
            goto cleanup;

        resume = true;
        if (!virDomainObjIsActive(vm)) {
11027 11028
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
11029 11030 11031 11032
            goto cleanup;
        }
    }

11033
    qemuDomainObjEnterMonitor(driver, vm);
11034
    ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
11035
    qemuDomainObjExitMonitor(driver, vm);
11036 11037 11038 11039 11040 11041
    if (ret < 0)
        goto cleanup;

    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
11042
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
11043 11044 11045 11046 11047 11048 11049
        virDomainAuditStop(vm, "from-snapshot");
        /* We already filtered the _HALT flag for persistent domains
         * only, so this end job never drops the last reference.  */
        ignore_value(qemuDomainObjEndJob(driver, vm));
        resume = false;
        vm = NULL;
    }
11050

11051 11052
cleanup:
    if (resume && virDomainObjIsActive(vm) &&
J
Jiri Denemark 已提交
11053
        qemuProcessStartCPUs(driver, vm, conn,
11054
                             VIR_DOMAIN_RUNNING_UNPAUSED,
11055 11056 11057 11058 11059 11060 11061 11062
                             QEMU_ASYNC_JOB_NONE) < 0) {
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
        if (virGetLastError() == NULL) {
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("resuming after snapshot failed"));
        }
11063 11064
    }

11065
endjob:
11066
    if (vm && qemuDomainObjEndJob(driver, vm) == 0) {
11067 11068
        /* Only possible if a transient vm quit while our locks were down,
         * in which case we don't want to save snapshot metadata.  */
11069
        *vmptr = NULL;
11070 11071
        ret = -1;
    }
11072

11073 11074 11075
    if (event)
        qemuDomainEventQueue(driver, event);

11076 11077 11078
    return ret;
}

11079
static int
E
Eric Blake 已提交
11080 11081
qemuDomainSnapshotPrepare(virDomainObjPtr vm, virDomainSnapshotDefPtr def,
                          unsigned int *flags)
11082 11083 11084 11085 11086
{
    int ret = -1;
    int i;
    bool active = virDomainObjIsActive(vm);
    struct stat st;
11087
    bool reuse = (*flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
11088
    bool atomic = (*flags & VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC) != 0;
11089
    bool found_internal = false;
11090 11091
    int external = 0;
    qemuDomainObjPrivatePtr priv = vm->privateData;
11092

E
Eric Blake 已提交
11093
    if (def->state == VIR_DOMAIN_DISK_SNAPSHOT &&
11094
        reuse && !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
11095 11096
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("reuse is not supported with this QEMU binary"));
11097 11098 11099
        goto cleanup;
    }

11100 11101
    for (i = 0; i < def->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk = &def->disks[i];
E
Eric Blake 已提交
11102
        virDomainDiskDefPtr dom_disk = vm->def->disks[i];
11103 11104

        switch (disk->snapshot) {
E
Eric Blake 已提交
11105
        case VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL:
E
Eric Blake 已提交
11106 11107 11108 11109 11110
            if (def->state != VIR_DOMAIN_DISK_SNAPSHOT &&
                dom_disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
                (dom_disk->protocol == VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG ||
                 dom_disk->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD)) {
                break;
11111
            }
11112 11113
            if (vm->def->disks[i]->format > 0 &&
                vm->def->disks[i]->format != VIR_STORAGE_FILE_QCOW2) {
11114 11115 11116 11117
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("internal snapshot for disk %s unsupported "
                                 "for storage type %s"),
                               disk->name,
11118 11119
                               virStorageFileFormatTypeToString(
                                   vm->def->disks[i]->format));
11120 11121
                goto cleanup;
            }
E
Eric Blake 已提交
11122 11123 11124 11125 11126 11127 11128
            if (def->state == VIR_DOMAIN_DISK_SNAPSHOT && active) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("active qemu domains require external disk "
                                 "snapshots; disk %s requested internal"),
                               disk->name);
                goto cleanup;
            }
11129
            found_internal = true;
11130 11131
            break;

E
Eric Blake 已提交
11132
        case VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL:
11133 11134 11135 11136
            if (!disk->format) {
                disk->format = VIR_STORAGE_FILE_QCOW2;
            } else if (disk->format != VIR_STORAGE_FILE_QCOW2 &&
                       disk->format != VIR_STORAGE_FILE_QED) {
11137 11138 11139
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("external snapshot format for disk %s "
                                 "is unsupported: %s"),
11140 11141
                               disk->name,
                               virStorageFileFormatTypeToString(disk->format));
11142 11143 11144 11145 11146 11147 11148 11149
                goto cleanup;
            }
            if (stat(disk->file, &st) < 0) {
                if (errno != ENOENT) {
                    virReportSystemError(errno,
                                         _("unable to stat for disk %s: %s"),
                                         disk->name, disk->file);
                    goto cleanup;
11150 11151 11152 11153 11154
                } else if (reuse) {
                    virReportSystemError(errno,
                                         _("missing existing file for disk %s: %s"),
                                         disk->name, disk->file);
                    goto cleanup;
11155
                }
11156
            } else if (!S_ISBLK(st.st_mode) && st.st_size && !reuse) {
11157 11158 11159 11160
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("external snapshot file for disk %s already "
                                 "exists and is not a block device: %s"),
                               disk->name, disk->file);
11161 11162
                goto cleanup;
            }
11163
            external++;
11164 11165
            break;

E
Eric Blake 已提交
11166
        case VIR_DOMAIN_SNAPSHOT_LOCATION_NONE:
11167 11168
            break;

E
Eric Blake 已提交
11169
        case VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT:
11170
        default:
11171 11172
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unexpected code path"));
11173 11174 11175 11176
            goto cleanup;
        }
    }

11177 11178 11179
    /* internal snapshot requires a disk image to store the memory image to */
    if (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL &&
        !found_internal) {
11180
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
11181
                       _("internal checkpoints require at least "
11182
                         "one disk to be selected for snapshot"));
11183 11184
        goto cleanup;
    }
11185

11186 11187 11188 11189 11190 11191 11192 11193 11194 11195 11196 11197 11198 11199 11200 11201 11202 11203 11204 11205 11206 11207
    /* disk snapshot requires at least one disk */
    if (def->state == VIR_DOMAIN_DISK_SNAPSHOT && !external) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("disk-only snapshots require at least "
                         "one disk to be selected for snapshot"));
        goto cleanup;
    }

    /* For now, we don't allow mixing internal and external disks.
     * XXX technically, we could mix internal and external disks for
     * offline snapshots */
    if (found_internal && external) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("mixing internal and external snapshots is not "
                         "supported yet"));
        goto cleanup;
    }

    /* Alter flags to let later users know what we learned.  */
    if (external && !active)
        *flags |= VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY;

E
Eric Blake 已提交
11208
    if (def->state != VIR_DOMAIN_DISK_SNAPSHOT && active) {
11209
        if (external == 1 ||
11210
            virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
11211 11212
            *flags |= VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC;
        } else if (atomic && external > 1) {
11213 11214 11215
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("atomic live snapshot of multiple disks "
                             "is unsupported"));
11216 11217 11218
            goto cleanup;
        }
    }
11219 11220 11221 11222 11223 11224 11225 11226 11227

    ret = 0;

cleanup:
    return ret;
}

/* The domain is expected to hold monitor lock.  */
static int
11228
qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
11229
                                         virDomainObjPtr vm,
11230
                                         virDomainSnapshotDiskDefPtr snap,
11231
                                         virDomainDiskDefPtr disk,
11232
                                         virDomainDiskDefPtr persistDisk,
11233 11234
                                         virJSONValuePtr actions,
                                         bool reuse)
11235 11236 11237 11238
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    char *device = NULL;
    char *source = NULL;
11239 11240
    int format = snap->format;
    const char *formatStr = NULL;
11241
    char *persistSource = NULL;
11242
    int ret = -1;
11243 11244
    int fd = -1;
    bool need_unlink = false;
11245

E
Eric Blake 已提交
11246
    if (snap->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
11247 11248
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected code path"));
11249 11250 11251 11252 11253
        return -1;
    }

    if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
        !(source = strdup(snap->file)) ||
11254
        (persistDisk &&
11255
         !(persistSource = strdup(source)))) {
11256 11257 11258 11259
        virReportOOMError();
        goto cleanup;
    }

11260 11261
    /* create the stub file and set selinux labels; manipulate disk in
     * place, in a way that can be reverted on failure. */
11262 11263 11264 11265 11266 11267 11268
    if (!reuse) {
        fd = qemuOpenFile(driver, source, O_WRONLY | O_TRUNC | O_CREAT,
                          &need_unlink, NULL);
        if (fd < 0)
            goto cleanup;
        VIR_FORCE_CLOSE(fd);
    }
11269

11270 11271 11272 11273 11274 11275 11276 11277
    /* XXX Here, we know we are about to alter disk->backingChain if
     * successful, so we nuke the existing chain so that future
     * commands will recompute it.  Better would be storing the chain
     * ourselves rather than reprobing, but this requires modifying
     * domain_conf and our XML to fully track the chain across
     * libvirtd restarts.  */
    virStorageFileFreeMetadata(disk->backingChain);
    disk->backingChain = NULL;
11278

11279
    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
11280
                                          VIR_DISK_CHAIN_READ_WRITE) < 0) {
11281
        qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
11282
                                          VIR_DISK_CHAIN_NO_ACCESS);
11283 11284 11285 11286
        goto cleanup;
    }

    /* create the actual snapshot */
11287 11288
    if (snap->format)
        formatStr = virStorageFileFormatTypeToString(snap->format);
11289
    ret = qemuMonitorDiskSnapshot(priv->mon, actions, device, source,
11290
                                  formatStr, reuse);
11291 11292 11293 11294 11295
    virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0);
    if (ret < 0)
        goto cleanup;

    /* Update vm in place to match changes.  */
11296
    need_unlink = false;
11297 11298 11299
    VIR_FREE(disk->src);
    disk->src = source;
    source = NULL;
11300
    disk->format = format;
11301 11302 11303 11304
    if (persistDisk) {
        VIR_FREE(persistDisk->src);
        persistDisk->src = persistSource;
        persistSource = NULL;
11305
        persistDisk->format = format;
11306
    }
11307 11308

cleanup:
11309 11310
    if (need_unlink && unlink(source))
        VIR_WARN("unable to unlink just-created %s", source);
11311 11312
    VIR_FREE(device);
    VIR_FREE(source);
11313
    VIR_FREE(persistSource);
11314 11315 11316
    return ret;
}

11317 11318 11319 11320
/* The domain is expected to hold monitor lock.  This is the
 * counterpart to qemuDomainSnapshotCreateSingleDiskActive, called
 * only on a failed transaction. */
static void
11321
qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
11322 11323 11324 11325 11326 11327 11328 11329 11330 11331 11332 11333
                                       virDomainObjPtr vm,
                                       virDomainDiskDefPtr origdisk,
                                       virDomainDiskDefPtr disk,
                                       virDomainDiskDefPtr persistDisk,
                                       bool need_unlink)
{
    char *source = NULL;
    char *persistSource = NULL;
    struct stat st;

    if (!(source = strdup(origdisk->src)) ||
        (persistDisk &&
11334
         !(persistSource = strdup(source)))) {
11335 11336 11337 11338
        virReportOOMError();
        goto cleanup;
    }

11339
    qemuDomainPrepareDiskChainElement(driver, vm, disk, origdisk->src,
11340
                                      VIR_DISK_CHAIN_NO_ACCESS);
11341
    if (need_unlink && stat(disk->src, &st) == 0 &&
11342
        S_ISREG(st.st_mode) && unlink(disk->src) < 0)
11343 11344 11345 11346 11347 11348
        VIR_WARN("Unable to remove just-created %s", disk->src);

    /* Update vm in place to match changes.  */
    VIR_FREE(disk->src);
    disk->src = source;
    source = NULL;
11349
    disk->format = origdisk->format;
11350 11351 11352 11353
    if (persistDisk) {
        VIR_FREE(persistDisk->src);
        persistDisk->src = persistSource;
        persistSource = NULL;
11354
        persistDisk->format = origdisk->format;
11355 11356 11357 11358 11359 11360 11361
    }

cleanup:
    VIR_FREE(source);
    VIR_FREE(persistSource);
}

11362 11363
/* The domain is expected to be locked and active. */
static int
11364
qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
11365
                                   virDomainObjPtr vm,
11366
                                   virDomainSnapshotObjPtr snap,
11367 11368
                                   unsigned int flags,
                                   enum qemuDomainAsyncJob asyncJob)
11369
{
11370 11371
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virJSONValuePtr actions = NULL;
11372 11373
    int ret = -1;
    int i;
11374
    bool persist = false;
11375
    bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
11376
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
11377

11378
    if (!virDomainObjIsActive(vm)) {
11379 11380
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
11381
        goto cleanup;
11382 11383
    }

11384
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
11385
        if (!(actions = virJSONValueNewArray())) {
11386 11387 11388
            virReportOOMError();
            goto cleanup;
        }
11389
    } else if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DISK_SNAPSHOT)) {
11390 11391 11392 11393
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("live disk snapshot not supported with this "
                         "QEMU binary"));
        goto cleanup;
11394
    }
11395 11396

    /* No way to roll back if first disk succeeds but later disks
11397
     * fail, unless we have transaction support.
E
Eric Blake 已提交
11398
     * Based on earlier qemuDomainSnapshotPrepare, all
11399 11400
     * disks in this list are now either SNAPSHOT_NO, or
     * SNAPSHOT_EXTERNAL with a valid file name and qcow2 format.  */
11401 11402 11403
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
        goto cleanup;

11404
    for (i = 0; i < snap->def->ndisks; i++) {
11405 11406
        virDomainDiskDefPtr persistDisk = NULL;

E
Eric Blake 已提交
11407
        if (snap->def->disks[i].snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
11408
            continue;
11409 11410 11411 11412 11413 11414 11415 11416 11417
        if (vm->newDef) {
            int indx = virDomainDiskIndexByName(vm->newDef,
                                                vm->def->disks[i]->dst,
                                                false);
            if (indx >= 0) {
                persistDisk = vm->newDef->disks[indx];
                persist = true;
            }
        }
11418

11419
        ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
11420
                                                       &snap->def->disks[i],
11421
                                                       vm->def->disks[i],
11422 11423
                                                       persistDisk, actions,
                                                       reuse);
11424 11425 11426
        if (ret < 0)
            break;
    }
11427 11428 11429
    if (actions) {
        if (ret == 0)
            ret = qemuMonitorTransaction(priv->mon, actions);
E
Eric Blake 已提交
11430
        virJSONValueFree(actions);
11431 11432 11433 11434 11435 11436
        if (ret < 0) {
            /* Transaction failed; undo the changes to vm.  */
            bool need_unlink = !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);
            while (--i >= 0) {
                virDomainDiskDefPtr persistDisk = NULL;

E
Eric Blake 已提交
11437 11438
                if (snap->def->disks[i].snapshot ==
                    VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
11439 11440 11441 11442 11443 11444 11445 11446 11447
                    continue;
                if (vm->newDef) {
                    int indx = virDomainDiskIndexByName(vm->newDef,
                                                        vm->def->disks[i]->dst,
                                                        false);
                    if (indx >= 0)
                        persistDisk = vm->newDef->disks[indx];
                }

11448
                qemuDomainSnapshotUndoSingleDiskActive(driver, vm,
11449 11450 11451 11452 11453 11454 11455
                                                       snap->def->dom->disks[i],
                                                       vm->def->disks[i],
                                                       persistDisk,
                                                       need_unlink);
            }
        }
    }
11456
    qemuDomainObjExitMonitor(driver, vm);
11457 11458 11459

cleanup:

11460
    if (ret == 0 || !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
11461
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0 ||
11462
            (persist && virDomainSaveConfig(cfg->configDir, vm->newDef) < 0))
11463 11464
            ret = -1;
    }
11465
    virObjectUnref(cfg);
11466 11467 11468 11469 11470 11471 11472

    return ret;
}


static int
qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
11473
                                       virQEMUDriverPtr driver,
11474 11475 11476 11477 11478 11479 11480 11481 11482 11483
                                       virDomainObjPtr *vmptr,
                                       virDomainSnapshotObjPtr snap,
                                       unsigned int flags)
{
    bool resume = false;
    int ret = -1;
    virDomainObjPtr vm = *vmptr;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    char *xml = NULL;
    bool memory = snap->def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
11484
    bool memory_unlink = false;
11485
    bool atomic = !!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC);
11486
    bool transaction = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION);
11487
    int thaw = 0; /* 1 if freeze succeeded, -1 if freeze failed */
11488
    bool pmsuspended = false;
11489

11490
    if (qemuDomainObjBeginAsyncJob(driver, vm,
11491
                                             QEMU_ASYNC_JOB_SNAPSHOT) < 0)
11492 11493
        goto cleanup;

11494 11495 11496 11497 11498
    /* If quiesce was requested, then issue a freeze command, and a
     * counterpart thaw command, no matter what.  The command will
     * fail if the guest is paused or the guest agent is not
     * running.  */
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
11499
        if (qemuDomainSnapshotFSFreeze(vm) < 0) {
11500 11501 11502 11503 11504 11505 11506 11507
            /* helper reported the error */
            thaw = -1;
            goto endjob;
        } else {
            thaw = 1;
        }
    }

11508 11509 11510 11511 11512
    /* We need to track what state the guest is in, since taking the
     * snapshot may alter that state and we must restore it later.  */
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PMSUSPENDED) {
        pmsuspended = true;
    } else if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
11513 11514 11515 11516 11517 11518 11519 11520 11521 11522 11523 11524 11525 11526 11527 11528 11529 11530 11531 11532 11533 11534 11535 11536 11537 11538 11539 11540 11541
        resume = true;

        /* For external checkpoints (those with memory), the guest
         * must pause (either by libvirt up front, or by qemu after
         * _LIVE converges).  For disk-only snapshots with multiple
         * disks, libvirt must pause externally to get all snapshots
         * to be at the same point in time, unless qemu supports
         * transactions.  For a single disk, snapshot is atomic
         * without requiring a pause.  Thanks to
         * qemuDomainSnapshotPrepare, if we got to this point, the
         * atomic flag now says whether we need to pause, and a
         * capability bit says whether to use transaction.
         */
        if ((memory && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE)) ||
            (!memory && atomic && !transaction)) {
            if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SNAPSHOT,
                                    QEMU_ASYNC_JOB_SNAPSHOT) < 0)
                goto endjob;

            if (!virDomainObjIsActive(vm)) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("guest unexpectedly quit"));
                goto endjob;
            }
        }
    }

    /* do the memory snapshot if necessary */
    if (memory) {
11542 11543 11544 11545
        /* check if migration is possible */
        if (!qemuMigrationIsAllowed(driver, vm, vm->def, false))
            goto endjob;

11546 11547 11548 11549 11550 11551 11552 11553 11554
        /* allow the migration job to be cancelled or the domain to be paused */
        qemuDomainObjSetAsyncJobMask(vm, DEFAULT_JOB_MASK |
                                     JOB_MASK(QEMU_JOB_SUSPEND) |
                                     JOB_MASK(QEMU_JOB_MIGRATION_OP));

        if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, false)))
            goto endjob;

        if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file,
11555
                                        xml, QEMU_SAVE_FORMAT_RAW,
11556 11557 11558 11559
                                        resume, 0,
                                        QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
            goto endjob;

11560 11561 11562
        /* the memory image was created, remove it on errors */
        memory_unlink = true;

11563 11564 11565 11566 11567 11568 11569 11570 11571 11572 11573 11574 11575 11576 11577 11578
        /* forbid any further manipulation */
        qemuDomainObjSetAsyncJobMask(vm, DEFAULT_JOB_MASK);
    }

    /* now the domain is now paused if:
     * - if a memory snapshot was requested
     * - an atomic snapshot was requested AND
     *   qemu does not support transactions
     *
     * Next we snapshot the disks.
     */
    if ((ret = qemuDomainSnapshotCreateDiskActive(driver, vm, snap, flags,
                                                  QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
        goto endjob;

    /* the snapshot is complete now */
11579 11580 11581 11582 11583
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
        virDomainEventPtr event;

        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
11584
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
11585 11586 11587
        virDomainAuditStop(vm, "from-snapshot");
        /* We already filtered the _HALT flag for persistent domains
         * only, so this end job never drops the last reference.  */
11588
        ignore_value(qemuDomainObjEndAsyncJob(driver, vm));
11589
        resume = false;
E
Eric Blake 已提交
11590
        thaw = 0;
11591 11592 11593
        vm = NULL;
        if (event)
            qemuDomainEventQueue(driver, event);
11594 11595 11596 11597 11598 11599 11600 11601 11602 11603 11604 11605
    } else if (memory && pmsuspended) {
        /* qemu 1.3 is unable to save a domain in pm-suspended (S3)
         * state; so we must emit an event stating that it was
         * converted to paused.  */
        virDomainEventPtr event;

        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
                             VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
        if (event)
            qemuDomainEventQueue(driver, event);
11606 11607
    }

11608
    ret = 0;
11609 11610

endjob:
11611 11612 11613
    if (resume && vm && virDomainObjIsActive(vm) &&
        qemuProcessStartCPUs(driver, vm, conn,
                             VIR_DOMAIN_RUNNING_UNPAUSED,
11614
                             QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
11615 11616 11617 11618 11619 11620 11621 11622 11623 11624
        virDomainEventPtr event = NULL;
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
        if (event)
            qemuDomainEventQueue(driver, event);
        if (virGetLastError() == NULL) {
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("resuming after snapshot failed"));
        }
11625

11626 11627
        ret = -1;
        goto cleanup;
11628
    }
E
Eric Blake 已提交
11629
    if (vm && thaw != 0 &&
11630
        qemuDomainSnapshotFSThaw(vm, thaw > 0) < 0) {
E
Eric Blake 已提交
11631 11632 11633 11634
        /* helper reported the error, if it was needed */
        if (thaw > 0)
            ret = -1;
    }
11635
    if (vm && !qemuDomainObjEndAsyncJob(driver, vm)) {
11636
        /* Only possible if a transient vm quit while our locks were down,
11637 11638
         * in which case we don't want to save snapshot metadata.
         */
11639 11640
        *vmptr = NULL;
        ret = -1;
11641 11642
    }

11643 11644
cleanup:
    VIR_FREE(xml);
11645 11646
    if (memory_unlink && ret < 0)
        unlink(snap->def->file);
11647

11648 11649 11650
    return ret;
}

11651

11652 11653 11654 11655
static virDomainSnapshotPtr
qemuDomainSnapshotCreateXML(virDomainPtr domain,
                            const char *xmlDesc,
                            unsigned int flags)
C
Chris Lalancette 已提交
11656
{
11657
    virQEMUDriverPtr driver = domain->conn->privateData;
C
Chris Lalancette 已提交
11658
    virDomainObjPtr vm = NULL;
11659
    char *xml = NULL;
C
Chris Lalancette 已提交
11660 11661 11662
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];
11663
    virDomainSnapshotDefPtr def = NULL;
11664
    bool update_current = true;
11665
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
11666
    virDomainSnapshotObjPtr other = NULL;
11667 11668
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
    int align_match = true;
11669
    virQEMUDriverConfigPtr cfg = NULL;
11670
    virCapsPtr caps = NULL;
C
Chris Lalancette 已提交
11671

11672 11673
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
                  VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
11674
                  VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
11675
                  VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
11676
                  VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY |
11677
                  VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT |
11678
                  VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
11679 11680
                  VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
                  VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);
11681 11682 11683

    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
        !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY)) {
11684 11685
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("quiesce requires disk-only"));
11686 11687
        return NULL;
    }
11688 11689 11690 11691 11692 11693 11694

    if (((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
         !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
        (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA))
        update_current = false;
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
11695

C
Chris Lalancette 已提交
11696
    virUUIDFormat(domain->uuid, uuidstr);
11697 11698

    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
11699 11700
        goto cleanup;

11701 11702
    cfg = virQEMUDriverGetConfig(driver);

11703 11704 11705
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

11706
    if (qemuProcessAutoDestroyActive(driver, vm)) {
11707 11708
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is marked for auto destroy"));
11709 11710
        goto cleanup;
    }
E
Eric Blake 已提交
11711 11712 11713 11714 11715 11716
    if (virDomainHasDiskMirror(vm)) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, "%s",
                       _("domain has active block copy job"));
        goto cleanup;
    }

11717
    if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
11718 11719
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot halt after transient domain snapshot"));
11720 11721
        goto cleanup;
    }
11722 11723 11724
    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) ||
        !virDomainObjIsActive(vm))
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE;
11725

11726
    if (!(def = virDomainSnapshotDefParseString(xmlDesc, caps, driver->xmlopt,
11727 11728
                                                QEMU_EXPECTED_VIRT_TYPES,
                                                parse_flags)))
C
Chris Lalancette 已提交
11729 11730
        goto cleanup;

11731 11732 11733 11734 11735 11736 11737 11738 11739 11740 11741 11742 11743 11744 11745 11746 11747 11748
    /* reject snapshot names containing slashes or starting with dot as
     * snapshot definitions are saved in files named by the snapshot name */
    if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
        if (strchr(def->name, '/')) {
            virReportError(VIR_ERR_XML_DETAIL,
                           _("invalid snapshot name '%s': "
                             "name can't contain '/'"),
                           def->name);
            goto cleanup;
        }

        if (def->name[0] == '.') {
            virReportError(VIR_ERR_XML_DETAIL,
                           _("invalid snapshot name '%s': "
                             "name can't start with '.'"),
                           def->name);
            goto cleanup;
        }
11749 11750
    }

11751 11752 11753 11754 11755 11756 11757 11758 11759 11760 11761 11762 11763 11764 11765 11766 11767 11768 11769
    /* reject the VIR_DOMAIN_SNAPSHOT_CREATE_LIVE flag where not supported */
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE &&
        (!virDomainObjIsActive(vm) ||
         def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL ||
         flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("live snapshot creation is supported only "
                         "with external checkpoints"));
        goto cleanup;
    }
    if ((def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL ||
         def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL) &&
        flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("disk-only snapshot creation is not compatible with "
                         "memory snapshot"));
        goto cleanup;
    }

11770 11771 11772 11773
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
        /* Prevent circular chains */
        if (def->parent) {
            if (STREQ(def->name, def->parent)) {
11774 11775 11776
                virReportError(VIR_ERR_INVALID_ARG,
                               _("cannot set snapshot %s as its own parent"),
                               def->name);
11777 11778
                goto cleanup;
            }
11779
            other = virDomainSnapshotFindByName(vm->snapshots, def->parent);
11780
            if (!other) {
11781 11782 11783
                virReportError(VIR_ERR_INVALID_ARG,
                               _("parent %s for snapshot %s not found"),
                               def->parent, def->name);
11784 11785 11786 11787
                goto cleanup;
            }
            while (other->def->parent) {
                if (STREQ(other->def->parent, def->name)) {
11788 11789 11790
                    virReportError(VIR_ERR_INVALID_ARG,
                                   _("parent %s would create cycle to %s"),
                                   other->def->name, def->name);
11791 11792
                    goto cleanup;
                }
11793
                other = virDomainSnapshotFindByName(vm->snapshots,
11794 11795 11796 11797 11798 11799 11800 11801 11802 11803
                                                    other->def->parent);
                if (!other) {
                    VIR_WARN("snapshots are inconsistent for %s",
                             vm->def->name);
                    break;
                }
            }
        }

        /* Check that any replacement is compatible */
11804 11805 11806 11807 11808 11809 11810 11811 11812
        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) &&
            def->state != VIR_DOMAIN_DISK_SNAPSHOT) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("disk-only flag for snapshot %s requires "
                             "disk-snapshot state"),
                           def->name);
            goto cleanup;

        }
11813

11814 11815
        if (def->dom &&
            memcmp(def->dom->uuid, domain->uuid, VIR_UUID_BUFLEN)) {
11816 11817 11818
            virReportError(VIR_ERR_INVALID_ARG,
                           _("definition for snapshot %s must use uuid %s"),
                           def->name, uuidstr);
11819 11820
            goto cleanup;
        }
11821

11822
        other = virDomainSnapshotFindByName(vm->snapshots, def->name);
11823 11824 11825 11826 11827
        if (other) {
            if ((other->def->state == VIR_DOMAIN_RUNNING ||
                 other->def->state == VIR_DOMAIN_PAUSED) !=
                (def->state == VIR_DOMAIN_RUNNING ||
                 def->state == VIR_DOMAIN_PAUSED)) {
11828 11829 11830 11831
                virReportError(VIR_ERR_INVALID_ARG,
                               _("cannot change between online and offline "
                                 "snapshot state in snapshot %s"),
                               def->name);
11832 11833
                goto cleanup;
            }
11834

11835 11836
            if ((other->def->state == VIR_DOMAIN_DISK_SNAPSHOT) !=
                (def->state == VIR_DOMAIN_DISK_SNAPSHOT)) {
11837 11838 11839 11840
                virReportError(VIR_ERR_INVALID_ARG,
                               _("cannot change between disk snapshot and "
                                 "system checkpoint in snapshot %s"),
                               def->name);
11841 11842
                goto cleanup;
            }
11843

11844 11845 11846 11847 11848 11849 11850 11851 11852 11853 11854
            if (other->def->dom) {
                if (def->dom) {
                    if (!virDomainDefCheckABIStability(other->def->dom,
                                                       def->dom))
                        goto cleanup;
                } else {
                    /* Transfer the domain def */
                    def->dom = other->def->dom;
                    other->def->dom = NULL;
                }
            }
11855

11856 11857
            if (def->dom) {
                if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
11858
                    virDomainSnapshotDefIsExternal(def)) {
11859 11860 11861 11862 11863 11864 11865 11866 11867 11868 11869 11870 11871 11872 11873
                    align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
                    align_match = false;
                }

                if (virDomainSnapshotAlignDisks(def, align_location,
                                                align_match) < 0) {
                    /* revert stealing of the snapshot domain definition */
                    if (def->dom && !other->def->dom) {
                        other->def->dom = def->dom;
                        def->dom = NULL;
                    }
                    goto cleanup;
                }
            }

11874 11875 11876 11877
            if (other == vm->current_snapshot) {
                update_current = true;
                vm->current_snapshot = NULL;
            }
11878

11879 11880
            /* Drop and rebuild the parent relationship, but keep all
             * child relations by reusing snap.  */
11881
            virDomainSnapshotDropParent(other);
11882
            virDomainSnapshotDefFree(other->def);
11883 11884
            other->def = def;
            def = NULL;
11885
            snap = other;
11886 11887 11888 11889 11890 11891 11892 11893 11894 11895
        } else {
            if (def->dom) {
                if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
                    def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
                    align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
                    align_match = false;
                }
                if (virDomainSnapshotAlignDisks(def, align_location,
                                                align_match) < 0)
                    goto cleanup;
11896
            }
11897
        }
11898 11899 11900
    } else {
        /* Easiest way to clone inactive portion of vm->def is via
         * conversion in and back out of xml.  */
11901
        if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)) ||
11902
            !(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt,
11903 11904 11905 11906
                                                 QEMU_EXPECTED_VIRT_TYPES,
                                                 VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

11907
        if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
11908 11909
            align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
            align_match = false;
11910 11911 11912 11913
            if (virDomainObjIsActive(vm))
                def->state = VIR_DOMAIN_DISK_SNAPSHOT;
            else
                def->state = VIR_DOMAIN_SHUTOFF;
11914
            def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
11915 11916 11917 11918
        } else if (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            def->state = virDomainObjGetState(vm, NULL);
            align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
            align_match = false;
11919 11920
        } else {
            def->state = virDomainObjGetState(vm, NULL);
11921 11922 11923
            def->memory = (def->state == VIR_DOMAIN_SHUTOFF ?
                           VIR_DOMAIN_SNAPSHOT_LOCATION_NONE :
                           VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL);
11924
        }
E
Eric Blake 已提交
11925 11926 11927 11928
        if (virDomainSnapshotAlignDisks(def, align_location,
                                        align_match) < 0 ||
            qemuDomainSnapshotPrepare(vm, def, &flags) < 0)
            goto cleanup;
11929 11930
    }

11931 11932 11933 11934 11935 11936
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;

        def = NULL;
    }
C
Chris Lalancette 已提交
11937

11938 11939
    if (update_current)
        snap->def->current = true;
11940
    if (vm->current_snapshot) {
11941 11942 11943 11944 11945 11946
        if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
            snap->def->parent = strdup(vm->current_snapshot->def->name);
            if (snap->def->parent == NULL) {
                virReportOOMError();
                goto cleanup;
            }
11947
        }
11948
        if (update_current) {
11949 11950
            vm->current_snapshot->def->current = false;
            if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
11951
                                                cfg->snapshotDir) < 0)
11952 11953 11954
                goto cleanup;
            vm->current_snapshot = NULL;
        }
11955
    }
11956

C
Chris Lalancette 已提交
11957
    /* actually do the snapshot */
11958 11959
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
        /* XXX Should we validate that the redefined snapshot even
11960 11961
         * makes sense, such as checking that qemu-img recognizes the
         * snapshot name in at least one of the domain's disks?  */
11962 11963 11964 11965 11966 11967 11968 11969 11970 11971 11972 11973 11974
    } else if (virDomainObjIsActive(vm)) {
        if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY ||
            snap->def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            /* external checkpoint or disk snapshot */
            if (qemuDomainSnapshotCreateActiveExternal(domain->conn, driver,
                                                       &vm, snap, flags) < 0)
                goto cleanup;
        } else {
            /* internal checkpoint */
            if (qemuDomainSnapshotCreateActiveInternal(domain->conn, driver,
                                                       &vm, snap, flags) < 0)
                goto cleanup;
        }
E
Eric Blake 已提交
11975
    } else {
11976 11977 11978 11979 11980 11981 11982 11983 11984 11985 11986 11987 11988
        /* inactive; qemuDomainSnapshotPrepare guaranteed that we
         * aren't mixing internal and external, and altered flags to
         * contain DISK_ONLY if there is an external disk.  */
        if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
            bool reuse = !!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);

            if (qemuDomainSnapshotCreateInactiveExternal(driver, vm, snap,
                                                         reuse) < 0)
                goto cleanup;
        } else {
            if (qemuDomainSnapshotCreateInactiveInternal(driver, vm, snap) < 0)
                goto cleanup;
        }
C
Chris Lalancette 已提交
11989 11990
    }

11991
    /* If we fail after this point, there's not a whole lot we can
C
Chris Lalancette 已提交
11992 11993 11994 11995 11996 11997
     * do; we've successfully taken the snapshot, and we are now running
     * on it, so we have to go forward the best we can
     */
    snapshot = virGetDomainSnapshot(domain, snap->def->name);

cleanup:
11998
    if (vm) {
11999
        if (snapshot && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
12000
            if (qemuDomainSnapshotWriteMetadata(vm, snap,
12001
                                                cfg->snapshotDir) < 0) {
12002 12003 12004 12005 12006 12007 12008 12009
                /* if writing of metadata fails, error out rather than trying
                 * to silently carry on  without completing the snapshot */
                virDomainSnapshotFree(snapshot);
                snapshot = NULL;
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unable to save metadata for snapshot %s"),
                               snap->def->name);
                virDomainSnapshotObjListRemove(vm->snapshots, snap);
12010 12011 12012
            } else {
                if (update_current)
                    vm->current_snapshot = snap;
12013
                other = virDomainSnapshotFindByName(vm->snapshots,
12014 12015 12016 12017 12018
                                                    snap->def->parent);
                snap->parent = other;
                other->nchildren++;
                snap->sibling = other->first_child;
                other->first_child = snap;
12019
            }
12020
        } else if (snap) {
12021
            virDomainSnapshotObjListRemove(vm->snapshots, snap);
12022
        }
12023
        virObjectUnlock(vm);
12024 12025
    }
    virDomainSnapshotDefFree(def);
12026
    VIR_FREE(xml);
12027
    virObjectUnref(caps);
12028
    virObjectUnref(cfg);
C
Chris Lalancette 已提交
12029 12030 12031 12032 12033
    return snapshot;
}

static int qemuDomainSnapshotListNames(virDomainPtr domain, char **names,
                                       int nameslen,
12034
                                       unsigned int flags)
C
Chris Lalancette 已提交
12035 12036 12037 12038
{
    virDomainObjPtr vm = NULL;
    int n = -1;

12039
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
12040
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
12041

12042
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
12043 12044
        goto cleanup;

12045
    n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
12046
                                         flags);
C
Chris Lalancette 已提交
12047 12048 12049

cleanup:
    if (vm)
12050
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
12051 12052 12053 12054
    return n;
}

static int qemuDomainSnapshotNum(virDomainPtr domain,
12055
                                 unsigned int flags)
C
Chris Lalancette 已提交
12056 12057 12058 12059
{
    virDomainObjPtr vm = NULL;
    int n = -1;

12060
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
12061
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
12062

12063
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
12064 12065
        goto cleanup;

12066
    n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);
C
Chris Lalancette 已提交
12067 12068 12069

cleanup:
    if (vm)
12070
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
12071 12072 12073
    return n;
}

12074 12075 12076 12077 12078 12079 12080 12081 12082 12083
static int
qemuDomainListAllSnapshots(virDomainPtr domain, virDomainSnapshotPtr **snaps,
                           unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

12084
    if (!(vm = qemuDomObjFromDomain(domain)))
12085 12086
        goto cleanup;

12087
    n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);
12088 12089 12090

cleanup:
    if (vm)
12091
        virObjectUnlock(vm);
12092 12093 12094
    return n;
}

12095 12096 12097 12098 12099 12100 12101 12102 12103 12104 12105
static int
qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
                                    char **names,
                                    int nameslen,
                                    unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
12106
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
12107

12108
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
12109 12110
        goto cleanup;

12111
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
12112 12113
        goto cleanup;

12114
    n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
12115
                                         flags);
12116 12117 12118

cleanup:
    if (vm)
12119
        virObjectUnlock(vm);
12120 12121 12122 12123 12124 12125 12126 12127 12128 12129 12130 12131
    return n;
}

static int
qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
12132
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
12133

12134
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
12135 12136
        goto cleanup;

12137
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
12138 12139
        goto cleanup;

12140
    n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);
12141 12142 12143

cleanup:
    if (vm)
12144
        virObjectUnlock(vm);
12145 12146 12147
    return n;
}

12148 12149 12150 12151 12152 12153 12154 12155 12156 12157 12158 12159
static int
qemuDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
                                  virDomainSnapshotPtr **snaps,
                                  unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    int n = -1;

    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);

12160
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
12161 12162
        goto cleanup;

12163
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
12164 12165
        goto cleanup;

12166
    n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
12167 12168 12169 12170
                               flags);

cleanup:
    if (vm)
12171
        virObjectUnlock(vm);
12172 12173 12174
    return n;
}

C
Chris Lalancette 已提交
12175 12176
static virDomainSnapshotPtr qemuDomainSnapshotLookupByName(virDomainPtr domain,
                                                           const char *name,
12177
                                                           unsigned int flags)
C
Chris Lalancette 已提交
12178 12179 12180 12181 12182
{
    virDomainObjPtr vm;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;

12183 12184
    virCheckFlags(0, NULL);

12185
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
12186 12187
        goto cleanup;

12188
    if (!(snap = qemuSnapObjFromName(vm, name)))
C
Chris Lalancette 已提交
12189 12190 12191 12192 12193 12194
        goto cleanup;

    snapshot = virGetDomainSnapshot(domain, snap->def->name);

cleanup:
    if (vm)
12195
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
12196 12197 12198 12199
    return snapshot;
}

static int qemuDomainHasCurrentSnapshot(virDomainPtr domain,
12200
                                        unsigned int flags)
C
Chris Lalancette 已提交
12201 12202 12203 12204
{
    virDomainObjPtr vm;
    int ret = -1;

12205 12206
    virCheckFlags(0, -1);

12207
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
12208 12209 12210 12211 12212 12213
        goto cleanup;

    ret = (vm->current_snapshot != NULL);

cleanup:
    if (vm)
12214
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
12215 12216 12217
    return ret;
}

12218 12219 12220 12221 12222 12223 12224 12225 12226 12227
static virDomainSnapshotPtr
qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr parent = NULL;

    virCheckFlags(0, NULL);

12228
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
12229 12230
        goto cleanup;

12231
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
12232 12233 12234
        goto cleanup;

    if (!snap->def->parent) {
12235 12236 12237
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("snapshot '%s' does not have a parent"),
                       snap->def->name);
12238 12239 12240 12241 12242 12243 12244
        goto cleanup;
    }

    parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent);

cleanup:
    if (vm)
12245
        virObjectUnlock(vm);
12246 12247 12248
    return parent;
}

C
Chris Lalancette 已提交
12249
static virDomainSnapshotPtr qemuDomainSnapshotCurrent(virDomainPtr domain,
12250
                                                      unsigned int flags)
C
Chris Lalancette 已提交
12251 12252 12253 12254
{
    virDomainObjPtr vm;
    virDomainSnapshotPtr snapshot = NULL;

12255 12256
    virCheckFlags(0, NULL);

12257
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
12258 12259 12260
        goto cleanup;

    if (!vm->current_snapshot) {
12261 12262
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
                       _("the domain does not have a current snapshot"));
C
Chris Lalancette 已提交
12263 12264 12265 12266 12267 12268 12269
        goto cleanup;
    }

    snapshot = virGetDomainSnapshot(domain, vm->current_snapshot->def->name);

cleanup:
    if (vm)
12270
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
12271 12272 12273
    return snapshot;
}

12274 12275
static char *qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                                          unsigned int flags)
C
Chris Lalancette 已提交
12276 12277 12278 12279 12280 12281
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

12282
    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);
12283

12284
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
C
Chris Lalancette 已提交
12285 12286
        goto cleanup;

12287
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
C
Chris Lalancette 已提交
12288
        goto cleanup;
12289 12290

    virUUIDFormat(snapshot->domain->uuid, uuidstr);
C
Chris Lalancette 已提交
12291

12292
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, flags, 0);
C
Chris Lalancette 已提交
12293 12294 12295

cleanup:
    if (vm)
12296
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
12297 12298 12299
    return xml;
}

12300 12301 12302 12303 12304 12305 12306 12307 12308 12309
static int
qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;

    virCheckFlags(0, -1);

12310
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
12311 12312
        goto cleanup;

12313
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
12314 12315 12316 12317 12318 12319 12320
        goto cleanup;

    ret = (vm->current_snapshot &&
           STREQ(snapshot->name, vm->current_snapshot->def->name));

cleanup:
    if (vm)
12321
        virObjectUnlock(vm);
12322 12323 12324 12325 12326 12327 12328 12329 12330 12331 12332 12333 12334 12335
    return ret;
}


static int
qemuDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;

    virCheckFlags(0, -1);

12336
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
12337 12338
        goto cleanup;

12339
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
12340 12341 12342 12343 12344 12345 12346 12347 12348
        goto cleanup;

    /* XXX Someday, we should recognize internal snapshots in qcow2
     * images that are not tied to a libvirt snapshot; if we ever do
     * that, then we would have a reason to return 0 here.  */
    ret = 1;

cleanup:
    if (vm)
12349
        virObjectUnlock(vm);
12350 12351 12352
    return ret;
}

12353 12354
/* The domain is expected to be locked and inactive. */
static int
12355
qemuDomainSnapshotRevertInactive(virQEMUDriverPtr driver,
E
Eric Blake 已提交
12356
                                 virDomainObjPtr vm,
12357 12358 12359
                                 virDomainSnapshotObjPtr snap)
{
    /* Try all disks, but report failure if we skipped any.  */
E
Eric Blake 已提交
12360
    int ret = qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-a", true);
12361 12362 12363
    return ret > 0 ? -1 : ret;
}

C
Chris Lalancette 已提交
12364
static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
12365
                                      unsigned int flags)
C
Chris Lalancette 已提交
12366
{
12367
    virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
C
Chris Lalancette 已提交
12368 12369 12370 12371
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainEventPtr event = NULL;
12372
    virDomainEventPtr event2 = NULL;
12373
    int detail;
C
Chris Lalancette 已提交
12374 12375
    qemuDomainObjPrivatePtr priv;
    int rc;
12376
    virDomainDefPtr config = NULL;
12377
    virQEMUDriverConfigPtr cfg = NULL;
12378
    virCapsPtr caps = NULL;
C
Chris Lalancette 已提交
12379

12380
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
12381 12382
                  VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
                  VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, -1);
12383

12384 12385 12386 12387 12388 12389 12390 12391 12392 12393
    /* We have the following transitions, which create the following events:
     * 1. inactive -> inactive: none
     * 2. inactive -> running:  EVENT_STARTED
     * 3. inactive -> paused:   EVENT_STARTED, EVENT_PAUSED
     * 4. running  -> inactive: EVENT_STOPPED
     * 5. running  -> running:  none
     * 6. running  -> paused:   EVENT_PAUSED
     * 7. paused   -> inactive: EVENT_STOPPED
     * 8. paused   -> running:  EVENT_RESUMED
     * 9. paused   -> paused:   none
12394 12395
     * Also, several transitions occur even if we fail partway through,
     * and use of FORCE can cause multiple transitions.
12396 12397
     */

12398 12399
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
        return -1;
12400 12401 12402

    cfg = virQEMUDriverGetConfig(driver);

12403 12404 12405
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

E
Eric Blake 已提交
12406 12407 12408 12409 12410
    if (virDomainHasDiskMirror(vm)) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, "%s",
                       _("domain has active block copy job"));
        goto cleanup;
    }
C
Chris Lalancette 已提交
12411

12412
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
C
Chris Lalancette 已提交
12413 12414
        goto cleanup;

12415 12416 12417 12418 12419
    if (!vm->persistent &&
        snap->def->state != VIR_DOMAIN_RUNNING &&
        snap->def->state != VIR_DOMAIN_PAUSED &&
        (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                  VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) == 0) {
12420 12421 12422
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("transient domain needs to request run or pause "
                         "to revert to inactive snapshot"));
12423 12424
        goto cleanup;
    }
12425
    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) {
12426 12427 12428
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("revert to external disk snapshot not supported "
                         "yet"));
12429 12430
        goto cleanup;
    }
12431 12432
    if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
        if (!snap->def->dom) {
12433 12434 12435
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
                           _("snapshot '%s' lacks domain '%s' rollback info"),
                           snap->def->name, vm->def->name);
12436 12437 12438 12439 12440 12441 12442
            goto cleanup;
        }
        if (virDomainObjIsActive(vm) &&
            !(snap->def->state == VIR_DOMAIN_RUNNING
              || snap->def->state == VIR_DOMAIN_PAUSED) &&
            (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                      VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
12443 12444
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                           _("must respawn qemu to start inactive snapshot"));
12445 12446 12447 12448
            goto cleanup;
        }
    }

12449

12450 12451 12452
    if (vm->current_snapshot) {
        vm->current_snapshot->def->current = false;
        if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
12453
                                            cfg->snapshotDir) < 0)
12454 12455 12456 12457 12458 12459
            goto cleanup;
        vm->current_snapshot = NULL;
        /* XXX Should we restore vm->current_snapshot after this point
         * in the failure cases where we know there was no change?  */
    }

12460
    /* Prepare to copy the snapshot inactive xml as the config of this
12461
     * domain.
12462 12463 12464
     *
     * XXX Should domain snapshots track live xml rather
     * than inactive xml?  */
12465
    snap->def->current = true;
12466
    if (snap->def->dom) {
12467
        config = virDomainDefCopy(snap->def->dom, caps, driver->xmlopt, true);
12468 12469 12470
        if (!config)
            goto cleanup;
    }
C
Chris Lalancette 已提交
12471

12472
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
C
Chris Lalancette 已提交
12473 12474 12475 12476
        goto cleanup;

    if (snap->def->state == VIR_DOMAIN_RUNNING
        || snap->def->state == VIR_DOMAIN_PAUSED) {
12477 12478 12479 12480 12481 12482 12483 12484 12485
        /* Transitions 2, 3, 5, 6, 8, 9 */
        bool was_running = false;
        bool was_stopped = false;

        /* When using the loadvm monitor command, qemu does not know
         * whether to pause or run the reverted domain, and just stays
         * in the same state as before the monitor command, whether
         * that is paused or running.  We always pause before loadvm,
         * to have finer control.  */
C
Chris Lalancette 已提交
12486
        if (virDomainObjIsActive(vm)) {
12487
            /* Transitions 5, 6, 8, 9 */
12488 12489
            /* Check for ABI compatibility.  */
            if (config && !virDomainDefCheckABIStability(vm->def, config)) {
12490 12491 12492 12493 12494
                virErrorPtr err = virGetLastError();

                if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
                    /* Re-spawn error using correct category. */
                    if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
12495 12496
                        virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                                       err->str2);
12497 12498 12499
                    goto endjob;
                }
                virResetError(err);
12500 12501
                qemuProcessStop(driver, vm,
                                VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
12502 12503 12504 12505 12506 12507 12508 12509
                virDomainAuditStop(vm, "from-snapshot");
                detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
                event = virDomainEventNewFromObj(vm,
                                                 VIR_DOMAIN_EVENT_STOPPED,
                                                 detail);
                if (event)
                    qemuDomainEventQueue(driver, event);
                goto load;
12510 12511
            }

C
Chris Lalancette 已提交
12512
            priv = vm->privateData;
12513 12514 12515 12516 12517 12518 12519 12520 12521 12522 12523 12524 12525 12526 12527
            if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
                /* Transitions 5, 6 */
                was_running = true;
                if (qemuProcessStopCPUs(driver, vm,
                                        VIR_DOMAIN_PAUSED_FROM_SNAPSHOT,
                                        QEMU_ASYNC_JOB_NONE) < 0)
                    goto endjob;
                /* Create an event now in case the restore fails, so
                 * that user will be alerted that they are now paused.
                 * If restore later succeeds, we might replace this. */
                detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
                event = virDomainEventNewFromObj(vm,
                                                 VIR_DOMAIN_EVENT_SUSPENDED,
                                                 detail);
                if (!virDomainObjIsActive(vm)) {
12528 12529
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("guest unexpectedly quit"));
12530 12531 12532
                    goto endjob;
                }
            }
12533
            qemuDomainObjEnterMonitor(driver, vm);
C
Chris Lalancette 已提交
12534
            rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name);
12535
            qemuDomainObjExitMonitor(driver, vm);
12536 12537 12538
            if (rc < 0) {
                /* XXX resume domain if it was running before the
                 * failed loadvm attempt? */
12539
                goto endjob;
12540
            }
12541
            if (config)
12542
                virDomainObjAssignDef(vm, config, false, NULL);
E
Eric Blake 已提交
12543
        } else {
12544
            /* Transitions 2, 3 */
12545
        load:
12546
            was_stopped = true;
12547
            if (config)
12548
                virDomainObjAssignDef(vm, config, false, NULL);
12549

12550 12551 12552 12553
            rc = qemuProcessStart(snapshot->domain->conn,
                                  driver, vm, NULL, -1, NULL, snap,
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                                  VIR_QEMU_PROCESS_START_PAUSED);
12554
            virDomainAuditStart(vm, "from-snapshot", rc >= 0);
12555 12556 12557 12558
            detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STARTED,
                                             detail);
C
Chris Lalancette 已提交
12559
            if (rc < 0)
12560
                goto endjob;
C
Chris Lalancette 已提交
12561 12562
        }

12563
        /* Touch up domain state.  */
12564 12565 12566
        if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
            (snap->def->state == VIR_DOMAIN_PAUSED ||
             (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
12567 12568 12569 12570 12571 12572 12573 12574 12575 12576 12577 12578 12579
            /* Transitions 3, 6, 9 */
            virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
                                 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
            if (was_stopped) {
                /* Transition 3, use event as-is and add event2 */
                detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
                event2 = virDomainEventNewFromObj(vm,
                                                  VIR_DOMAIN_EVENT_SUSPENDED,
                                                  detail);
            } /* else transition 6 and 9 use event as-is */
        } else {
            /* Transitions 2, 5, 8 */
            if (!virDomainObjIsActive(vm)) {
12580 12581
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("guest unexpectedly quit"));
12582 12583 12584 12585 12586
                goto endjob;
            }
            rc = qemuProcessStartCPUs(driver, vm, snapshot->domain->conn,
                                      VIR_DOMAIN_RUNNING_FROM_SNAPSHOT,
                                      QEMU_ASYNC_JOB_NONE);
H
Hu Tao 已提交
12587
            if (rc < 0)
12588
                goto endjob;
12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600 12601 12602 12603
            virDomainEventFree(event);
            event = NULL;
            if (was_stopped) {
                /* Transition 2 */
                detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
                event = virDomainEventNewFromObj(vm,
                                                 VIR_DOMAIN_EVENT_STARTED,
                                                 detail);
            } else if (was_running) {
                /* Transition 8 */
                detail = VIR_DOMAIN_EVENT_RESUMED;
                event = virDomainEventNewFromObj(vm,
                                                 VIR_DOMAIN_EVENT_RESUMED,
                                                 detail);
            }
C
Chris Lalancette 已提交
12604
        }
E
Eric Blake 已提交
12605
    } else {
12606
        /* Transitions 1, 4, 7 */
12607 12608 12609
        /* Newer qemu -loadvm refuses to revert to the state of a snapshot
         * created by qemu-img snapshot -c.  If the domain is running, we
         * must take it offline; then do the revert using qemu-img.
C
Chris Lalancette 已提交
12610 12611 12612
         */

        if (virDomainObjIsActive(vm)) {
12613
            /* Transitions 4, 7 */
12614
            qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
12615
            virDomainAuditStop(vm, "from-snapshot");
12616
            detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
C
Chris Lalancette 已提交
12617 12618
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STOPPED,
12619
                                             detail);
12620 12621
        }

E
Eric Blake 已提交
12622
        if (qemuDomainSnapshotRevertInactive(driver, vm, snap) < 0) {
12623
            if (!vm->persistent) {
12624
                if (qemuDomainObjEndJob(driver, vm) > 0)
12625
                    qemuDomainRemoveInactive(driver, vm);
12626
                vm = NULL;
12627
                goto cleanup;
12628
            }
12629
            goto endjob;
C
Chris Lalancette 已提交
12630
        }
12631
        if (config)
12632
            virDomainObjAssignDef(vm, config, false, NULL);
12633

12634 12635 12636 12637
        if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                     VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
            /* Flush first event, now do transition 2 or 3 */
            bool paused = (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED) != 0;
12638 12639 12640
            unsigned int start_flags = 0;

            start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
12641 12642 12643

            if (event)
                qemuDomainEventQueue(driver, event);
12644 12645 12646 12647
            rc = qemuProcessStart(snapshot->domain->conn,
                                  driver, vm, NULL, -1, NULL, NULL,
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                                  start_flags);
12648 12649 12650 12651
            virDomainAuditStart(vm, "from-snapshot", rc >= 0);
            if (rc < 0) {
                if (!vm->persistent) {
                    if (qemuDomainObjEndJob(driver, vm) > 0)
12652
                        qemuDomainRemoveInactive(driver, vm);
12653 12654 12655 12656 12657 12658 12659 12660 12661 12662 12663 12664 12665 12666 12667 12668
                    vm = NULL;
                    goto cleanup;
                }
                goto endjob;
            }
            detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STARTED,
                                             detail);
            if (paused) {
                detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
                event2 = virDomainEventNewFromObj(vm,
                                                  VIR_DOMAIN_EVENT_SUSPENDED,
                                                  detail);
            }
        }
C
Chris Lalancette 已提交
12669 12670 12671 12672
    }

    ret = 0;

12673
endjob:
12674
    if (vm && qemuDomainObjEndJob(driver, vm) == 0)
C
Chris Lalancette 已提交
12675 12676
        vm = NULL;

12677
cleanup:
12678 12679
    if (vm && ret == 0) {
        if (qemuDomainSnapshotWriteMetadata(vm, snap,
12680
                                            cfg->snapshotDir) < 0)
12681 12682 12683 12684 12685 12686
            ret = -1;
        else
            vm->current_snapshot = snap;
    } else if (snap) {
        snap->def->current = false;
    }
12687
    if (event) {
C
Chris Lalancette 已提交
12688
        qemuDomainEventQueue(driver, event);
12689 12690 12691
        if (event2)
            qemuDomainEventQueue(driver, event2);
    }
C
Chris Lalancette 已提交
12692
    if (vm)
12693
        virObjectUnlock(vm);
12694
    virObjectUnref(caps);
12695
    virObjectUnref(cfg);
C
Chris Lalancette 已提交
12696 12697 12698 12699

    return ret;
}

12700 12701 12702 12703

typedef struct _virQEMUSnapReparent virQEMUSnapReparent;
typedef virQEMUSnapReparent *virQEMUSnapReparentPtr;
struct _virQEMUSnapReparent {
12704
    virQEMUDriverConfigPtr cfg;
12705
    virDomainSnapshotObjPtr parent;
12706 12707
    virDomainObjPtr vm;
    int err;
12708
    virDomainSnapshotObjPtr last;
12709 12710 12711 12712
};

static void
qemuDomainSnapshotReparentChildren(void *payload,
12713
                                   const void *name ATTRIBUTE_UNUSED,
12714 12715 12716
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
12717
    virQEMUSnapReparentPtr rep = data;
12718 12719 12720 12721 12722

    if (rep->err < 0) {
        return;
    }

12723
    VIR_FREE(snap->def->parent);
12724
    snap->parent = rep->parent;
12725

12726
    if (rep->parent->def) {
12727
        snap->def->parent = strdup(rep->parent->def->name);
12728

12729 12730 12731 12732
        if (snap->def->parent == NULL) {
            virReportOOMError();
            rep->err = -1;
            return;
12733 12734
        }
    }
12735

12736 12737 12738
    if (!snap->sibling)
        rep->last = snap;

12739
    rep->err = qemuDomainSnapshotWriteMetadata(rep->vm, snap,
12740
                                               rep->cfg->snapshotDir);
12741 12742
}

12743

C
Chris Lalancette 已提交
12744 12745 12746
static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                                    unsigned int flags)
{
12747
    virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
C
Chris Lalancette 已提交
12748 12749 12750
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;
12751 12752
    virQEMUSnapRemove rem;
    virQEMUSnapReparent rep;
12753
    bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);
12754
    int external = 0;
12755
    virQEMUDriverConfigPtr cfg = NULL;
C
Chris Lalancette 已提交
12756

12757
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
12758 12759
                  VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY |
                  VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);
12760

12761 12762
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
        return -1;
C
Chris Lalancette 已提交
12763

12764
    cfg = virQEMUDriverGetConfig(driver);
12765
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
C
Chris Lalancette 已提交
12766 12767
        goto cleanup;

12768
    if (!metadata_only) {
12769
        if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
12770
            virDomainSnapshotIsExternal(snap))
12771 12772
            external++;
        if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN)
E
Eric Blake 已提交
12773
            virDomainSnapshotForEachDescendant(snap,
12774 12775 12776
                                               qemuDomainSnapshotCountExternal,
                                               &external);
        if (external) {
12777 12778 12779
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("deletion of %d external disk snapshots not "
                             "supported yet"), external);
12780 12781 12782 12783
            goto cleanup;
        }
    }

12784
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
12785 12786
        goto cleanup;

12787 12788
    if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
C
Chris Lalancette 已提交
12789 12790
        rem.driver = driver;
        rem.vm = vm;
12791
        rem.metadata_only = metadata_only;
C
Chris Lalancette 已提交
12792
        rem.err = 0;
12793
        rem.current = false;
E
Eric Blake 已提交
12794
        virDomainSnapshotForEachDescendant(snap,
E
Eric Blake 已提交
12795
                                           qemuDomainSnapshotDiscardAll,
12796
                                           &rem);
C
Chris Lalancette 已提交
12797
        if (rem.err < 0)
12798
            goto endjob;
12799 12800 12801 12802
        if (rem.current) {
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
                snap->def->current = true;
                if (qemuDomainSnapshotWriteMetadata(vm, snap,
12803
                                                    cfg->snapshotDir) < 0) {
12804 12805 12806
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("failed to set snapshot '%s' as current"),
                                   snap->def->name);
12807 12808 12809 12810
                    snap->def->current = false;
                    goto endjob;
                }
            }
12811
            vm->current_snapshot = snap;
12812
        }
12813
    } else if (snap->nchildren) {
12814
        rep.cfg = cfg;
12815
        rep.parent = snap->parent;
12816 12817
        rep.vm = vm;
        rep.err = 0;
12818
        rep.last = NULL;
E
Eric Blake 已提交
12819
        virDomainSnapshotForEachChild(snap,
12820 12821
                                      qemuDomainSnapshotReparentChildren,
                                      &rep);
12822 12823
        if (rep.err < 0)
            goto endjob;
12824
        /* Can't modify siblings during ForEachChild, so do it now.  */
12825 12826 12827
        snap->parent->nchildren += snap->nchildren;
        rep.last->sibling = snap->parent->first_child;
        snap->parent->first_child = snap->first_child;
C
Chris Lalancette 已提交
12828 12829
    }

12830 12831 12832
    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
        snap->nchildren = 0;
        snap->first_child = NULL;
12833
        ret = 0;
12834
    } else {
12835
        virDomainSnapshotDropParent(snap);
12836
        ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
12837
    }
C
Chris Lalancette 已提交
12838

12839
endjob:
12840
    if (qemuDomainObjEndJob(driver, vm) == 0)
12841 12842
        vm = NULL;

C
Chris Lalancette 已提交
12843 12844
cleanup:
    if (vm)
12845
        virObjectUnlock(vm);
12846
    virObjectUnref(cfg);
C
Chris Lalancette 已提交
12847 12848
    return ret;
}
12849

12850 12851
static int qemuDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
                                        char **result, unsigned int flags)
12852
{
12853
    virQEMUDriverPtr driver = domain->conn->privateData;
12854 12855 12856
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
12857
    bool hmp;
12858

12859
    virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
12860

12861
    if (!(vm = qemuDomObjFromDomain(domain)))
12862 12863 12864
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
12865 12866
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
12867
        goto cleanup;
12868
    }
12869

12870
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
12871 12872 12873
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
12874 12875
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
12876 12877 12878
        goto endjob;
    }

12879 12880
    priv = vm->privateData;

12881
    qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_MONITOR, -1);
12882

12883 12884
    hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);

12885
    qemuDomainObjEnterMonitor(driver, vm);
12886
    ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
12887
    qemuDomainObjExitMonitor(driver, vm);
12888 12889

endjob:
12890
    if (qemuDomainObjEndJob(driver, vm) == 0) {
12891 12892 12893 12894 12895
        vm = NULL;
    }

cleanup:
    if (vm)
12896
        virObjectUnlock(vm);
12897 12898 12899
    return ret;
}

12900

12901 12902 12903
static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn,
                                         unsigned int pid_value,
                                         unsigned int flags)
12904
{
12905
    virQEMUDriverPtr driver = conn->privateData;
12906 12907 12908 12909 12910
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainPtr dom = NULL;
    virDomainChrSourceDefPtr monConfig = NULL;
    bool monJSON = false;
12911
    pid_t pid = pid_value;
12912
    char *pidfile = NULL;
12913
    virQEMUCapsPtr qemuCaps = NULL;
12914
    virCapsPtr caps = NULL;
12915 12916 12917

    virCheckFlags(0, NULL);

12918 12919 12920
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

12921
    if (!(def = qemuParseCommandLinePid(caps, driver->xmlopt, pid,
12922 12923 12924 12925
                                        &pidfile, &monConfig, &monJSON)))
        goto cleanup;

    if (!monConfig) {
12926 12927
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("No monitor connection for pid %u"), pid_value);
12928 12929 12930
        goto cleanup;
    }
    if (monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
12931 12932 12933 12934 12935
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Cannot connect to monitor connection of type '%s' "
                         "for pid %u"),
                       virDomainChrTypeToString(monConfig->type),
                       pid_value);
12936 12937 12938 12939
        goto cleanup;
    }

    if (!(def->name) &&
12940
        virAsprintf(&def->name, "attach-pid-%u", pid_value) < 0) {
12941 12942 12943 12944
        virReportOOMError();
        goto cleanup;
    }

12945
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
12946 12947
        goto cleanup;

12948
    if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
12949 12950
        goto cleanup;

12951
    if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
12952 12953
        goto cleanup;

12954
    if (!(vm = virDomainObjListAdd(driver->domains, def,
12955
                                   driver->xmlopt,
12956 12957 12958
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
12959 12960 12961 12962
        goto cleanup;

    def = NULL;

12963
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
12964 12965 12966 12967 12968 12969 12970 12971 12972 12973 12974 12975 12976 12977
        goto cleanup;

    if (qemuProcessAttach(conn, driver, vm, pid,
                          pidfile, monConfig, monJSON) < 0) {
        monConfig = NULL;
        goto endjob;
    }

    monConfig = NULL;

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

endjob:
12978
    if (qemuDomainObjEndJob(driver, vm) == 0) {
12979 12980 12981 12982 12983 12984
        vm = NULL;
        goto cleanup;
    }

cleanup:
    virDomainDefFree(def);
12985
    virObjectUnref(qemuCaps);
12986 12987
    virDomainChrSourceDefFree(monConfig);
    if (vm)
12988
        virObjectUnlock(vm);
12989
    VIR_FREE(pidfile);
12990
    virObjectUnref(caps);
12991 12992 12993 12994
    return dom;
}


12995 12996
static int
qemuDomainOpenConsole(virDomainPtr dom,
12997
                      const char *dev_name,
12998 12999 13000 13001 13002 13003 13004
                      virStreamPtr st,
                      unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    int i;
    virDomainChrDefPtr chr = NULL;
13005
    qemuDomainObjPrivatePtr priv;
13006

13007 13008
    virCheckFlags(VIR_DOMAIN_CONSOLE_SAFE |
                  VIR_DOMAIN_CONSOLE_FORCE, -1);
13009

13010
    if (!(vm = qemuDomObjFromDomain(dom)))
13011 13012 13013
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
13014 13015
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
13016 13017 13018
        goto cleanup;
    }

13019 13020
    priv = vm->privateData;

13021
    if (dev_name) {
13022
        for (i = 0; !chr && i < vm->def->nconsoles; i++) {
13023 13024 13025 13026
            if (vm->def->consoles[i]->info.alias &&
                STREQ(dev_name, vm->def->consoles[i]->info.alias))
                chr = vm->def->consoles[i];
        }
13027
        for (i = 0; !chr && i < vm->def->nserials; i++) {
13028
            if (STREQ(dev_name, vm->def->serials[i]->info.alias))
13029 13030
                chr = vm->def->serials[i];
        }
13031
        for (i = 0; !chr && i < vm->def->nparallels; i++) {
13032
            if (STREQ(dev_name, vm->def->parallels[i]->info.alias))
13033 13034 13035
                chr = vm->def->parallels[i];
        }
    } else {
13036 13037
        if (vm->def->nconsoles)
            chr = vm->def->consoles[0];
13038 13039 13040 13041 13042
        else if (vm->def->nserials)
            chr = vm->def->serials[0];
    }

    if (!chr) {
13043 13044 13045
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find character device %s"),
                       NULLSTR(dev_name));
13046 13047 13048
        goto cleanup;
    }

13049
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
13050 13051 13052
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"),
                       NULLSTR(dev_name));
13053 13054 13055
        goto cleanup;
    }

13056
    /* handle mutually exclusive access to console devices */
13057
    ret = virChrdevOpen(priv->devs,
13058
                        &chr->source,
13059 13060
                        st,
                        (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
13061 13062

    if (ret == 1) {
13063 13064
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Active console session exists for this domain"));
13065 13066
        ret = -1;
    }
13067 13068 13069

cleanup:
    if (vm)
13070
        virObjectUnlock(vm);
13071 13072 13073
    return ret;
}

13074 13075 13076 13077 13078 13079 13080 13081 13082 13083 13084 13085 13086 13087 13088 13089 13090 13091 13092 13093 13094 13095 13096 13097 13098 13099
static int
qemuDomainOpenChannel(virDomainPtr dom,
                      const char *name,
                      virStreamPtr st,
                      unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    int i;
    virDomainChrDefPtr chr = NULL;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(VIR_DOMAIN_CHANNEL_FORCE, -1);

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    priv = vm->privateData;

    if (name) {
13100
        for (i = 0; !chr && i < vm->def->nchannels; i++) {
13101 13102 13103 13104 13105 13106 13107 13108 13109 13110 13111 13112 13113 13114 13115 13116 13117 13118 13119 13120 13121 13122 13123 13124 13125 13126 13127 13128 13129 13130 13131 13132 13133 13134 13135 13136 13137 13138 13139 13140 13141
            if (STREQ(name, vm->def->channels[i]->info.alias))
                chr = vm->def->channels[i];

            if (vm->def->channels[i]->targetType == \
                VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
                STREQ(name, vm->def->channels[i]->target.name))
                chr = vm->def->channels[i];
        }
    } else {
        if (vm->def->nchannels)
            chr = vm->def->channels[0];
    }

    if (!chr) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find channel %s"),
                       NULLSTR(name));
        goto cleanup;
    }

    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_UNIX) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("channel %s is not using a UNIX socket"),
                       NULLSTR(name));
        goto cleanup;
    }

    /* handle mutually exclusive access to channel devices */
    ret = virChrdevOpen(priv->devs,
                        &chr->source,
                        st,
                        (flags & VIR_DOMAIN_CHANNEL_FORCE) != 0);

    if (ret == 1) {
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Active channel stream exists for this domain"));
        ret = -1;
    }

cleanup:
    if (vm)
13142
        virObjectUnlock(vm);
13143 13144 13145
    return ret;
}

E
Eric Blake 已提交
13146
static char *
E
Eric Blake 已提交
13147
qemuDiskPathToAlias(virDomainObjPtr vm, const char *path, int *idx)
E
Eric Blake 已提交
13148
{
13149 13150
    int i;
    char *ret = NULL;
13151
    virDomainDiskDefPtr disk;
13152

13153 13154 13155
    i = virDomainDiskIndexByName(vm->def, path, true);
    if (i < 0)
        goto cleanup;
13156

13157
    disk = vm->def->disks[i];
E
Eric Blake 已提交
13158 13159
    if (idx)
        *idx = i;
13160

13161 13162 13163 13164
    if (disk->src) {
        if (virAsprintf(&ret, "drive-%s", disk->info.alias) < 0) {
            virReportOOMError();
            return NULL;
13165 13166 13167
        }
    }

13168
cleanup:
13169
    if (!ret) {
13170 13171
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("No device found for specified path"));
13172 13173 13174 13175
    }
    return ret;
}

13176 13177 13178 13179
/* Called while holding the VM job lock, to implement a block job
 * abort with pivot; this updates the VM definition as appropriate, on
 * either success or failure.  */
static int
E
Eric Blake 已提交
13180
qemuDomainBlockPivot(virConnectPtr conn,
13181
                     virQEMUDriverPtr driver, virDomainObjPtr vm,
13182 13183 13184 13185 13186 13187
                     const char *device, virDomainDiskDefPtr disk)
{
    int ret = -1;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virDomainBlockJobInfo info;
    const char *format = virStorageFileFormatTypeToString(disk->mirrorFormat);
E
Eric Blake 已提交
13188
    bool resume = false;
13189 13190 13191
    char *oldsrc = NULL;
    int oldformat;
    virStorageFileMetadataPtr oldchain = NULL;
13192
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
13193 13194 13195

    /* Probe the status, if needed.  */
    if (!disk->mirroring) {
13196
        qemuDomainObjEnterMonitor(driver, vm);
13197 13198
        ret = qemuMonitorBlockJob(priv->mon, device, NULL, 0, &info,
                                  BLOCK_JOB_INFO, true);
13199
        qemuDomainObjExitMonitor(driver, vm);
13200 13201 13202 13203 13204 13205 13206 13207 13208 13209 13210 13211 13212 13213 13214 13215 13216 13217 13218
        if (ret < 0)
            goto cleanup;
        if (!virDomainObjIsActive(vm)) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("domain is not running"));
            goto cleanup;
        }
        if (ret == 1 && info.cur == info.end &&
            info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
            disk->mirroring = true;
    }

    if (!disk->mirroring) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
                       _("disk '%s' not ready for pivot yet"),
                       disk->dst);
        goto cleanup;
    }

E
Eric Blake 已提交
13219 13220 13221 13222 13223 13224 13225 13226 13227 13228 13229 13230 13231 13232 13233 13234 13235 13236 13237 13238 13239 13240 13241
    /* If we are using the older 'drive-reopen', we want to make sure
     * that management apps can tell whether the command succeeded,
     * even if libvirtd is restarted at the wrong time.  To accomplish
     * that, we pause the guest before drive-reopen, and resume it
     * only when we know the outcome; if libvirtd restarts, then
     * management will see the guest still paused, and know that no
     * guest I/O has caused the source and mirror to diverge.  XXX
     * With the newer 'block-job-complete', we need to use a
     * persistent bitmap to make things safe; so for now, we just
     * blindly pause the guest.  */
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
                                QEMU_ASYNC_JOB_NONE) < 0)
            goto cleanup;

        resume = true;
        if (!virDomainObjIsActive(vm)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
            goto cleanup;
        }
    }

13242 13243 13244 13245 13246 13247 13248 13249 13250 13251 13252 13253 13254 13255 13256 13257 13258 13259 13260
    /* We previously labeled only the top-level image; but if the
     * image includes a relative backing file, the pivot may result in
     * qemu needing to open the entire backing chain, so we need to
     * label the entire chain.  This action is safe even if the
     * backing chain has already been labeled; but only necessary when
     * we know for sure that there is a backing chain.  */
    oldsrc = disk->src;
    oldformat = disk->format;
    oldchain = disk->backingChain;
    disk->src = disk->mirror;
    disk->format = disk->mirrorFormat;
    disk->backingChain = NULL;
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) {
        disk->src = oldsrc;
        disk->format = oldformat;
        disk->backingChain = oldchain;
        goto cleanup;
    }
    if (disk->mirrorFormat && disk->mirrorFormat != VIR_STORAGE_FILE_RAW &&
13261
        (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
13262
                                 vm, disk) < 0 ||
13263
         qemuSetupDiskCgroup(vm, disk) < 0 ||
13264 13265 13266 13267 13268 13269 13270 13271
         virSecurityManagerSetImageLabel(driver->securityManager, vm->def,
                                         disk) < 0)) {
        disk->src = oldsrc;
        disk->format = oldformat;
        disk->backingChain = oldchain;
        goto cleanup;
    }

13272
    /* Attempt the pivot.  */
13273
    qemuDomainObjEnterMonitor(driver, vm);
13274
    ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror, format);
13275
    qemuDomainObjExitMonitor(driver, vm);
13276 13277 13278 13279 13280 13281 13282 13283 13284

    if (ret == 0) {
        /* XXX We want to revoke security labels and disk lease, as
         * well as audit that revocation, before dropping the original
         * source.  But it gets tricky if both source and mirror share
         * common backing files (we want to only revoke the non-shared
         * portion of the chain, and is made more difficult by the
         * fact that we aren't tracking the full chain ourselves; so
         * for now, we leak the access to the original.  */
13285 13286
        VIR_FREE(oldsrc);
        virStorageFileFreeMetadata(oldchain);
13287 13288 13289 13290 13291 13292 13293 13294 13295 13296
        disk->mirror = NULL;
    } else {
        /* On failure, qemu abandons the mirror, and reverts back to
         * the source disk (RHEL 6.3 has a bug where the revert could
         * cause catastrophic failure in qemu, but we don't need to
         * worry about it here as it is not an upstream qemu problem.  */
        /* XXX should we be parsing the exact qemu error, or calling
         * 'query-block', to see what state we really got left in
         * before killing the mirroring job?  And just as on the
         * success case, there's security labeling to worry about.  */
13297 13298 13299 13300
        disk->src = oldsrc;
        disk->format = oldformat;
        virStorageFileFreeMetadata(disk->backingChain);
        disk->backingChain = oldchain;
13301 13302
        VIR_FREE(disk->mirror);
    }
13303 13304
    disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
    disk->mirroring = false;
13305 13306

cleanup:
E
Eric Blake 已提交
13307 13308 13309
    if (resume && virDomainObjIsActive(vm) &&
        qemuProcessStartCPUs(driver, vm, conn,
                             VIR_DOMAIN_RUNNING_UNPAUSED,
13310 13311 13312 13313 13314 13315 13316 13317 13318 13319 13320
                             QEMU_ASYNC_JOB_NONE) < 0) {
        virDomainEventPtr event = NULL;
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
        if (event)
            qemuDomainEventQueue(driver, event);
        if (virGetLastError() == NULL) {
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("resuming after drive-reopen failed"));
        }
E
Eric Blake 已提交
13321
    }
13322
    virObjectUnref(cfg);
13323 13324 13325
    return ret;
}

13326
static int
13327
qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base,
13328
                       unsigned long bandwidth, virDomainBlockJobInfoPtr info,
13329
                       int mode, unsigned int flags)
13330
{
13331
    virQEMUDriverPtr driver = dom->conn->privateData;
13332 13333
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
E
Eric Blake 已提交
13334
    char *device = NULL;
13335
    int ret = -1;
13336
    bool async = false;
13337 13338 13339
    virDomainEventPtr event = NULL;
    int idx;
    virDomainDiskDefPtr disk;
13340

13341 13342 13343
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

13344
    if (!virDomainObjIsActive(vm)) {
13345 13346
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
13347 13348 13349
        goto cleanup;
    }

13350
    priv = vm->privateData;
13351
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC)) {
13352
        async = true;
13353
    } else if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_SYNC)) {
13354 13355
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("block jobs not supported with this QEMU binary"));
13356 13357
        goto cleanup;
    } else if (base) {
13358 13359 13360
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("partial block pull not supported with this "
                         "QEMU binary"));
13361
        goto cleanup;
13362
    } else if (mode == BLOCK_JOB_PULL && bandwidth) {
13363 13364 13365
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("setting bandwidth at start of block pull not "
                         "supported with this QEMU binary"));
13366
        goto cleanup;
13367
    }
13368

13369 13370
    device = qemuDiskPathToAlias(vm, path, &idx);
    if (!device)
13371
        goto cleanup;
13372
    disk = vm->def->disks[idx];
13373

E
Eric Blake 已提交
13374 13375 13376 13377 13378 13379
    if (mode == BLOCK_JOB_PULL && disk->mirror) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
                       _("disk '%s' already in active block copy job"),
                       disk->dst);
        goto cleanup;
    }
13380 13381 13382 13383 13384 13385 13386 13387
    if (mode == BLOCK_JOB_ABORT &&
        (flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT) &&
        !(async && disk->mirror)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("pivot of disk '%s' requires an active copy job"),
                       disk->dst);
        goto cleanup;
    }
E
Eric Blake 已提交
13388

13389
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
13390
        goto cleanup;
13391 13392

    if (!virDomainObjIsActive(vm)) {
13393 13394
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
13395 13396 13397
        goto endjob;
    }

13398 13399
    if (disk->mirror && mode == BLOCK_JOB_ABORT &&
        (flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT)) {
E
Eric Blake 已提交
13400
        ret = qemuDomainBlockPivot(dom->conn, driver, vm, device, disk);
13401 13402 13403
        goto endjob;
    }

13404
    qemuDomainObjEnterMonitor(driver, vm);
13405
    /* XXX - libvirt should really be tracking the backing file chain
13406 13407
     * itself, and validating that base is on the chain, rather than
     * relying on qemu to do this.  */
13408 13409
    ret = qemuMonitorBlockJob(priv->mon, device, base, bandwidth, info, mode,
                              async);
13410
    qemuDomainObjExitMonitor(driver, vm);
13411 13412 13413
    if (ret < 0)
        goto endjob;

13414 13415 13416 13417 13418 13419
    /* Snoop block copy operations, so future cancel operations can
     * avoid checking if pivot is safe.  */
    if (mode == BLOCK_JOB_INFO && ret == 1 && disk->mirror &&
        info->cur == info->end && info->type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
        disk->mirroring = true;

13420 13421 13422 13423 13424 13425 13426 13427 13428
    /* A successful block job cancelation stops any mirroring.  */
    if (mode == BLOCK_JOB_ABORT && disk->mirror) {
        /* XXX We should also revoke security labels and disk lease on
         * the mirror, and audit that fact, before dropping things.  */
        VIR_FREE(disk->mirror);
        disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
        disk->mirroring = false;
    }

13429 13430 13431 13432 13433 13434 13435 13436 13437 13438 13439 13440 13441 13442 13443 13444 13445 13446 13447
    /* With synchronous block cancel, we must synthesize an event, and
     * we silently ignore the ABORT_ASYNC flag.  With asynchronous
     * block cancel, the event will come from qemu, but without the
     * ABORT_ASYNC flag, we must block to guarantee synchronous
     * operation.  We do the waiting while still holding the VM job,
     * to prevent newly scheduled block jobs from confusing us.  */
    if (mode == BLOCK_JOB_ABORT) {
        if (!async) {
            int type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
            int status = VIR_DOMAIN_BLOCK_JOB_CANCELED;
            event = virDomainEventBlockJobNewFromObj(vm, disk->src, type,
                                                     status);
        } else if (!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)) {
            while (1) {
                /* Poll every 50ms */
                static struct timespec ts = { .tv_sec = 0,
                                              .tv_nsec = 50 * 1000 * 1000ull };
                virDomainBlockJobInfo dummy;

13448
                qemuDomainObjEnterMonitor(driver, vm);
13449 13450
                ret = qemuMonitorBlockJob(priv->mon, device, NULL, 0, &dummy,
                                          BLOCK_JOB_INFO, async);
13451
                qemuDomainObjExitMonitor(driver, vm);
13452 13453 13454 13455

                if (ret <= 0)
                    break;

13456
                virObjectUnlock(vm);
13457 13458 13459

                nanosleep(&ts, NULL);

13460
                virObjectLock(vm);
13461 13462

                if (!virDomainObjIsActive(vm)) {
13463 13464
                    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                                   _("domain is not running"));
13465 13466 13467 13468 13469 13470
                    ret = -1;
                    break;
                }
            }
        }
    }
13471 13472

endjob:
13473 13474 13475 13476 13477 13478 13479 13480
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    VIR_FREE(device);
    if (vm)
13481
        virObjectUnlock(vm);
13482 13483
    if (event)
        qemuDomainEventQueue(driver, event);
13484 13485 13486 13487 13488 13489
    return ret;
}

static int
qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags)
{
13490 13491
    virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC |
                  VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, -1);
13492 13493
    return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT,
                                  flags);
13494 13495 13496 13497 13498 13499 13500
}

static int
qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
                           virDomainBlockJobInfoPtr info, unsigned int flags)
{
    virCheckFlags(0, -1);
13501 13502
    return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO,
                                  flags);
13503 13504 13505 13506 13507 13508 13509
}

static int
qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
                           unsigned long bandwidth, unsigned int flags)
{
    virCheckFlags(0, -1);
13510
    return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
13511
                                  BLOCK_JOB_SPEED, flags);
13512 13513
}

13514 13515 13516 13517 13518
static int
qemuDomainBlockCopy(virDomainPtr dom, const char *path,
                    const char *dest, const char *format,
                    unsigned long bandwidth, unsigned int flags)
{
13519
    virQEMUDriverPtr driver = dom->conn->privateData;
13520 13521 13522 13523 13524 13525
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    char *device = NULL;
    virDomainDiskDefPtr disk;
    int ret = -1;
    int idx;
13526
    struct stat st;
13527 13528
    bool need_unlink = false;
    char *mirror = NULL;
13529
    virQEMUDriverConfigPtr cfg = NULL;
13530 13531

    /* Preliminaries: find the disk we are editing, sanity checks */
13532 13533
    virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
                  VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1);
13534 13535 13536 13537

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;
    priv = vm->privateData;
13538
    cfg = virQEMUDriverGetConfig(driver);
13539 13540 13541 13542 13543 13544 13545 13546 13547 13548 13549 13550 13551 13552 13553 13554 13555 13556
    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
        goto cleanup;
    }

    device = qemuDiskPathToAlias(vm, path, &idx);
    if (!device) {
        goto cleanup;
    }
    disk = vm->def->disks[idx];
    if (disk->mirror) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
                       _("disk '%s' already in active block copy job"),
                       disk->dst);
        goto cleanup;
    }

13557 13558
    if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
          virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
13559 13560 13561 13562 13563 13564 13565 13566 13567 13568 13569 13570 13571 13572 13573 13574 13575 13576 13577 13578 13579 13580 13581 13582 13583 13584 13585 13586 13587 13588 13589 13590 13591 13592 13593 13594
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("block copy is not supported with this QEMU binary"));
        goto cleanup;
    }
    if (vm->persistent) {
        /* XXX if qemu ever lets us start a new domain with mirroring
         * already active, we can relax this; but for now, the risk of
         * 'managedsave' due to libvirt-guests means we can't risk
         * this on persistent domains.  */
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not transient"));
        goto cleanup;
    }

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
        goto endjob;
    }
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
        goto endjob;

    if ((flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) &&
        STREQ_NULLABLE(format, "raw") &&
        disk->backingChain->backingStore) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk '%s' has backing file, so raw shallow copy "
                         "is not possible"),
                       disk->dst);
        goto endjob;
    }

    /* Prepare the destination file.  */
13595 13596 13597 13598 13599 13600 13601 13602 13603 13604 13605 13606 13607 13608 13609 13610 13611 13612 13613 13614
    if (stat(dest, &st) < 0) {
        if (errno != ENOENT) {
            virReportSystemError(errno, _("unable to stat for disk %s: %s"),
                                 disk->dst, dest);
            goto endjob;
        } else if (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) {
            virReportSystemError(errno,
                                 _("missing destination file for disk %s: %s"),
                                 disk->dst, dest);
            goto endjob;
        }
    } else if (!S_ISBLK(st.st_mode) && st.st_size &&
               !(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("external destination file for disk %s already "
                         "exists and is not a block device: %s"),
                       disk->dst, dest);
        goto endjob;
    }

13615 13616 13617 13618 13619 13620 13621
    if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
        int fd = qemuOpenFile(driver, dest, O_WRONLY | O_TRUNC | O_CREAT,
                              &need_unlink, NULL);
        if (fd < 0)
            goto endjob;
        VIR_FORCE_CLOSE(fd);
        if (!format)
13622
            disk->mirrorFormat = disk->format;
13623
    } else if (format) {
13624 13625 13626 13627 13628 13629
        disk->mirrorFormat = virStorageFileFormatTypeFromString(format);
        if (disk->mirrorFormat <= 0) {
            virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"),
                           format);
            goto endjob;
        }
13630 13631 13632 13633 13634
    } else {
        /* If the user passed the REUSE_EXT flag, then either they
         * also passed the RAW flag (and format is non-NULL), or it is
         * safe for us to probe the format from the file that we will
         * be using.  */
13635 13636
        disk->mirrorFormat = virStorageFileProbeFormat(dest, cfg->user,
                                                       cfg->group);
13637 13638 13639
    }
    if (!format && disk->mirrorFormat > 0)
        format = virStorageFileFormatTypeToString(disk->mirrorFormat);
13640
    if (!(mirror = strdup(dest))) {
13641 13642 13643 13644
        virReportOOMError();
        goto endjob;
    }

13645
    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
13646
                                          VIR_DISK_CHAIN_READ_WRITE) < 0) {
13647
        qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
13648 13649 13650 13651
                                          VIR_DISK_CHAIN_NO_ACCESS);
        goto endjob;
    }

13652 13653 13654 13655
    /* Actually start the mirroring */
    qemuDomainObjEnterMonitor(driver, vm);
    ret = qemuMonitorDriveMirror(priv->mon, device, dest, format, bandwidth,
                                 flags);
13656
    virDomainAuditDisk(vm, NULL, dest, "mirror", ret >= 0);
13657
    qemuDomainObjExitMonitor(driver, vm);
13658
    if (ret < 0) {
13659
        qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
13660 13661 13662 13663 13664 13665 13666 13667
                                          VIR_DISK_CHAIN_NO_ACCESS);
        goto endjob;
    }

    /* Update vm in place to match changes.  */
    need_unlink = false;
    disk->mirror = mirror;
    mirror = NULL;
13668 13669

endjob:
13670 13671 13672
    if (need_unlink && unlink(dest))
        VIR_WARN("unable to unlink just-created %s", dest);
    if (ret < 0)
13673
        disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
13674
    VIR_FREE(mirror);
13675 13676 13677 13678 13679 13680 13681 13682
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    VIR_FREE(device);
    if (vm)
13683
        virObjectUnlock(vm);
13684
    virObjectUnref(cfg);
13685 13686 13687
    return ret;
}

13688
static int
13689 13690
qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
                      unsigned long bandwidth, unsigned int flags)
13691
{
13692
    virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
13693
                  VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
13694 13695 13696 13697 13698 13699 13700 13701 13702 13703 13704 13705
                  VIR_DOMAIN_BLOCK_REBASE_COPY |
                  VIR_DOMAIN_BLOCK_REBASE_COPY_RAW, -1);

    if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY) {
        const char *format = NULL;
        if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_RAW)
            format = "raw";
        flags &= ~(VIR_DOMAIN_BLOCK_REBASE_COPY |
                   VIR_DOMAIN_BLOCK_REBASE_COPY_RAW);
        return qemuDomainBlockCopy(dom, path, base, format, bandwidth, flags);
    }

13706 13707
    return qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL,
                                  BLOCK_JOB_PULL, flags);
13708
}
13709

13710 13711 13712 13713
static int
qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
                    unsigned int flags)
{
13714 13715 13716
    virCheckFlags(0, -1);
    return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
                                  BLOCK_JOB_PULL, flags);
13717 13718
}

13719 13720 13721 13722 13723 13724

static int
qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
                      const char *top, unsigned long bandwidth,
                      unsigned int flags)
{
13725
    virQEMUDriverPtr driver = dom->conn->privateData;
13726 13727 13728 13729 13730
    qemuDomainObjPrivatePtr priv;
    virDomainObjPtr vm = NULL;
    char *device = NULL;
    int ret = -1;
    int idx;
E
Eric Blake 已提交
13731
    virDomainDiskDefPtr disk = NULL;
13732 13733 13734 13735
    const char *top_canon = NULL;
    virStorageFileMetadataPtr top_meta = NULL;
    const char *top_parent = NULL;
    const char *base_canon = NULL;
E
Eric Blake 已提交
13736
    bool clean_access = false;
13737

13738
    virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW, -1);
13739 13740 13741 13742 13743 13744 13745 13746 13747 13748 13749 13750 13751

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;
    priv = vm->privateData;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto endjob;
    }
13752
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_COMMIT)) {
13753 13754 13755 13756 13757 13758 13759 13760 13761 13762 13763 13764 13765 13766 13767 13768
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("online commit not supported with this QEMU binary"));
        goto endjob;
    }

    device = qemuDiskPathToAlias(vm, path, &idx);
    if (!device)
        goto endjob;
    disk = vm->def->disks[idx];

    if (!disk->src) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk %s has no source file to be committed"),
                       disk->dst);
        goto endjob;
    }
13769 13770
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
        goto endjob;
13771

13772 13773 13774 13775 13776 13777 13778 13779 13780 13781 13782 13783 13784 13785 13786 13787 13788 13789 13790 13791 13792 13793 13794 13795 13796 13797 13798 13799 13800 13801 13802 13803 13804 13805 13806 13807 13808 13809 13810
    if (!top) {
        top_canon = disk->src;
        top_meta = disk->backingChain;
    } else if (!(top_canon = virStorageFileChainLookup(disk->backingChain,
                                                       disk->src,
                                                       top, &top_meta,
                                                       &top_parent))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("could not find top '%s' in chain for '%s'"),
                       top, path);
        goto endjob;
    }
    if (!top_meta || !top_meta->backingStore) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("top '%s' in chain for '%s' has no backing file"),
                       top, path);
        goto endjob;
    }
    if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW)) {
        base_canon = top_meta->backingStore;
    } else if (!(base_canon = virStorageFileChainLookup(top_meta, top_canon,
                                                        base, NULL, NULL))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("could not find base '%s' below '%s' in chain "
                         "for '%s'"),
                       base ? base : "(default)", top_canon, path);
        goto endjob;
    }
    /* Note that this code exploits the fact that
     * virStorageFileChainLookup guarantees a simple pointer
     * comparison will work, rather than needing full-blown STREQ.  */
    if ((flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW) &&
        base_canon != top_meta->backingStore) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("base '%s' is not immediately below '%s' in chain "
                         "for '%s'"),
                       base, top_canon, path);
        goto endjob;
    }
13811

13812 13813 13814 13815 13816 13817 13818
    /* For the commit to succeed, we must allow qemu to open both the
     * 'base' image and the parent of 'top' as read/write; 'top' might
     * not have a parent, or might already be read-write.  XXX It
     * would also be nice to revert 'base' to read-only, as well as
     * revoke access to files removed from the chain, when the commit
     * operation succeeds, but doing that requires tracking the
     * operation in XML across libvirtd restarts.  */
E
Eric Blake 已提交
13819
    clean_access = true;
13820
    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, base_canon,
13821 13822
                                          VIR_DISK_CHAIN_READ_WRITE) < 0 ||
        (top_parent && top_parent != disk->src &&
13823
         qemuDomainPrepareDiskChainElement(driver, vm, disk,
13824 13825 13826 13827 13828
                                           top_parent,
                                           VIR_DISK_CHAIN_READ_WRITE) < 0))
        goto endjob;

    /* Start the commit operation.  */
13829
    qemuDomainObjEnterMonitor(driver, vm);
13830 13831
    ret = qemuMonitorBlockCommit(priv->mon, device, top_canon, base_canon,
                                 bandwidth);
13832 13833 13834
    qemuDomainObjExitMonitor(driver, vm);

endjob:
E
Eric Blake 已提交
13835
    if (ret < 0 && clean_access) {
13836
        /* Revert access to read-only, if possible.  */
13837
        qemuDomainPrepareDiskChainElement(driver, vm, disk, base_canon,
13838 13839
                                          VIR_DISK_CHAIN_READ_ONLY);
        if (top_parent && top_parent != disk->src)
13840
            qemuDomainPrepareDiskChainElement(driver, vm, disk,
13841 13842 13843
                                              top_parent,
                                              VIR_DISK_CHAIN_READ_ONLY);
    }
13844 13845 13846 13847 13848 13849 13850 13851
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    VIR_FREE(device);
    if (vm)
13852
        virObjectUnlock(vm);
13853 13854 13855
    return ret;
}

13856 13857 13858 13859 13860 13861
static int
qemuDomainOpenGraphics(virDomainPtr dom,
                       unsigned int idx,
                       int fd,
                       unsigned int flags)
{
13862
    virQEMUDriverPtr driver = dom->conn->privateData;
13863 13864 13865 13866 13867 13868 13869
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
    const char *protocol;

    virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);

13870 13871
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
13872 13873

    if (!virDomainObjIsActive(vm)) {
13874 13875
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
13876 13877 13878 13879 13880 13881
        goto cleanup;
    }

    priv = vm->privateData;

    if (idx >= vm->def->ngraphics) {
13882 13883
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No graphics backend with index %d"), idx);
13884 13885 13886 13887 13888 13889 13890 13891 13892 13893
        goto cleanup;
    }
    switch (vm->def->graphics[idx]->type) {
    case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
        protocol = "vnc";
        break;
    case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
        protocol = "spice";
        break;
    default:
13894 13895 13896
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Can only open VNC or SPICE graphics backends, not %s"),
                       virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
13897 13898 13899
        goto cleanup;
    }

13900
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
13901
        goto cleanup;
13902
    qemuDomainObjEnterMonitor(driver, vm);
13903 13904
    ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
                                  (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
13905
    qemuDomainObjExitMonitor(driver, vm);
13906 13907 13908 13909 13910 13911 13912
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    if (vm)
13913
        virObjectUnlock(vm);
13914 13915 13916
    return ret;
}

13917 13918 13919 13920 13921 13922 13923
static int
qemuDomainSetBlockIoTune(virDomainPtr dom,
                         const char *disk,
                         virTypedParameterPtr params,
                         int nparams,
                         unsigned int flags)
{
13924
    virQEMUDriverPtr driver = dom->conn->privateData;
13925 13926 13927 13928
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
    virDomainDefPtr persistentDef = NULL;
    virDomainBlockIoTuneInfo info;
E
Eric Blake 已提交
13929
    virDomainBlockIoTuneInfo *oldinfo;
13930 13931 13932 13933
    const char *device = NULL;
    int ret = -1;
    int i;
    int idx = -1;
E
Eric Blake 已提交
13934 13935
    bool set_bytes = false;
    bool set_iops = false;
13936
    virQEMUDriverConfigPtr cfg = NULL;
13937
    virCapsPtr caps = NULL;
13938 13939 13940

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
13941 13942 13943 13944 13945 13946 13947 13948 13949 13950 13951 13952 13953 13954 13955
    if (virTypedParameterArrayValidate(params, nparams,
                                       VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
                                       VIR_TYPED_PARAM_ULLONG,
                                       NULL) < 0)
        return -1;
13956 13957 13958

    memset(&info, 0, sizeof(info));

13959 13960 13961
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

13962
    priv = vm->privateData;
13963 13964
    cfg = virQEMUDriverGetConfig(driver);

13965 13966 13967
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

13968
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE)) {
13969 13970 13971
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("block I/O throttling not supported with this "
                         "QEMU binary"));
13972 13973
        goto cleanup;
    }
13974

E
Eric Blake 已提交
13975
    device = qemuDiskPathToAlias(vm, disk, &idx);
13976 13977 13978 13979
    if (!device) {
        goto cleanup;
    }

13980
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
13981 13982
        goto cleanup;

13983
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
13984
                                        &persistentDef) < 0)
13985 13986 13987 13988 13989 13990 13991
        goto endjob;

    for (i = 0; i < nparams; i++) {
        virTypedParameterPtr param = &params[i];

        if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC)) {
            info.total_bytes_sec = param->value.ul;
E
Eric Blake 已提交
13992
            set_bytes = true;
13993 13994 13995
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC)) {
            info.read_bytes_sec = param->value.ul;
E
Eric Blake 已提交
13996
            set_bytes = true;
13997 13998 13999
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC)) {
            info.write_bytes_sec = param->value.ul;
E
Eric Blake 已提交
14000
            set_bytes = true;
14001 14002 14003
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC)) {
            info.total_iops_sec = param->value.ul;
E
Eric Blake 已提交
14004
            set_iops = true;
14005 14006 14007
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC)) {
            info.read_iops_sec = param->value.ul;
E
Eric Blake 已提交
14008
            set_iops = true;
14009 14010 14011
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) {
            info.write_iops_sec = param->value.ul;
E
Eric Blake 已提交
14012
            set_iops = true;
14013 14014 14015 14016 14017
        }
    }

    if ((info.total_bytes_sec && info.read_bytes_sec) ||
        (info.total_bytes_sec && info.write_bytes_sec)) {
14018 14019
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of bytes_sec cannot be set at the same time"));
14020 14021 14022 14023 14024
        goto endjob;
    }

    if ((info.total_iops_sec && info.read_iops_sec) ||
        (info.total_iops_sec && info.write_iops_sec)) {
14025 14026
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of iops_sec cannot be set at the same time"));
14027 14028 14029 14030
        goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
E
Eric Blake 已提交
14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 14043 14044
        /* If the user didn't specify bytes limits, inherit previous
         * values; likewise if the user didn't specify iops
         * limits.  */
        oldinfo = &vm->def->disks[idx]->blkdeviotune;
        if (!set_bytes) {
            info.total_bytes_sec = oldinfo->total_bytes_sec;
            info.read_bytes_sec = oldinfo->read_bytes_sec;
            info.write_bytes_sec = oldinfo->write_bytes_sec;
        }
        if (!set_iops) {
            info.total_iops_sec = oldinfo->total_iops_sec;
            info.read_iops_sec = oldinfo->read_iops_sec;
            info.write_iops_sec = oldinfo->write_iops_sec;
        }
14045
        qemuDomainObjEnterMonitor(driver, vm);
14046
        ret = qemuMonitorSetBlockIoThrottle(priv->mon, device, &info);
14047
        qemuDomainObjExitMonitor(driver, vm);
L
Lei Li 已提交
14048 14049
        if (ret < 0)
            goto endjob;
14050
        vm->def->disks[idx]->blkdeviotune = info;
14051 14052 14053
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
14054 14055 14056 14057
        sa_assert(persistentDef);
        idx = virDomainDiskIndexByName(persistentDef, disk, true);
        if (idx < 0)
            goto endjob;
E
Eric Blake 已提交
14058 14059 14060 14061 14062 14063 14064 14065 14066 14067 14068
        oldinfo = &persistentDef->disks[idx]->blkdeviotune;
        if (!set_bytes) {
            info.total_bytes_sec = oldinfo->total_bytes_sec;
            info.read_bytes_sec = oldinfo->read_bytes_sec;
            info.write_bytes_sec = oldinfo->write_bytes_sec;
        }
        if (!set_iops) {
            info.total_iops_sec = oldinfo->total_iops_sec;
            info.read_iops_sec = oldinfo->read_iops_sec;
            info.write_iops_sec = oldinfo->write_iops_sec;
        }
14069
        persistentDef->disks[idx]->blkdeviotune = info;
14070
        ret = virDomainSaveConfig(cfg->configDir, persistentDef);
14071
        if (ret < 0) {
14072
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14073 14074 14075 14076 14077 14078 14079 14080 14081 14082 14083 14084
                           _("Write to config file failed"));
            goto endjob;
        }
    }

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    VIR_FREE(device);
    if (vm)
14085
        virObjectUnlock(vm);
14086
    virObjectUnref(caps);
14087
    virObjectUnref(cfg);
14088 14089 14090 14091 14092 14093 14094 14095 14096 14097
    return ret;
}

static int
qemuDomainGetBlockIoTune(virDomainPtr dom,
                         const char *disk,
                         virTypedParameterPtr params,
                         int *nparams,
                         unsigned int flags)
{
14098
    virQEMUDriverPtr driver = dom->conn->privateData;
14099 14100 14101 14102 14103 14104 14105
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
    virDomainDefPtr persistentDef = NULL;
    virDomainBlockIoTuneInfo reply;
    const char *device = NULL;
    int ret = -1;
    int i;
14106
    virCapsPtr caps = NULL;
14107 14108 14109 14110 14111 14112 14113 14114

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

14115 14116
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
14117

14118 14119 14120
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

14121 14122 14123 14124 14125 14126 14127
    if ((*nparams) == 0) {
        /* Current number of parameters supported by QEMU Block I/O Throttling */
        *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM;
        ret = 0;
        goto cleanup;
    }

E
Eric Blake 已提交
14128
    device = qemuDiskPathToAlias(vm, disk, NULL);
14129 14130 14131 14132 14133

    if (!device) {
        goto cleanup;
    }

14134
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
14135 14136
        goto cleanup;

14137
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
14138
                                        &persistentDef) < 0)
14139 14140 14141 14142
        goto endjob;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        priv = vm->privateData;
14143
        qemuDomainObjEnterMonitor(driver, vm);
14144
        ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, &reply);
14145
        qemuDomainObjExitMonitor(driver, vm);
14146 14147 14148 14149 14150 14151 14152 14153 14154 14155 14156 14157 14158 14159
        if (ret < 0)
            goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        int idx = virDomainDiskIndexByName(vm->def, disk, true);
        if (idx < 0)
            goto endjob;
        reply = persistentDef->disks[idx]->blkdeviotune;
    }

    for (i = 0; i < QEMU_NB_BLOCK_IO_TUNE_PARAM && i < *nparams; i++) {
        virTypedParameterPtr param = &params[i];

14160
        switch (i) {
14161
        case 0:
14162 14163 14164 14165
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.total_bytes_sec) < 0)
14166 14167 14168
                goto endjob;
            break;
        case 1:
14169 14170 14171 14172
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.read_bytes_sec) < 0)
14173 14174 14175
                goto endjob;
            break;
        case 2:
14176 14177 14178 14179
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.write_bytes_sec) < 0)
14180 14181 14182
                goto endjob;
            break;
        case 3:
14183 14184 14185 14186
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.total_iops_sec) < 0)
14187 14188 14189
                goto endjob;
            break;
        case 4:
14190 14191 14192 14193
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.read_iops_sec) < 0)
14194 14195 14196
                goto endjob;
            break;
        case 5:
14197 14198 14199 14200
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.write_iops_sec) < 0)
14201 14202 14203 14204 14205 14206 14207 14208 14209 14210 14211 14212 14213 14214 14215 14216 14217 14218
                goto endjob;
            break;
        default:
            break;
        }
    }

    if (*nparams > QEMU_NB_BLOCK_IO_TUNE_PARAM)
        *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM;
    ret = 0;

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    VIR_FREE(device);
    if (vm)
14219
        virObjectUnlock(vm);
14220
    virObjectUnref(caps);
14221 14222
    return ret;
}
14223

14224 14225 14226 14227 14228 14229
static int
qemuDomainGetDiskErrors(virDomainPtr dom,
                        virDomainDiskErrorPtr errors,
                        unsigned int nerrors,
                        unsigned int flags)
{
14230
    virQEMUDriverPtr driver = dom->conn->privateData;
14231 14232 14233 14234 14235 14236 14237 14238 14239
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
    virHashTablePtr table = NULL;
    int ret = -1;
    int i;
    int n = 0;

    virCheckFlags(0, -1);

14240
    if (!(vm = qemuDomObjFromDomain(dom)))
14241 14242 14243 14244 14245 14246 14247 14248
        goto cleanup;

    priv = vm->privateData;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
14249 14250
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
14251 14252 14253 14254 14255 14256 14257 14258 14259 14260 14261 14262 14263 14264 14265 14266 14267 14268 14269 14270 14271 14272 14273 14274 14275 14276 14277 14278 14279 14280 14281 14282 14283 14284 14285 14286 14287 14288 14289 14290
        goto endjob;
    }

    if (!errors) {
        ret = vm->def->ndisks;
        goto endjob;
    }

    qemuDomainObjEnterMonitor(driver, vm);
    table = qemuMonitorGetBlockInfo(priv->mon);
    qemuDomainObjExitMonitor(driver, vm);
    if (!table)
        goto endjob;

    for (i = n = 0; i < vm->def->ndisks; i++) {
        struct qemuDomainDiskInfo *info;
        virDomainDiskDefPtr disk = vm->def->disks[i];

        if ((info = virHashLookup(table, disk->info.alias)) &&
            info->io_status != VIR_DOMAIN_DISK_ERROR_NONE) {
            if (n == nerrors)
                break;

            if (!(errors[n].disk = strdup(disk->dst))) {
                virReportOOMError();
                goto endjob;
            }
            errors[n].error = info->io_status;
            n++;
        }
    }

    ret = n;

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    if (vm)
14291
        virObjectUnlock(vm);
14292 14293 14294 14295 14296 14297 14298 14299
    virHashFree(table);
    if (ret < 0) {
        for (i = 0; i < n; i++)
            VIR_FREE(errors[i].disk);
    }
    return ret;
}

14300 14301 14302 14303 14304 14305 14306 14307
static int
qemuDomainSetMetadata(virDomainPtr dom,
                      int type,
                      const char *metadata,
                      const char *key ATTRIBUTE_UNUSED,
                      const char *uri ATTRIBUTE_UNUSED,
                      unsigned int flags)
{
14308
    virQEMUDriverPtr driver = dom->conn->privateData;
14309 14310 14311
    virDomainObjPtr vm;
    virDomainDefPtr persistentDef;
    int ret = -1;
14312
    virQEMUDriverConfigPtr cfg = NULL;
14313
    virCapsPtr caps = NULL;
14314 14315 14316 14317

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

14318
    if (!(vm = qemuDomObjFromDomain(dom)))
14319 14320
        goto cleanup;

14321 14322
    cfg = virQEMUDriverGetConfig(driver);

14323 14324 14325
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

14326
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
14327 14328 14329 14330 14331 14332 14333 14334 14335 14336 14337 14338 14339 14340 14341 14342 14343 14344
                                        &persistentDef) < 0)
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        switch ((virDomainMetadataType) type) {
        case VIR_DOMAIN_METADATA_DESCRIPTION:
            VIR_FREE(vm->def->description);
            if (metadata &&
                !(vm->def->description = strdup(metadata)))
                goto no_memory;
            break;
        case VIR_DOMAIN_METADATA_TITLE:
            VIR_FREE(vm->def->title);
            if (metadata &&
                !(vm->def->title = strdup(metadata)))
                goto no_memory;
            break;
        case VIR_DOMAIN_METADATA_ELEMENT:
14345
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
14346
                           _("QEmu driver does not support modifying "
14347
                             "<metadata> element"));
14348 14349 14350
            goto cleanup;
            break;
        default:
14351 14352
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("unknown metadata type"));
14353 14354 14355 14356 14357 14358 14359 14360 14361 14362 14363 14364 14365 14366 14367 14368 14369 14370 14371 14372
            goto cleanup;
            break;
        }
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        switch ((virDomainMetadataType) type) {
        case VIR_DOMAIN_METADATA_DESCRIPTION:
            VIR_FREE(persistentDef->description);
            if (metadata &&
                !(persistentDef->description = strdup(metadata)))
                goto no_memory;
            break;
        case VIR_DOMAIN_METADATA_TITLE:
            VIR_FREE(persistentDef->title);
            if (metadata &&
                !(persistentDef->title = strdup(metadata)))
                goto no_memory;
            break;
        case VIR_DOMAIN_METADATA_ELEMENT:
14373
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
14374
                           _("QEMU driver does not support "
14375
                             "<metadata> element"));
14376 14377
            goto cleanup;
         default:
14378 14379
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("unknown metadata type"));
14380 14381 14382 14383
            goto cleanup;
            break;
        }

14384
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
14385 14386 14387 14388 14389 14390 14391
            goto cleanup;
    }

    ret = 0;

cleanup:
    if (vm)
14392
        virObjectUnlock(vm);
14393
    virObjectUnref(caps);
14394
    virObjectUnref(cfg);
14395 14396 14397 14398 14399 14400 14401 14402 14403 14404 14405 14406
    return ret;
no_memory:
    virReportOOMError();
    goto cleanup;
}

static char *
qemuDomainGetMetadata(virDomainPtr dom,
                      int type,
                      const char *uri ATTRIBUTE_UNUSED,
                      unsigned int flags)
{
14407
    virQEMUDriverPtr driver = dom->conn->privateData;
14408 14409 14410 14411
    virDomainObjPtr vm;
    virDomainDefPtr def;
    char *ret = NULL;
    char *field = NULL;
14412
    virCapsPtr caps = NULL;
14413 14414 14415 14416

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

14417
    if (!(vm = qemuDomObjFromDomain(dom)))
14418 14419
        goto cleanup;

14420 14421 14422
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

14423
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags, &def) < 0)
14424 14425 14426 14427 14428 14429 14430 14431 14432 14433 14434 14435 14436 14437
        goto cleanup;

    /* use correct domain definition according to flags */
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
        def = vm->def;

    switch ((virDomainMetadataType) type) {
    case VIR_DOMAIN_METADATA_DESCRIPTION:
        field = def->description;
        break;
    case VIR_DOMAIN_METADATA_TITLE:
        field = def->title;
        break;
    case VIR_DOMAIN_METADATA_ELEMENT:
14438
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
14439
                       _("QEMU driver does not support "
14440
                         "<metadata> element"));
14441 14442 14443
        goto cleanup;
        break;
    default:
14444 14445
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("unknown metadata type"));
14446 14447 14448 14449 14450
        goto cleanup;
        break;
    }

    if (!field) {
14451 14452
        virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s",
                       _("Requested metadata element is not present"));
14453 14454 14455 14456 14457 14458 14459 14460 14461 14462
        goto cleanup;
    }

    if (!(ret = strdup(field))) {
        virReportOOMError();
        goto cleanup;
    }

cleanup:
    if (vm)
14463
        virObjectUnlock(vm);
14464
    virObjectUnref(caps);
14465 14466 14467
    return ret;
}

14468 14469
/* qemuDomainGetCPUStats() with start_cpu == -1 */
static int
14470
qemuDomainGetTotalcpuStats(virDomainObjPtr vm,
14471 14472 14473 14474 14475
                           virTypedParameterPtr params,
                           int nparams)
{
    unsigned long long cpu_time;
    int ret;
14476
    qemuDomainObjPrivatePtr priv = vm->privateData;
14477 14478

    if (nparams == 0) /* return supported number of params */
E
Eric Blake 已提交
14479
        return QEMU_NB_TOTAL_CPU_STAT_PARAM;
14480
    /* entry 0 is cputime */
14481
    ret = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time);
14482 14483 14484 14485 14486
    if (ret < 0) {
        virReportSystemError(-ret, "%s", _("unable to get cpu account"));
        return -1;
    }

E
Eric Blake 已提交
14487 14488 14489 14490 14491 14492 14493 14494
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
                                VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
        return -1;

    if (nparams > 1) {
        unsigned long long user;
        unsigned long long sys;

14495
        ret = virCgroupGetCpuacctStat(priv->cgroup, &user, &sys);
E
Eric Blake 已提交
14496 14497 14498 14499 14500 14501 14502 14503 14504 14505 14506 14507 14508 14509 14510 14511 14512 14513 14514 14515
        if (ret < 0) {
            virReportSystemError(-ret, "%s", _("unable to get cpu account"));
            return -1;
        }

        if (virTypedParameterAssign(&params[1],
                                    VIR_DOMAIN_CPU_STATS_USERTIME,
                                    VIR_TYPED_PARAM_ULLONG, user) < 0)
            return -1;
        if (nparams > 2 &&
            virTypedParameterAssign(&params[2],
                                    VIR_DOMAIN_CPU_STATS_SYSTEMTIME,
                                    VIR_TYPED_PARAM_ULLONG, sys) < 0)
            return -1;

        if (nparams > QEMU_NB_TOTAL_CPU_STAT_PARAM)
            nparams = QEMU_NB_TOTAL_CPU_STAT_PARAM;
    }

    return nparams;
14516 14517
}

14518 14519 14520 14521 14522 14523 14524 14525 14526 14527 14528 14529 14530 14531 14532
/* This function gets the sums of cpu time consumed by all vcpus.
 * For example, if there are 4 physical cpus, and 2 vcpus in a domain,
 * then for each vcpu, the cpuacct.usage_percpu looks like this:
 *   t0 t1 t2 t3
 * and we have 2 groups of such data:
 *   v\p   0   1   2   3
 *   0   t00 t01 t02 t03
 *   1   t10 t11 t12 t13
 * for each pcpu, the sum is cpu time consumed by all vcpus.
 *   s0 = t00 + t10
 *   s1 = t01 + t11
 *   s2 = t02 + t12
 *   s3 = t03 + t13
 */
static int
14533
getSumVcpuPercpuStats(virDomainObjPtr vm,
14534 14535 14536 14537 14538 14539
                      unsigned long long *sum_cpu_time,
                      unsigned int num)
{
    int ret = -1;
    int i;
    char *buf = NULL;
14540
    qemuDomainObjPrivatePtr priv = vm->privateData;
14541 14542
    virCgroupPtr group_vcpu = NULL;

14543
    for (i = 0; i < priv->nvcpupids; i++) {
14544 14545 14546 14547
        char *pos;
        unsigned long long tmp;
        int j;

14548
        if (virCgroupNewVcpu(priv->cgroup, i, false, &group_vcpu) < 0) {
14549 14550
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("error accessing cgroup cpuacct for vcpu"));
14551 14552 14553
            goto cleanup;
        }

14554
        if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
14555 14556 14557 14558 14559
            goto cleanup;

        pos = buf;
        for (j = 0; j < num; j++) {
            if (virStrToLong_ull(pos, &pos, 10, &tmp) < 0) {
14560 14561
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("cpuacct parse error"));
14562 14563 14564 14565 14566 14567 14568 14569 14570 14571 14572 14573 14574 14575 14576 14577
                goto cleanup;
            }
            sum_cpu_time[j] += tmp;
        }

        virCgroupFree(&group_vcpu);
        VIR_FREE(buf);
    }

    ret = 0;
cleanup:
    virCgroupFree(&group_vcpu);
    VIR_FREE(buf);
    return ret;
}

14578
static int
14579
qemuDomainGetPercpuStats(virDomainObjPtr vm,
14580 14581 14582 14583 14584 14585
                         virTypedParameterPtr params,
                         unsigned int nparams,
                         int start_cpu,
                         unsigned int ncpus)
{
    int rv = -1;
14586
    int i, id, max_id;
14587 14588
    char *pos;
    char *buf = NULL;
14589 14590 14591 14592
    unsigned long long *sum_cpu_time = NULL;
    unsigned long long *sum_cpu_pos;
    unsigned int n = 0;
    qemuDomainObjPrivatePtr priv = vm->privateData;
14593 14594
    virTypedParameterPtr ent;
    int param_idx;
14595
    unsigned long long cpu_time;
14596 14597 14598

    /* return the number of supported params */
    if (nparams == 0 && ncpus != 0)
14599
        return QEMU_NB_PER_CPU_STAT_PARAM;
14600

14601 14602 14603
    /* To parse account file, we need to know how many cpus are present.  */
    max_id = nodeGetCPUCount();
    if (max_id < 0)
14604 14605 14606
        return rv;

    if (ncpus == 0) { /* returns max cpu ID */
14607
        rv = max_id;
14608 14609 14610 14611
        goto cleanup;
    }

    if (start_cpu > max_id) {
14612 14613 14614
        virReportError(VIR_ERR_INVALID_ARG,
                       _("start_cpu %d larger than maximum of %d"),
                       start_cpu, max_id);
14615 14616 14617 14618
        goto cleanup;
    }

    /* we get percpu cputime accounting info. */
14619
    if (virCgroupGetCpuacctPercpuUsage(priv->cgroup, &buf))
14620 14621
        goto cleanup;
    pos = buf;
14622
    memset(params, 0, nparams * ncpus);
14623

14624 14625 14626
    /* return percpu cputime in index 0 */
    param_idx = 0;

14627
    /* number of cpus to compute */
14628 14629 14630
    if (start_cpu >= max_id - ncpus)
        id = max_id - 1;
    else
14631
        id = start_cpu + ncpus - 1;
14632

14633
    for (i = 0; i <= id; i++) {
14634
        if (virStrToLong_ull(pos, &pos, 10, &cpu_time) < 0) {
14635
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
14636
                           _("cpuacct parse error"));
14637
            goto cleanup;
14638 14639
        } else {
            n++;
14640 14641 14642
        }
        if (i < start_cpu)
            continue;
14643
        ent = &params[(i - start_cpu) * nparams + param_idx];
E
Eric Blake 已提交
14644 14645 14646
        if (virTypedParameterAssign(ent, VIR_DOMAIN_CPU_STATS_CPUTIME,
                                    VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
            goto cleanup;
14647
    }
14648 14649 14650 14651 14652 14653 14654 14655 14656 14657 14658

    /* return percpu vcputime in index 1 */
    if (++param_idx >= nparams) {
        rv = nparams;
        goto cleanup;
    }

    if (VIR_ALLOC_N(sum_cpu_time, n) < 0) {
        virReportOOMError();
        goto cleanup;
    }
14659
    if (getSumVcpuPercpuStats(vm, sum_cpu_time, n) < 0)
14660 14661 14662
        goto cleanup;

    sum_cpu_pos = sum_cpu_time;
14663
    for (i = 0; i <= id; i++) {
14664
        cpu_time = *(sum_cpu_pos++);
14665 14666 14667 14668 14669 14670 14671 14672 14673 14674
        if (i < start_cpu)
            continue;
        if (virTypedParameterAssign(&params[(i - start_cpu) * nparams +
                                            param_idx],
                                    VIR_DOMAIN_CPU_STATS_VCPUTIME,
                                    VIR_TYPED_PARAM_ULLONG,
                                    cpu_time) < 0)
            goto cleanup;
    }

14675 14676
    rv = param_idx + 1;
cleanup:
14677
    VIR_FREE(sum_cpu_time);
14678 14679 14680 14681 14682 14683 14684
    VIR_FREE(buf);
    return rv;
}


static int
qemuDomainGetCPUStats(virDomainPtr domain,
14685 14686 14687 14688 14689
                      virTypedParameterPtr params,
                      unsigned int nparams,
                      int start_cpu,
                      unsigned int ncpus,
                      unsigned int flags)
14690 14691 14692 14693
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    bool isActive;
14694
    qemuDomainObjPrivatePtr priv;
14695 14696 14697

    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

14698 14699
    if (!(vm = qemuDomObjFromDomain(domain)))
        return -1;
14700

14701 14702
    priv = vm->privateData;

14703 14704
    isActive = virDomainObjIsActive(vm);
    if (!isActive) {
14705 14706
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
14707 14708 14709
        goto cleanup;
    }

14710
    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) {
14711 14712
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cgroup CPUACCT controller is not mounted"));
14713 14714 14715 14716
        goto cleanup;
    }

    if (start_cpu == -1)
14717
        ret = qemuDomainGetTotalcpuStats(vm, params, nparams);
14718
    else
14719
        ret = qemuDomainGetPercpuStats(vm, params, nparams,
14720 14721 14722
                                       start_cpu, ncpus);
cleanup:
    if (vm)
14723
        virObjectUnlock(vm);
14724 14725 14726
    return ret;
}

14727 14728 14729 14730 14731 14732
static int
qemuDomainPMSuspendForDuration(virDomainPtr dom,
                               unsigned int target,
                               unsigned long long duration,
                               unsigned int flags)
{
14733
    virQEMUDriverPtr driver = dom->conn->privateData;
14734 14735 14736 14737 14738 14739 14740
    qemuDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    if (duration) {
14741 14742
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Duration not supported. Use 0 for now"));
14743 14744 14745 14746 14747 14748
        return -1;
    }

    if (!(target == VIR_NODE_SUSPEND_TARGET_MEM ||
          target == VIR_NODE_SUSPEND_TARGET_DISK ||
          target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
14749 14750 14751
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Unknown suspend target: %u"),
                       target);
14752 14753 14754
        return -1;
    }

14755
    if (!(vm = qemuDomObjFromDomain(dom)))
14756 14757 14758 14759
        goto cleanup;

    priv = vm->privateData;

14760
    if (!virDomainObjIsActive(vm)) {
14761 14762
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
14763 14764 14765
        goto cleanup;
    }

14766
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_WAKEUP) &&
14767 14768
        (target == VIR_NODE_SUSPEND_TARGET_MEM ||
         target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
14769 14770 14771
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Unable to suspend domain due to "
                         "missing system_wakeup monitor command"));
O
Osier Yang 已提交
14772
        goto cleanup;
14773 14774
    }

14775 14776 14777 14778 14779 14780 14781 14782 14783 14784 14785 14786 14787 14788 14789 14790 14791
    if (vm->def->pm.s3 || vm->def->pm.s4) {
        if (vm->def->pm.s3 == VIR_DOMAIN_PM_STATE_DISABLED &&
            (target == VIR_NODE_SUSPEND_TARGET_MEM ||
             target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("S3 state is disabled for this domain"));
            goto cleanup;
        }

        if (vm->def->pm.s4 == VIR_DOMAIN_PM_STATE_DISABLED &&
            target == VIR_NODE_SUSPEND_TARGET_DISK) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("S4 state is disabled for this domain"));
            goto cleanup;
        }
    }

14792
    if (priv->agentError) {
14793 14794 14795
        virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                       _("QEMU guest agent is not "
                         "available due to an error"));
14796 14797 14798 14799
        goto cleanup;
    }

    if (!priv->agent) {
14800 14801
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("QEMU guest agent is not configured"));
14802 14803 14804 14805 14806 14807 14808
        goto cleanup;
    }

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
14809 14810
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
14811 14812 14813
        goto endjob;
    }

14814
    qemuDomainObjEnterAgent(vm);
14815
    ret = qemuAgentSuspend(priv->agent, target);
14816
    qemuDomainObjExitAgent(vm);
14817 14818 14819 14820 14821 14822 14823

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    if (vm)
14824
        virObjectUnlock(vm);
14825 14826 14827
    return ret;
}

14828 14829 14830 14831
static int
qemuDomainPMWakeup(virDomainPtr dom,
                   unsigned int flags)
{
14832
    virQEMUDriverPtr driver = dom->conn->privateData;
14833 14834 14835 14836 14837 14838
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

14839
    if (!(vm = qemuDomObjFromDomain(dom)))
14840 14841 14842 14843 14844 14845
        goto cleanup;

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
14846 14847
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
14848 14849 14850 14851 14852
        goto endjob;
    }

    priv = vm->privateData;

14853
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_WAKEUP)) {
14854 14855 14856
       virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                      _("Unable to wake up domain due to "
                        "missing system_wakeup monitor command"));
14857 14858 14859 14860 14861 14862 14863 14864 14865 14866 14867 14868 14869
       goto endjob;
    }

    qemuDomainObjEnterMonitor(driver, vm);
    ret = qemuMonitorSystemWakeup(priv->mon);
    qemuDomainObjExitMonitor(driver, vm);

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    if (vm)
14870
        virObjectUnlock(vm);
14871 14872 14873
    return ret;
}

14874
static int
14875 14876 14877
qemuConnectListAllDomains(virConnectPtr conn,
                          virDomainPtr **domains,
                          unsigned int flags)
14878
{
14879
    virQEMUDriverPtr driver = conn->privateData;
14880 14881
    int ret = -1;

O
Osier Yang 已提交
14882
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
14883

14884
    ret = virDomainObjListExport(driver->domains, conn, domains, flags);
14885 14886 14887 14888

    return ret;
}

M
MATSUDA Daiki 已提交
14889
static char *
14890 14891 14892 14893
qemuDomainQemuAgentCommand(virDomainPtr domain,
                           const char *cmd,
                           int timeout,
                           unsigned int flags)
M
MATSUDA Daiki 已提交
14894
{
14895
    virQEMUDriverPtr driver = domain->conn->privateData;
M
MATSUDA Daiki 已提交
14896 14897 14898 14899 14900 14901 14902
    virDomainObjPtr vm;
    int ret = -1;
    char *result = NULL;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, NULL);

14903
    if (!(vm = qemuDomObjFromDomain(domain)))
M
MATSUDA Daiki 已提交
14904 14905 14906 14907 14908 14909 14910 14911 14912 14913 14914
        goto cleanup;

    priv = vm->privateData;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    if (priv->agentError) {
14915 14916 14917
        virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                       _("QEMU guest agent is not "
                         "available due to an error"));
M
MATSUDA Daiki 已提交
14918 14919 14920 14921 14922 14923 14924 14925 14926 14927 14928 14929 14930 14931 14932 14933 14934 14935
        goto cleanup;
    }

    if (!priv->agent) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("QEMU guest agent is not configured"));
        goto cleanup;
    }

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto endjob;
    }

14936
    qemuDomainObjEnterAgent(vm);
M
MATSUDA Daiki 已提交
14937
    ret = qemuAgentArbitraryCommand(priv->agent, cmd, &result, timeout);
14938
    qemuDomainObjExitAgent(vm);
M
MATSUDA Daiki 已提交
14939 14940 14941 14942 14943 14944 14945 14946 14947 14948 14949 14950 14951
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Failed to execute agent command"));
        goto endjob;
    }

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
    }

cleanup:
    if (vm)
14952
        virObjectUnlock(vm);
M
MATSUDA Daiki 已提交
14953 14954 14955
    return result;
}

M
Michal Privoznik 已提交
14956 14957 14958 14959 14960 14961
static int
qemuDomainFSTrim(virDomainPtr dom,
                 const char *mountPoint,
                 unsigned long long minimum,
                 unsigned int flags)
{
14962
    virQEMUDriverPtr driver = dom->conn->privateData;
M
Michal Privoznik 已提交
14963 14964 14965 14966 14967 14968 14969 14970 14971 14972 14973 14974 14975 14976 14977 14978 14979 14980 14981 14982 14983 14984 14985 14986 14987 14988 14989 14990 14991 14992 14993 14994 14995 14996 14997 14998 14999 15000 15001 15002 15003 15004 15005 15006 15007 15008
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

    if (mountPoint) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Specifying mount point "
                         "is not supported for now"));
        return -1;
    }

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    priv = vm->privateData;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    if (!priv->agent) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("QEMU guest agent is not configured"));
        goto cleanup;
    }

    if (priv->agentError) {
        virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                       _("QEMU guest agent is not "
                         "available due to an error"));
        goto cleanup;
    }

    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto endjob;
    }

15009
    qemuDomainObjEnterAgent(vm);
M
Michal Privoznik 已提交
15010
    ret = qemuAgentFSTrim(priv->agent, minimum);
15011
    qemuDomainObjExitAgent(vm);
M
Michal Privoznik 已提交
15012 15013 15014 15015 15016 15017 15018

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    if (vm)
15019
        virObjectUnlock(vm);
M
Michal Privoznik 已提交
15020 15021 15022
    return ret;
}

15023 15024 15025 15026 15027 15028 15029 15030 15031 15032 15033 15034 15035 15036 15037 15038 15039 15040 15041 15042 15043 15044 15045 15046 15047 15048 15049 15050 15051 15052 15053 15054 15055 15056 15057 15058 15059 15060 15061 15062 15063 15064 15065 15066 15067 15068 15069 15070 15071 15072 15073 15074 15075 15076 15077 15078 15079 15080 15081 15082 15083 15084 15085 15086 15087 15088 15089 15090 15091 15092 15093 15094 15095 15096 15097 15098 15099

static int
qemuNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
                virNodeInfoPtr nodeinfo)
{
    return nodeGetInfo(nodeinfo);
}


static int
qemuNodeGetCPUStats(virConnectPtr conn ATTRIBUTE_UNUSED,
                    int cpuNum,
                    virNodeCPUStatsPtr params,
                    int *nparams,
                    unsigned int flags)
{
    return nodeGetCPUStats(cpuNum, params, nparams, flags);
}


static int
qemuNodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED,
                       int cellNum,
                       virNodeMemoryStatsPtr params,
                       int *nparams,
                       unsigned int flags)
{
    return nodeGetMemoryStats(cellNum, params, nparams, flags);
}


static int
qemuNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
                           unsigned long long *freeMems,
                           int startCell,
                           int maxCells)
{
    return nodeGetCellsFreeMemory(freeMems, startCell, maxCells);
}


static unsigned long long
qemuNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return nodeGetFreeMemory();
}


static int
qemuNodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
                            virTypedParameterPtr params,
                            int *nparams,
                            unsigned int flags)
{
    return nodeGetMemoryParameters(params, nparams, flags);
}


static int
qemuNodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
                            virTypedParameterPtr params,
                            int nparams,
                            unsigned int flags)
{
    return nodeSetMemoryParameters(params, nparams, flags);
}


static int
qemuNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
                  unsigned char **cpumap,
                  unsigned int *online,
                  unsigned int flags)
{
    return nodeGetCPUMap(cpumap, online, flags);
}

15100 15101 15102 15103 15104 15105 15106 15107 15108 15109 15110

static int
qemuNodeSuspendForDuration(virConnectPtr conn ATTRIBUTE_UNUSED,
                           unsigned int target,
                           unsigned long long duration,
                           unsigned int flags)
{
    return nodeSuspendForDuration(target, duration, flags);
}


15111
static virDriver qemuDriver = {
15112
    .no = VIR_DRV_QEMU,
15113
    .name = QEMU_DRIVER_NAME,
15114 15115 15116 15117 15118
    .connectOpen = qemuConnectOpen, /* 0.2.0 */
    .connectClose = qemuConnectClose, /* 0.2.0 */
    .connectSupportsFeature = qemuConnectSupportsFeature, /* 0.5.0 */
    .connectGetType = qemuConnectGetType, /* 0.2.0 */
    .connectGetVersion = qemuConnectGetVersion, /* 0.2.0 */
15119
    .connectGetHostname = qemuConnectGetHostname, /* 0.3.3 */
15120 15121
    .connectGetSysinfo = qemuConnectGetSysinfo, /* 0.8.8 */
    .connectGetMaxVcpus = qemuConnectGetMaxVcpus, /* 0.2.1 */
15122
    .nodeGetInfo = qemuNodeGetInfo, /* 0.2.0 */
15123 15124 15125 15126 15127
    .connectGetCapabilities = qemuConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = qemuConnectListDomains, /* 0.2.0 */
    .connectNumOfDomains = qemuConnectNumOfDomains, /* 0.2.0 */
    .connectListAllDomains = qemuConnectListAllDomains, /* 0.9.13 */
    .domainCreateXML = qemuDomainCreateXML, /* 0.2.0 */
15128 15129 15130 15131 15132
    .domainLookupByID = qemuDomainLookupByID, /* 0.2.0 */
    .domainLookupByUUID = qemuDomainLookupByUUID, /* 0.2.0 */
    .domainLookupByName = qemuDomainLookupByName, /* 0.2.0 */
    .domainSuspend = qemuDomainSuspend, /* 0.2.0 */
    .domainResume = qemuDomainResume, /* 0.2.0 */
15133
    .domainShutdown = qemuDomainShutdown, /* 0.2.0 */
15134
    .domainShutdownFlags = qemuDomainShutdownFlags, /* 0.9.10 */
15135
    .domainReboot = qemuDomainReboot, /* 0.9.3 */
15136
    .domainReset = qemuDomainReset, /* 0.9.7 */
15137 15138
    .domainDestroy = qemuDomainDestroy, /* 0.2.0 */
    .domainDestroyFlags = qemuDomainDestroyFlags, /* 0.9.4 */
15139
    .domainGetOSType = qemuDomainGetOSType, /* 0.2.2 */
15140
    .domainGetMaxMemory = qemuDomainGetMaxMemory, /* 0.4.2 */
15141 15142 15143
    .domainSetMaxMemory = qemuDomainSetMaxMemory, /* 0.4.2 */
    .domainSetMemory = qemuDomainSetMemory, /* 0.4.2 */
    .domainSetMemoryFlags = qemuDomainSetMemoryFlags, /* 0.9.0 */
15144 15145 15146 15147
    .domainSetMemoryParameters = qemuDomainSetMemoryParameters, /* 0.8.5 */
    .domainGetMemoryParameters = qemuDomainGetMemoryParameters, /* 0.8.5 */
    .domainSetBlkioParameters = qemuDomainSetBlkioParameters, /* 0.9.0 */
    .domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */
15148
    .domainGetInfo = qemuDomainGetInfo, /* 0.2.0 */
15149
    .domainGetState = qemuDomainGetState, /* 0.9.2 */
15150
    .domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */
15151 15152
    .domainSave = qemuDomainSave, /* 0.2.0 */
    .domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */
15153
    .domainRestore = qemuDomainRestore, /* 0.2.0 */
15154
    .domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */
15155 15156
    .domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */
    .domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */
15157
    .domainCoreDump = qemuDomainCoreDump, /* 0.7.0 */
15158
    .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */
15159 15160
    .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */
    .domainSetVcpusFlags = qemuDomainSetVcpusFlags, /* 0.8.5 */
15161 15162 15163 15164 15165 15166 15167 15168 15169
    .domainGetVcpusFlags = qemuDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = qemuDomainPinVcpu, /* 0.4.4 */
    .domainPinVcpuFlags = qemuDomainPinVcpuFlags, /* 0.9.3 */
    .domainGetVcpuPinInfo = qemuDomainGetVcpuPinInfo, /* 0.9.3 */
    .domainPinEmulator = qemuDomainPinEmulator, /* 0.10.0 */
    .domainGetEmulatorPinInfo = qemuDomainGetEmulatorPinInfo, /* 0.10.0 */
    .domainGetVcpus = qemuDomainGetVcpus, /* 0.4.4 */
    .domainGetMaxVcpus = qemuDomainGetMaxVcpus, /* 0.4.4 */
    .domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
M
Marcelo Cerri 已提交
15170
    .domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
15171
    .nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
15172
    .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */
15173 15174 15175 15176 15177 15178 15179
    .connectDomainXMLFromNative = qemuConnectDomainXMLFromNative, /* 0.6.4 */
    .connectDomainXMLToNative = qemuConnectDomainXMLToNative, /* 0.6.4 */
    .connectListDefinedDomains = qemuConnectListDefinedDomains, /* 0.2.0 */
    .connectNumOfDefinedDomains = qemuConnectNumOfDefinedDomains, /* 0.2.0 */
    .domainCreate = qemuDomainCreate, /* 0.2.0 */
    .domainCreateWithFlags = qemuDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = qemuDomainDefineXML, /* 0.2.0 */
15180
    .domainUndefine = qemuDomainUndefine, /* 0.2.0 */
15181
    .domainUndefineFlags = qemuDomainUndefineFlags, /* 0.9.4 */
15182 15183 15184 15185 15186
    .domainAttachDevice = qemuDomainAttachDevice, /* 0.4.1 */
    .domainAttachDeviceFlags = qemuDomainAttachDeviceFlags, /* 0.7.7 */
    .domainDetachDevice = qemuDomainDetachDevice, /* 0.5.0 */
    .domainDetachDeviceFlags = qemuDomainDetachDeviceFlags, /* 0.7.7 */
    .domainUpdateDeviceFlags = qemuDomainUpdateDeviceFlags, /* 0.8.0 */
15187 15188
    .domainGetAutostart = qemuDomainGetAutostart, /* 0.2.1 */
    .domainSetAutostart = qemuDomainSetAutostart, /* 0.2.1 */
15189 15190 15191 15192 15193
    .domainGetSchedulerType = qemuDomainGetSchedulerType, /* 0.7.0 */
    .domainGetSchedulerParameters = qemuDomainGetSchedulerParameters, /* 0.7.0 */
    .domainGetSchedulerParametersFlags = qemuDomainGetSchedulerParametersFlags, /* 0.9.2 */
    .domainSetSchedulerParameters = qemuDomainSetSchedulerParameters, /* 0.7.0 */
    .domainSetSchedulerParametersFlags = qemuDomainSetSchedulerParametersFlags, /* 0.9.2 */
15194
    .domainMigratePerform = qemuDomainMigratePerform, /* 0.5.0 */
15195
    .domainBlockResize = qemuDomainBlockResize, /* 0.9.8 */
15196 15197
    .domainBlockStats = qemuDomainBlockStats, /* 0.4.1 */
    .domainBlockStatsFlags = qemuDomainBlockStatsFlags, /* 0.9.5 */
15198 15199 15200 15201
    .domainInterfaceStats = qemuDomainInterfaceStats, /* 0.4.1 */
    .domainMemoryStats = qemuDomainMemoryStats, /* 0.7.5 */
    .domainBlockPeek = qemuDomainBlockPeek, /* 0.4.4 */
    .domainMemoryPeek = qemuDomainMemoryPeek, /* 0.4.4 */
15202
    .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
15203 15204 15205 15206
    .nodeGetCPUStats = qemuNodeGetCPUStats, /* 0.9.3 */
    .nodeGetMemoryStats = qemuNodeGetMemoryStats, /* 0.9.3 */
    .nodeGetCellsFreeMemory = qemuNodeGetCellsFreeMemory, /* 0.4.4 */
    .nodeGetFreeMemory = qemuNodeGetFreeMemory, /* 0.4.4 */
15207 15208
    .connectDomainEventRegister = qemuConnectDomainEventRegister, /* 0.5.0 */
    .connectDomainEventDeregister = qemuConnectDomainEventDeregister, /* 0.5.0 */
15209 15210 15211
    .domainMigratePrepare2 = qemuDomainMigratePrepare2, /* 0.5.0 */
    .domainMigrateFinish2 = qemuDomainMigrateFinish2, /* 0.5.0 */
    .nodeDeviceDettach = qemuNodeDeviceDettach, /* 0.6.1 */
15212
    .nodeDeviceDetachFlags = qemuNodeDeviceDetachFlags, /* 1.0.5 */
15213 15214 15215
    .nodeDeviceReAttach = qemuNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = qemuNodeDeviceReset, /* 0.6.1 */
    .domainMigratePrepareTunnel = qemuDomainMigratePrepareTunnel, /* 0.7.2 */
15216 15217
    .connectIsEncrypted = qemuConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = qemuConnectIsSecure, /* 0.7.3 */
15218 15219 15220
    .domainIsActive = qemuDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = qemuDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = qemuDomainIsUpdated, /* 0.8.6 */
15221 15222
    .connectCompareCPU = qemuConnectCompareCPU, /* 0.7.5 */
    .connectBaselineCPU = qemuConnectBaselineCPU, /* 0.7.7 */
15223
    .domainGetJobInfo = qemuDomainGetJobInfo, /* 0.7.7 */
15224
    .domainGetJobStats = qemuDomainGetJobStats, /* 1.0.3 */
15225 15226
    .domainAbortJob = qemuDomainAbortJob, /* 0.7.7 */
    .domainMigrateSetMaxDowntime = qemuDomainMigrateSetMaxDowntime, /* 0.8.0 */
15227 15228
    .domainMigrateGetCompressionCache = qemuDomainMigrateGetCompressionCache, /* 1.0.3 */
    .domainMigrateSetCompressionCache = qemuDomainMigrateSetCompressionCache, /* 1.0.3 */
15229
    .domainMigrateSetMaxSpeed = qemuDomainMigrateSetMaxSpeed, /* 0.9.0 */
15230
    .domainMigrateGetMaxSpeed = qemuDomainMigrateGetMaxSpeed, /* 0.9.5 */
15231 15232
    .connectDomainEventRegisterAny = qemuConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = qemuConnectDomainEventDeregisterAny, /* 0.8.0 */
15233 15234 15235 15236 15237 15238 15239
    .domainManagedSave = qemuDomainManagedSave, /* 0.8.0 */
    .domainHasManagedSaveImage = qemuDomainHasManagedSaveImage, /* 0.8.0 */
    .domainManagedSaveRemove = qemuDomainManagedSaveRemove, /* 0.8.0 */
    .domainSnapshotCreateXML = qemuDomainSnapshotCreateXML, /* 0.8.0 */
    .domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */
    .domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */
    .domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */
15240
    .domainListAllSnapshots = qemuDomainListAllSnapshots, /* 0.9.13 */
15241 15242
    .domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */
    .domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */
15243
    .domainSnapshotListAllChildren = qemuDomainSnapshotListAllChildren, /* 0.9.13 */
15244 15245
    .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */
    .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */
15246
    .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */
15247
    .domainSnapshotCurrent = qemuDomainSnapshotCurrent, /* 0.8.0 */
15248 15249
    .domainSnapshotIsCurrent = qemuDomainSnapshotIsCurrent, /* 0.9.13 */
    .domainSnapshotHasMetadata = qemuDomainSnapshotHasMetadata, /* 0.9.13 */
15250 15251
    .domainRevertToSnapshot = qemuDomainRevertToSnapshot, /* 0.8.0 */
    .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
15252 15253 15254
    .domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
    .domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */
    .domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
15255
    .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
15256
    .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
15257
    .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
15258 15259 15260 15261 15262 15263
    .domainMigrateBegin3 = qemuDomainMigrateBegin3, /* 0.9.2 */
    .domainMigratePrepare3 = qemuDomainMigratePrepare3, /* 0.9.2 */
    .domainMigratePrepareTunnel3 = qemuDomainMigratePrepareTunnel3, /* 0.9.2 */
    .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
    .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
    .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
15264
    .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
15265 15266 15267 15268
    .domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
    .domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
    .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
    .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
15269
    .domainBlockRebase = qemuDomainBlockRebase, /* 0.9.10 */
15270
    .domainBlockCommit = qemuDomainBlockCommit, /* 1.0.0 */
15271
    .connectIsAlive = qemuConnectIsAlive, /* 0.9.8 */
15272
    .nodeSuspendForDuration = qemuNodeSuspendForDuration, /* 0.9.8 */
15273 15274
    .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
    .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
15275 15276
    .domainSetNumaParameters = qemuDomainSetNumaParameters, /* 0.9.9 */
    .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
15277 15278
    .domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
    .domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
15279
    .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
15280 15281
    .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */
    .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */
15282
    .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
15283
    .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
15284
    .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
15285 15286 15287
    .nodeGetMemoryParameters = qemuNodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = qemuNodeSetMemoryParameters, /* 0.10.2 */
    .nodeGetCPUMap = qemuNodeGetCPUMap, /* 1.0.0 */
M
Michal Privoznik 已提交
15288
    .domainFSTrim = qemuDomainFSTrim, /* 1.0.1 */
15289
    .domainOpenChannel = qemuDomainOpenChannel, /* 1.0.2 */
15290 15291 15292
};


15293
static virStateDriver qemuStateDriver = {
15294
    .name = "QEMU",
15295 15296 15297 15298
    .stateInitialize = qemuStateInitialize,
    .stateCleanup = qemuStateCleanup,
    .stateReload = qemuStateReload,
    .stateStop = qemuStateStop,
15299
};
15300

15301
int qemuRegister(void) {
15302 15303 15304 15305
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}