qemu_driver.c 469.9 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 "virutil.h"
65
#include "nodeinfo.h"
66
#include "virstatslinux.h"
67
#include "capabilities.h"
68
#include "viralloc.h"
69
#include "viruuid.h"
70
#include "domain_conf.h"
71
#include "domain_audit.h"
72
#include "node_device_conf.h"
73
#include "virpci.h"
74
#include "virusb.h"
75
#include "virprocess.h"
C
Chris Lalancette 已提交
76
#include "libvirt_internal.h"
77
#include "virxml.h"
78
#include "cpu/cpu.h"
79
#include "virsysinfo.h"
80
#include "domain_nwfilter.h"
81
#include "nwfilter_conf.h"
82
#include "virhook.h"
83
#include "virstoragefile.h"
E
Eric Blake 已提交
84
#include "virfile.h"
85
#include "fdstream.h"
86
#include "configmake.h"
87
#include "virthreadpool.h"
88
#include "locking/lock_manager.h"
89
#include "locking/domain_lock.h"
90
#include "virkeycode.h"
91
#include "virnodesuspend.h"
92
#include "virtime.h"
93
#include "virtypedparam.h"
94
#include "virbitmap.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 qemuShutdown(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
 * qemuStartup:
545 546 547
 *
 * Initialization function for the QEmu daemon
 */
548
static int
549 550 551 552
qemuStartup(bool privileged,
            virStateInhibitCallback callback,
            void *opaque)
{
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
    if (qemuSecurityInit(qemu_driver) < 0)
        goto error;
668

669
    if ((qemu_driver->activePciHostdevs = virPCIDeviceListNew()) == NULL)
670
        goto error;
671

672
    if ((qemu_driver->activeUsbHostdevs = virUSBDeviceListNew()) == NULL)
673 674
        goto error;

675
    if ((qemu_driver->inactivePciHostdevs = virPCIDeviceListNew()) == NULL)
676 677
        goto error;

678
    if (!(qemu_driver->sharedDisks = virHashCreate(30, qemuSharedDiskEntryFree)))
679 680
        goto error;

681
    if (privileged) {
682
        if (chown(cfg->libDir, cfg->user, cfg->group) < 0) {
683 684
            virReportSystemError(errno,
                                 _("unable to set ownership of '%s' to user %d:%d"),
685
                                 cfg->libDir, cfg->user, cfg->group);
686
            goto error;
687
        }
688
        if (chown(cfg->cacheDir, cfg->user, cfg->group) < 0) {
689
            virReportSystemError(errno,
690
                                 _("unable to set ownership of '%s' to %d:%d"),
691
                                 cfg->cacheDir, cfg->user, cfg->group);
692
            goto error;
693
        }
694
        if (chown(cfg->saveDir, cfg->user, cfg->group) < 0) {
695 696
            virReportSystemError(errno,
                                 _("unable to set ownership of '%s' to %d:%d"),
697
                                 cfg->saveDir, cfg->user, cfg->group);
698 699
            goto error;
        }
700
        if (chown(cfg->snapshotDir, cfg->user, cfg->group) < 0) {
701 702
            virReportSystemError(errno,
                                 _("unable to set ownership of '%s' to %d:%d"),
703
                                 cfg->snapshotDir, cfg->user, cfg->group);
704
            goto error;
705
        }
706 707
        run_uid = cfg->user;
        run_gid = cfg->group;
708
    }
709

710
    qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
711 712
                                                     run_uid,
                                                     run_gid);
713
    if (!qemu_driver->qemuCapsCache)
714 715
        goto error;

716
    if ((qemu_driver->caps = virQEMUDriverCreateCapabilities(qemu_driver)) == NULL)
717 718
        goto error;

719
    if (!(qemu_driver->xmlopt = virQEMUDriverCreateXMLConf(qemu_driver)))
720 721
        goto error;

722 723 724 725 726 727
    /* 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
728
     */
729 730
    if (cfg->hugetlbfsMount &&
        cfg->hugetlbfsMount[0] == '/') {
731
        if (virAsprintf(&membase, "%s/libvirt",
732
                        cfg->hugetlbfsMount) < 0 ||
733
            virAsprintf(&mempath, "%s/qemu", membase) < 0)
734
            goto out_of_memory;
735

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

754
        cfg->hugepagePath = mempath;
755
    }
756

757
    if (!(qemu_driver->closeCallbacks = virQEMUCloseCallbacksNew()))
758 759
        goto error;

760
    /* Get all the running persistent or transient configs first */
761
    if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
762 763
                                       cfg->stateDir,
                                       NULL, 1,
764
                                       qemu_driver->caps,
765
                                       qemu_driver->xmlopt,
766
                                       QEMU_EXPECTED_VIRT_TYPES,
767
                                       NULL, NULL) < 0)
768
        goto error;
769

770 771 772
    /* find the maximum ID from active and transient configs to initialize
     * the driver with. This is to avoid race between autostart and reconnect
     * threads */
773 774 775
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainFindMaxID,
                            &qemu_driver->nextvmid);
776

777 778 779
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainNetsRestart,
                            NULL);
780

781
    conn = virConnectOpen(cfg->uri);
782

783
    qemuProcessReconnectAll(conn, qemu_driver);
784

785
    /* Then inactive persistent configs */
786
    if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
787 788
                                       cfg->configDir,
                                       cfg->autostartDir, 0,
789
                                       qemu_driver->caps,
790
                                       qemu_driver->xmlopt,
791
                                       QEMU_EXPECTED_VIRT_TYPES,
792
                                       NULL, NULL) < 0)
793
        goto error;
794

795

796 797 798
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainSnapshotLoad,
                            cfg->snapshotDir);
799

800 801 802
    virDomainObjListForEach(qemu_driver->domains,
                            qemuDomainManagedSaveLoad,
                            qemu_driver);
803

804
    qemu_driver->workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver);
805 806
    if (!qemu_driver->workerPool)
        goto error;
807

808 809
    qemuAutostartDomains(qemu_driver);

810 811
    if (conn)
        virConnectClose(conn);
812

813
    virNWFilterRegisterCallbackDriver(&qemuCallbackDriver);
814
    return 0;
815

816 817 818 819 820 821
out_of_memory:
    virReportOOMError();
error:
    if (conn)
        virConnectClose(conn);
    VIR_FREE(driverConf);
822 823
    VIR_FREE(membase);
    VIR_FREE(mempath);
824
    qemuShutdown();
825
    return -1;
826 827
}

828
static void qemuNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
829
{
830
    virQEMUDriverPtr driver = opaque;
831

832 833 834 835 836 837 838
    if (newVM) {
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
        if (event)
            qemuDomainEventQueue(driver, event);
E
Eric Blake 已提交
839
    }
840
}
E
Eric Blake 已提交
841

842
/**
843
 * qemuReload:
844 845 846 847 848
 *
 * Function to restart the QEmu daemon, it will recheck the configuration
 * files and update its state and the networking
 */
static int
849
qemuReload(void) {
850 851
    virQEMUDriverConfigPtr cfg = NULL;
    virCapsPtr caps = NULL;
852

853 854
    if (!qemu_driver)
        return 0;
855

856 857 858
    if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
        goto cleanup;

859
    cfg = virQEMUDriverGetConfig(qemu_driver);
860 861
    virDomainObjListLoadAllConfigs(qemu_driver->domains,
                                   cfg->configDir,
862 863 864
                                   cfg->autostartDir, 0,
                                   caps, qemu_driver->xmlopt,
                                   QEMU_EXPECTED_VIRT_TYPES,
865
                                   qemuNotifyLoadDomain, qemu_driver);
866
cleanup:
867
    virObjectUnref(cfg);
868
    virObjectUnref(caps);
869 870
    return 0;
}
S
Stefan Berger 已提交
871

872 873 874 875 876 877 878 879 880 881 882

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

890 891
    if (!(conn = virConnectOpen(cfg->uri)))
        goto cleanup;
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926

    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. */
    for (i = 0 ; i < numDomains ; i++) {
        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 */
    for (i = 0 ; i < numDomains ; i++)
        if (virDomainManagedSave(domains[i], flags[i]) < 0)
            ret = -1;

 cleanup:
    for (i = 0 ; i < numDomains ; i++)
        virDomainFree(domains[i]);
    VIR_FREE(domains);
    VIR_FREE(flags);
927 928 929
    if (conn)
        virConnectClose(conn);
    virObjectUnref(cfg);
930 931 932 933

    return ret;
}

934
/**
935
 * qemuShutdown:
936 937 938 939
 *
 * Shutdown the QEmu daemon, it will stop all active domains and networks
 */
static int
940
qemuShutdown(void) {
941 942
    if (!qemu_driver)
        return -1;
943

944
    virNWFilterUnRegisterCallbackDriver(&qemuCallbackDriver);
945
    virObjectUnref(qemu_driver->config);
946 947 948
    virObjectUnref(qemu_driver->activePciHostdevs);
    virObjectUnref(qemu_driver->inactivePciHostdevs);
    virObjectUnref(qemu_driver->activeUsbHostdevs);
949
    virHashFree(qemu_driver->sharedDisks);
950
    virObjectUnref(qemu_driver->caps);
951
    virQEMUCapsCacheFree(qemu_driver->qemuCapsCache);
952

953
    virObjectUnref(qemu_driver->domains);
954
    virObjectUnref(qemu_driver->remotePorts);
955

956
    virObjectUnref(qemu_driver->xmlopt);
957

958
    virSysinfoDefFree(qemu_driver->hostsysinfo);
959

960
    virObjectUnref(qemu_driver->closeCallbacks);
961

E
Eric Blake 已提交
962
    VIR_FREE(qemu_driver->qemuImgBinary);
963

964
    virObjectUnref(qemu_driver->securityManager);
965

966
    ebtablesContextFree(qemu_driver->ebtables);
967

968
    /* Free domain callback list */
969
    virDomainEventStateFree(qemu_driver->domainEventState);
D
Daniel P. Berrange 已提交
970

971 972
    virLockManagerPluginUnref(qemu_driver->lockManager);

973 974 975
    virMutexDestroy(&qemu_driver->lock);
    virThreadPoolFree(qemu_driver->workerPool);
    VIR_FREE(qemu_driver);
976

977
    return 0;
978 979
}

980

981 982 983
static virDrvOpenStatus qemuOpen(virConnectPtr conn,
                                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                 unsigned int flags)
984
{
985 986
    virQEMUDriverConfigPtr cfg = NULL;
    virDrvOpenStatus ret = VIR_DRV_OPEN_ERROR;
E
Eric Blake 已提交
987 988
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

989
    if (conn->uri == NULL) {
990 991 992 993 994 995
        if (qemu_driver == NULL) {
            ret = VIR_DRV_OPEN_DECLINED;
            goto cleanup;
        }

        cfg = virQEMUDriverGetConfig(qemu_driver);
996

997 998
        if (!(conn->uri = virURIParse(cfg->uri)))
            goto cleanup;
999 1000 1001
    } else {
        /* If URI isn't 'qemu' its definitely not for us */
        if (conn->uri->scheme == NULL ||
1002 1003 1004 1005
            STRNEQ(conn->uri->scheme, "qemu")) {
            ret = VIR_DRV_OPEN_DECLINED;
            goto cleanup;
        }
1006 1007

        /* Allow remote driver to deal with URIs with hostname server */
1008 1009 1010 1011
        if (conn->uri->server != NULL) {
            ret = VIR_DRV_OPEN_DECLINED;
            goto cleanup;
        }
1012

1013
        if (qemu_driver == NULL) {
1014 1015
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("qemu state driver is not active"));
1016
            goto cleanup;
1017 1018
        }

J
Ján Tomko 已提交
1019
        cfg = virQEMUDriverGetConfig(qemu_driver);
1020
        if (conn->uri->path == NULL) {
1021 1022
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("no QEMU URI path given, try %s"),
1023 1024
                           cfg->uri);
            goto cleanup;
1025 1026
        }

1027
        if (cfg->privileged) {
1028 1029
            if (STRNEQ(conn->uri->path, "/system") &&
                STRNEQ(conn->uri->path, "/session")) {
1030 1031 1032
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected QEMU URI path '%s', try qemu:///system"),
                               conn->uri->path);
1033
                goto cleanup;
1034 1035
            }
        } else {
1036
            if (STRNEQ(conn->uri->path, "/session")) {
1037 1038 1039
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected QEMU URI path '%s', try qemu:///session"),
                               conn->uri->path);
1040
                goto cleanup;
1041 1042
            }
        }
1043 1044 1045
    }
    conn->privateData = qemu_driver;

1046 1047 1048 1049
    ret = VIR_DRV_OPEN_SUCCESS;
cleanup:
    virObjectUnref(cfg);
    return ret;
1050 1051
}

1052 1053
static int qemuClose(virConnectPtr conn)
{
1054
    virQEMUDriverPtr driver = conn->privateData;
1055 1056

    /* Get rid of callbacks registered for this conn */
1057
    virQEMUCloseCallbacksRun(driver->closeCallbacks, conn, driver);
1058 1059 1060 1061 1062 1063

    conn->privateData = NULL;

    return 0;
}

D
Daniel Veillard 已提交
1064 1065
/* Which features are supported by this driver? */
static int
1066
qemuSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
D
Daniel Veillard 已提交
1067 1068
{
    switch (feature) {
1069
    case VIR_DRV_FEATURE_MIGRATION_V2:
1070
    case VIR_DRV_FEATURE_MIGRATION_V3:
1071
    case VIR_DRV_FEATURE_MIGRATION_P2P:
1072
    case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
1073
    case VIR_DRV_FEATURE_FD_PASSING:
1074
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
1075
    case VIR_DRV_FEATURE_XML_MIGRATABLE:
L
liguang 已提交
1076
    case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
1077 1078 1079
        return 1;
    default:
        return 0;
D
Daniel Veillard 已提交
1080 1081 1082
    }
}

1083
static const char *qemuGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1084
    return "QEMU";
1085 1086
}

1087

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
static int qemuIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* Trivially secure, since always inside the daemon */
    return 1;
}

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

1100 1101 1102 1103 1104
static int qemuIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return 1;
}

1105

1106 1107 1108 1109
static int
kvmGetMaxVCPUs(void) {
    int fd;
    int ret;
1110

1111
    if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) {
1112
        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
1113
        return -1;
1114 1115
    }

1116
#ifdef KVM_CAP_MAX_VCPUS
1117 1118 1119
    /* 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;
1120
#endif /* KVM_CAP_MAX_VCPUS */
1121 1122 1123 1124 1125 1126 1127 1128 1129

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

1131
cleanup:
1132
    VIR_FORCE_CLOSE(fd);
1133
    return ret;
1134 1135 1136
}


E
Eric Blake 已提交
1137 1138 1139
static char *
qemuGetSysinfo(virConnectPtr conn, unsigned int flags)
{
1140
    virQEMUDriverPtr driver = conn->privateData;
1141
    virBuffer buf = VIR_BUFFER_INITIALIZER;
E
Eric Blake 已提交
1142 1143 1144 1145

    virCheckFlags(0, NULL);

    if (!driver->hostsysinfo) {
1146 1147
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Host SMBIOS information is not available"));
E
Eric Blake 已提交
1148 1149 1150
        return NULL;
    }

1151 1152 1153 1154 1155 1156 1157
    if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
        return NULL;
    if (virBufferError(&buf)) {
        virReportOOMError();
        return NULL;
    }
    return virBufferContentAndReset(&buf);
E
Eric Blake 已提交
1158 1159
}

1160
static int qemuGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type) {
1161 1162 1163
    if (!type)
        return 16;

1164
    if (STRCASEEQ(type, "qemu"))
1165 1166
        return 16;

1167
    if (STRCASEEQ(type, "kvm"))
1168
        return kvmGetMaxVCPUs();
1169

1170
    if (STRCASEEQ(type, "kqemu"))
1171
        return 1;
1172

1173 1174
    virReportError(VIR_ERR_INVALID_ARG,
                   _("unknown type '%s'"), type);
1175 1176 1177
    return -1;
}

1178

1179
static char *qemuGetCapabilities(virConnectPtr conn) {
1180
    virQEMUDriverPtr driver = conn->privateData;
1181
    virCapsPtr caps = NULL;
1182
    char *xml = NULL;
1183

1184
    if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
1185
        goto cleanup;
1186

1187
    if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
1188
        virReportOOMError();
1189
    virObjectUnref(caps);
1190 1191

cleanup:
1192

1193
    return xml;
1194 1195 1196
}


1197
static int
1198 1199
qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
                   pid_t pid, int tid)
1200 1201
{
    char *proc;
D
Daniel P. Berrange 已提交
1202
    FILE *pidinfo;
1203
    unsigned long long usertime, systime;
1204
    long rss;
1205 1206
    int cpu;
    int ret;
D
Daniel P. Berrange 已提交
1207

1208 1209
    /* In general, we cannot assume pid_t fits in int; but /proc parsing
     * is specific to Linux where int works fine.  */
1210
    if (tid)
1211
        ret = virAsprintf(&proc, "/proc/%d/task/%d/stat", (int) pid, tid);
1212
    else
1213
        ret = virAsprintf(&proc, "/proc/%d/stat", (int) pid);
1214
    if (ret < 0)
D
Daniel P. Berrange 已提交
1215 1216 1217 1218
        return -1;

    if (!(pidinfo = fopen(proc, "r"))) {
        /* VM probably shut down, so fake 0 */
1219 1220 1221 1222
        if (cpuTime)
            *cpuTime = 0;
        if (lastCpu)
            *lastCpu = 0;
1223 1224
        if (vm_rss)
            *vm_rss = 0;
1225
        VIR_FREE(proc);
D
Daniel P. Berrange 已提交
1226 1227
        return 0;
    }
1228
    VIR_FREE(proc);
D
Daniel P. Berrange 已提交
1229

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

    /* We got jiffies
     * We want nanoseconds
     * _SC_CLK_TCK is jiffies per second
     * So calulate thus....
     */
1251 1252 1253 1254 1255
    if (cpuTime)
        *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
    if (lastCpu)
        *lastCpu = cpu;

1256 1257 1258 1259 1260 1261
    /* 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 已提交
1262

1263 1264

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

1267
    VIR_FORCE_FCLOSE(pidinfo);
D
Daniel P. Berrange 已提交
1268 1269 1270 1271 1272

    return 0;
}


1273 1274
static virDomainPtr qemuDomainLookupByID(virConnectPtr conn,
                                         int id) {
1275
    virQEMUDriverPtr driver = conn->privateData;
1276 1277 1278
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

1279
    vm  = virDomainObjListFindByID(driver->domains, id);
1280 1281

    if (!vm) {
1282 1283
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching id %d"), id);
1284
        goto cleanup;
1285 1286
    }

1287
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1288
    if (dom) dom->id = vm->def->id;
1289 1290

cleanup:
1291
    if (vm)
1292
        virObjectUnlock(vm);
1293 1294
    return dom;
}
1295

1296 1297
static virDomainPtr qemuDomainLookupByUUID(virConnectPtr conn,
                                           const unsigned char *uuid) {
1298
    virQEMUDriverPtr driver = conn->privateData;
1299 1300
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1301

1302
    vm = virDomainObjListFindByUUID(driver->domains, uuid);
1303

1304
    if (!vm) {
1305 1306
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(uuid, uuidstr);
1307 1308
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s'"), uuidstr);
1309
        goto cleanup;
1310 1311
    }

1312
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1313
    if (dom) dom->id = vm->def->id;
1314 1315

cleanup:
1316
    if (vm)
1317
        virObjectUnlock(vm);
1318 1319
    return dom;
}
1320

1321 1322
static virDomainPtr qemuDomainLookupByName(virConnectPtr conn,
                                           const char *name) {
1323
    virQEMUDriverPtr driver = conn->privateData;
1324 1325
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
1326

1327
    vm = virDomainObjListFindByName(driver->domains, name);
1328

1329
    if (!vm) {
1330 1331
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching name '%s'"), name);
1332
        goto cleanup;
1333 1334
    }

1335
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1336
    if (dom) dom->id = vm->def->id;
1337 1338

cleanup:
1339
    if (vm)
1340
        virObjectUnlock(vm);
1341 1342 1343
    return dom;
}

1344 1345 1346 1347 1348 1349

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

1350
    if (!(obj = qemuDomObjFromDomain(dom)))
1351
        goto cleanup;
1352

1353 1354 1355 1356
    ret = virDomainObjIsActive(obj);

cleanup:
    if (obj)
1357
        virObjectUnlock(obj);
1358 1359 1360 1361 1362 1363 1364 1365
    return ret;
}

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

1366
    if (!(obj = qemuDomObjFromDomain(dom)))
1367
        goto cleanup;
1368

1369 1370 1371 1372
    ret = obj->persistent;

cleanup:
    if (obj)
1373
        virObjectUnlock(obj);
1374 1375 1376
    return ret;
}

1377 1378 1379 1380 1381
static int qemuDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

1382
    if (!(obj = qemuDomObjFromDomain(dom)))
1383
        goto cleanup;
1384

1385 1386 1387 1388
    ret = obj->updated;

cleanup:
    if (obj)
1389
        virObjectUnlock(obj);
1390 1391
    return ret;
}
1392

1393
static int qemuGetVersion(virConnectPtr conn, unsigned long *version) {
1394
    virQEMUDriverPtr driver = conn->privateData;
1395
    int ret = -1;
1396
    unsigned int qemuVersion = 0;
1397
    virCapsPtr caps = NULL;
1398

1399 1400 1401 1402
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (virQEMUCapsGetDefaultVersion(caps,
1403 1404
                                     driver->qemuCapsCache,
                                     &qemuVersion) < 0)
1405
        goto cleanup;
1406

1407
    *version = qemuVersion;
1408 1409 1410
    ret = 0;

cleanup:
1411
    virObjectUnref(caps);
1412
    return ret;
D
Daniel P. Berrange 已提交
1413 1414
}

1415
static int qemuListDomains(virConnectPtr conn, int *ids, int nids) {
1416
    virQEMUDriverPtr driver = conn->privateData;
1417
    int n;
1418

1419
    n = virDomainObjListGetActiveIDs(driver->domains, ids, nids);
1420

1421
    return n;
D
Daniel P. Berrange 已提交
1422
}
1423

1424
static int qemuNumDomains(virConnectPtr conn) {
1425
    virQEMUDriverPtr driver = conn->privateData;
1426
    int n;
1427

1428
    n = virDomainObjListNumOfDomains(driver->domains, 1);
1429

1430
    return n;
D
Daniel P. Berrange 已提交
1431
}
1432

1433 1434

static int
1435
qemuCanonicalizeMachine(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
1436
{
1437
    const char *canon;
1438

1439
    if (!(canon = virQEMUCapsGetCanonicalMachine(qemuCaps, def->os.machine)))
1440 1441 1442
        return 0;

    if (STRNEQ(canon, def->os.machine)) {
1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
        char *tmp;
        if (!(tmp = strdup(canon))) {
            virReportOOMError();
            return -1;
        }
        VIR_FREE(def->os.machine);
        def->os.machine = tmp;
    }

    return 0;
}


1456 1457
static virDomainPtr qemuDomainCreate(virConnectPtr conn, const char *xml,
                                     unsigned int flags) {
1458
    virQEMUDriverPtr driver = conn->privateData;
1459
    virDomainDefPtr def = NULL;
1460
    virDomainObjPtr vm = NULL;
1461
    virDomainPtr dom = NULL;
1462
    virDomainEventPtr event = NULL;
1463
    virDomainEventPtr event2 = NULL;
1464
    unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
1465
    virQEMUCapsPtr qemuCaps = NULL;
1466
    virCapsPtr caps = NULL;
D
Daniel P. Berrange 已提交
1467

1468 1469
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
                  VIR_DOMAIN_START_AUTODESTROY, NULL);
1470

1471 1472 1473
    if (flags & VIR_DOMAIN_START_PAUSED)
        start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
    if (flags & VIR_DOMAIN_START_AUTODESTROY)
1474
        start_flags |= VIR_QEMU_PROCESS_START_AUTODESTROY;
1475

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

1479
    if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
M
Matthias Bolte 已提交
1480
                                        QEMU_EXPECTED_VIRT_TYPES,
1481
                                        VIR_DOMAIN_XML_INACTIVE)))
1482
        goto cleanup;
1483

1484
    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
1485 1486
        goto cleanup;

1487
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
1488 1489
        goto cleanup;

1490
    if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
1491 1492
        goto cleanup;

1493
    if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
1494 1495
        goto cleanup;

1496
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1497
                                   driver->xmlopt,
1498 1499
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1500 1501 1502
        goto cleanup;

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

1504
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1505 1506
        goto cleanup; /* XXXX free the 'vm' we created ? */

1507 1508 1509
    if (qemuProcessStart(conn, driver, vm, NULL, -1, NULL, NULL,
                         VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                         start_flags) < 0) {
1510
        virDomainAuditStart(vm, "booted", false);
1511
        if (qemuDomainObjEndJob(driver, vm) > 0)
1512
            qemuDomainRemoveInactive(driver, vm);
1513
        vm = NULL;
1514
        goto cleanup;
D
Daniel P. Berrange 已提交
1515
    }
1516 1517 1518 1519

    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
    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);
    }
1530
    virDomainAuditStart(vm, "booted", true);
D
Daniel P. Berrange 已提交
1531

1532
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1533
    if (dom) dom->id = vm->def->id;
1534

1535
    if (vm &&
1536
        qemuDomainObjEndJob(driver, vm) == 0)
1537
        vm = NULL;
1538

1539 1540
cleanup:
    virDomainDefFree(def);
1541
    if (vm)
1542
        virObjectUnlock(vm);
1543
    if (event) {
1544
        qemuDomainEventQueue(driver, event);
1545 1546 1547
        if (event2)
            qemuDomainEventQueue(driver, event2);
    }
1548
    virObjectUnref(caps);
1549
    virObjectUnref(qemuCaps);
1550
    return dom;
D
Daniel P. Berrange 已提交
1551 1552 1553
}


1554
static int qemuDomainSuspend(virDomainPtr dom) {
1555
    virQEMUDriverPtr driver = dom->conn->privateData;
1556 1557
    virDomainObjPtr vm;
    int ret = -1;
1558
    virDomainEventPtr event = NULL;
1559
    qemuDomainObjPrivatePtr priv;
1560 1561
    virDomainPausedReason reason;
    int eventDetail;
1562
    int state;
1563
    virQEMUDriverConfigPtr cfg = NULL;
1564

1565 1566
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
1567

D
Daniel P. Berrange 已提交
1568
    if (!virDomainObjIsActive(vm)) {
1569 1570
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1571
        goto cleanup;
D
Daniel P. Berrange 已提交
1572
    }
1573

1574
    cfg = virQEMUDriverGetConfig(driver);
1575 1576
    priv = vm->privateData;

1577
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_SUSPEND) < 0)
1578 1579 1580
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
1581 1582
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1583 1584
        goto endjob;
    }
1585

1586 1587 1588
    if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) {
        reason = VIR_DOMAIN_PAUSED_MIGRATION;
        eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED;
1589 1590 1591
    } else if (priv->job.asyncJob == QEMU_ASYNC_JOB_SNAPSHOT) {
        reason = VIR_DOMAIN_PAUSED_SNAPSHOT;
        eventDetail = -1; /* don't create lifecycle events when doing snapshot */
1592 1593 1594 1595 1596
    } else {
        reason = VIR_DOMAIN_PAUSED_USER;
        eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
    }

1597 1598 1599 1600 1601 1602
    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) {
1603
        if (qemuProcessStopCPUs(driver, vm, reason, QEMU_ASYNC_JOB_NONE) < 0) {
1604
            goto endjob;
1605
        }
1606 1607 1608 1609 1610 1611

        if (eventDetail >= 0) {
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_SUSPENDED,
                                             eventDetail);
        }
D
Daniel P. Berrange 已提交
1612
    }
1613
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1614 1615
        goto endjob;
    ret = 0;
1616

1617
endjob:
1618
    if (qemuDomainObjEndJob(driver, vm) == 0)
1619
        vm = NULL;
1620

1621
cleanup:
1622
    if (vm)
1623
        virObjectUnlock(vm);
1624

1625
    if (event)
1626
        qemuDomainEventQueue(driver, event);
1627
    virObjectUnref(cfg);
1628
    return ret;
D
Daniel P. Berrange 已提交
1629 1630 1631
}


1632
static int qemuDomainResume(virDomainPtr dom) {
1633
    virQEMUDriverPtr driver = dom->conn->privateData;
1634 1635
    virDomainObjPtr vm;
    int ret = -1;
1636
    virDomainEventPtr event = NULL;
1637
    int state;
1638
    virQEMUDriverConfigPtr cfg = NULL;
1639
    virCapsPtr caps = NULL;
1640

1641 1642
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
1643

1644 1645
    cfg = virQEMUDriverGetConfig(driver);

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

D
Daniel P. Berrange 已提交
1649
    if (!virDomainObjIsActive(vm)) {
1650 1651
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1652
        goto endjob;
D
Daniel P. Berrange 已提交
1653
    }
1654 1655 1656 1657 1658 1659 1660

    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 已提交
1661
        if (qemuProcessStartCPUs(driver, vm, dom->conn,
1662 1663
                                 VIR_DOMAIN_RUNNING_UNPAUSED,
                                 QEMU_ASYNC_JOB_NONE) < 0) {
1664
            if (virGetLastError() == NULL)
1665 1666
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("resume operation failed"));
1667
            goto endjob;
1668
        }
1669 1670 1671
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
D
Daniel P. Berrange 已提交
1672
    }
1673 1674
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto endjob;
1675
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1676
        goto endjob;
1677 1678
    ret = 0;

1679
endjob:
1680
    if (qemuDomainObjEndJob(driver, vm) == 0)
1681
        vm = NULL;
1682

1683
cleanup:
1684
    if (vm)
1685
        virObjectUnlock(vm);
1686
    if (event)
1687
        qemuDomainEventQueue(driver, event);
1688
    virObjectUnref(caps);
1689
    virObjectUnref(cfg);
1690
    return ret;
D
Daniel P. Berrange 已提交
1691 1692
}

1693
static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags) {
1694
    virQEMUDriverPtr driver = dom->conn->privateData;
1695 1696
    virDomainObjPtr vm;
    int ret = -1;
1697
    qemuDomainObjPrivatePtr priv;
1698
    bool useAgent = false, agentRequested, acpiRequested;
1699 1700 1701

    virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
                  VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1);
1702

1703
    if (!(vm = qemuDomObjFromDomain(dom)))
1704
        goto cleanup;
1705

1706
    priv = vm->privateData;
1707 1708
    agentRequested = flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT;
    acpiRequested  = flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
1709

1710 1711
    /* Prefer agent unless we were requested to not to. */
    if (agentRequested || (!flags && priv->agent))
1712 1713
        useAgent = true;

1714 1715
    if (priv->agentError) {
        if (agentRequested && !acpiRequested) {
1716 1717 1718
            virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                           _("QEMU guest agent is not "
                             "available due to an error"));
1719
            goto cleanup;
1720 1721
        } else {
            useAgent = false;
1722
        }
1723 1724 1725 1726
    }

    if (!priv->agent) {
        if (agentRequested && !acpiRequested) {
1727 1728
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("QEMU guest agent is not configured"));
1729
            goto cleanup;
1730 1731
        } else {
            useAgent = false;
1732 1733 1734
        }
    }

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

D
Daniel P. Berrange 已提交
1738
    if (!virDomainObjIsActive(vm)) {
1739 1740
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1741
        goto endjob;
1742 1743
    }

1744
    if (useAgent) {
1745
        qemuDomainObjEnterAgent(vm);
1746
        ret = qemuAgentShutdown(priv->agent, QEMU_AGENT_SHUTDOWN_POWERDOWN);
1747
        qemuDomainObjExitAgent(vm);
1748 1749 1750 1751 1752 1753 1754
    }

    /* 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))) {
1755
        qemuDomainSetFakeReboot(driver, vm, false);
1756

1757 1758 1759 1760
        qemuDomainObjEnterMonitor(driver, vm);
        ret = qemuMonitorSystemPowerdown(priv->mon);
        qemuDomainObjExitMonitor(driver, vm);
    }
1761

1762
endjob:
1763
    if (qemuDomainObjEndJob(driver, vm) == 0)
1764
        vm = NULL;
1765

1766
cleanup:
1767
    if (vm)
1768
        virObjectUnlock(vm);
1769
    return ret;
1770 1771
}

1772 1773
static int qemuDomainShutdown(virDomainPtr dom)
{
1774 1775 1776
    return qemuDomainShutdownFlags(dom, 0);
}

1777

1778 1779 1780
static int
qemuDomainReboot(virDomainPtr dom, unsigned int flags)
{
1781
    virQEMUDriverPtr driver = dom->conn->privateData;
1782 1783 1784
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
1785
    bool useAgent = false;
1786

1787 1788
    virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
                  VIR_DOMAIN_REBOOT_GUEST_AGENT , -1);
1789

1790 1791 1792 1793 1794 1795 1796 1797
    /* 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;
    }

1798
    if (!(vm = qemuDomObjFromDomain(dom)))
1799 1800
        goto cleanup;

1801 1802
    priv = vm->privateData;

1803 1804
    if ((flags & VIR_DOMAIN_REBOOT_GUEST_AGENT) ||
        (!(flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) &&
1805 1806 1807 1808 1809
         priv->agent))
        useAgent = true;

    if (useAgent) {
        if (priv->agentError) {
1810 1811 1812
            virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                           _("QEMU guest agent is not "
                             "available due to an error"));
1813 1814 1815
            goto cleanup;
        }
        if (!priv->agent) {
1816 1817
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("QEMU guest agent is not configured"));
1818 1819 1820
            goto cleanup;
        }
    } else {
1821
#if WITH_YAJL
1822 1823
        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) {
1824 1825
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Reboot is not supported with this QEMU binary"));
1826 1827 1828 1829
                goto cleanup;
            }
        } else {
#endif
1830 1831
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Reboot is not supported without the JSON monitor"));
1832
            goto cleanup;
1833
#if WITH_YAJL
1834
        }
1835 1836
#endif
    }
1837

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

1841
    if (!virDomainObjIsActive(vm)) {
1842 1843
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1844 1845
        goto endjob;
    }
1846

1847
    if (useAgent) {
1848
        qemuDomainObjEnterAgent(vm);
1849
        ret = qemuAgentShutdown(priv->agent, QEMU_AGENT_SHUTDOWN_REBOOT);
1850
        qemuDomainObjExitAgent(vm);
1851
    } else {
1852
        qemuDomainObjEnterMonitor(driver, vm);
1853
        ret = qemuMonitorSystemPowerdown(priv->mon);
1854
        qemuDomainObjExitMonitor(driver, vm);
1855

1856 1857
        if (ret == 0)
            qemuDomainSetFakeReboot(driver, vm, true);
1858 1859
    }

1860 1861 1862 1863
endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

1864 1865
cleanup:
    if (vm)
1866
        virObjectUnlock(vm);
1867 1868 1869 1870
    return ret;
}


1871 1872 1873
static int
qemuDomainReset(virDomainPtr dom, unsigned int flags)
{
1874
    virQEMUDriverPtr driver = dom->conn->privateData;
1875 1876 1877 1878 1879 1880
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

1881
    if (!(vm = qemuDomObjFromDomain(dom)))
1882 1883 1884 1885 1886 1887
        goto cleanup;

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

    if (!virDomainObjIsActive(vm)) {
1888 1889
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905
        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)
1906
        virObjectUnlock(vm);
1907 1908 1909 1910
    return ret;
}


1911
/* Count how many snapshots in a set are external snapshots or checkpoints.  */
1912 1913 1914 1915 1916 1917 1918 1919
static void
qemuDomainSnapshotCountExternal(void *payload,
                                const void *name ATTRIBUTE_UNUSED,
                                void *data)
{
    virDomainSnapshotObjPtr snap = payload;
    int *count = data;

1920
    if (virDomainSnapshotIsExternal(snap))
1921 1922 1923
        (*count)++;
}

1924 1925 1926 1927
static int
qemuDomainDestroyFlags(virDomainPtr dom,
                       unsigned int flags)
{
1928
    virQEMUDriverPtr driver = dom->conn->privateData;
1929 1930
    virDomainObjPtr vm;
    int ret = -1;
1931
    virDomainEventPtr event = NULL;
1932
    qemuDomainObjPrivatePtr priv;
1933

1934
    virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);
1935

1936 1937
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
1938

1939 1940
    priv = vm->privateData;

1941
    qemuDomainSetFakeReboot(driver, vm, false);
1942

1943 1944 1945 1946 1947 1948

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

1949 1950 1951 1952 1953
    /* 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
     */
1954
    if (flags & VIR_DOMAIN_DESTROY_GRACEFUL) {
1955
        if (qemuProcessKill(vm, 0) < 0) {
1956
            priv->beingDestroyed = false;
1957
            goto cleanup;
1958
        }
1959
    } else {
1960
        if (qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE) < 0) {
1961
            priv->beingDestroyed = false;
1962
            goto cleanup;
1963
        }
1964
    }
1965

1966
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_DESTROY) < 0)
1967 1968
        goto cleanup;

1969 1970
    priv->beingDestroyed = false;

D
Daniel P. Berrange 已提交
1971
    if (!virDomainObjIsActive(vm)) {
1972 1973
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1974
        goto endjob;
1975
    }
1976

1977
    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED, 0);
1978 1979 1980
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1981
    virDomainAuditStop(vm, "destroyed");
1982

1983
    if (!vm->persistent) {
1984
        if (qemuDomainObjEndJob(driver, vm) > 0)
1985
            qemuDomainRemoveInactive(driver, vm);
1986 1987
        vm = NULL;
    }
1988 1989
    ret = 0;

1990
endjob:
1991
    if (vm &&
1992
        qemuDomainObjEndJob(driver, vm) == 0)
1993
        vm = NULL;
1994

1995
cleanup:
1996
    if (vm)
1997
        virObjectUnlock(vm);
1998 1999
    if (event)
        qemuDomainEventQueue(driver, event);
2000
    return ret;
D
Daniel P. Berrange 已提交
2001 2002
}

2003 2004 2005 2006 2007
static int
qemuDomainDestroy(virDomainPtr dom)
{
    return qemuDomainDestroyFlags(dom, 0);
}
D
Daniel P. Berrange 已提交
2008

2009
static char *qemuDomainGetOSType(virDomainPtr dom) {
2010 2011
    virDomainObjPtr vm;
    char *type = NULL;
2012

2013
    if (!(vm = qemuDomObjFromDomain(dom)))
2014
        goto cleanup;
2015

2016
    if (!(type = strdup(vm->def->os.type)))
2017
        virReportOOMError();
2018 2019

cleanup:
2020
    if (vm)
2021
        virObjectUnlock(vm);
2022 2023 2024
    return type;
}

2025
/* Returns max memory in kb, 0 if error */
2026 2027 2028
static unsigned long long
qemuDomainGetMaxMemory(virDomainPtr dom)
{
2029
    virDomainObjPtr vm;
2030
    unsigned long long ret = 0;
2031

2032
    if (!(vm = qemuDomObjFromDomain(dom)))
2033
        goto cleanup;
2034

2035
    ret = vm->def->mem.max_balloon;
2036 2037

cleanup:
2038
    if (vm)
2039
        virObjectUnlock(vm);
2040
    return ret;
2041 2042
}

2043 2044
static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
                                    unsigned int flags) {
2045
    virQEMUDriverPtr driver = dom->conn->privateData;
2046
    qemuDomainObjPrivatePtr priv;
2047
    virDomainObjPtr vm;
2048
    virDomainDefPtr persistentDef = NULL;
2049
    int ret = -1, r;
2050
    virQEMUDriverConfigPtr cfg = NULL;
2051
    virCapsPtr caps = NULL;
2052

2053 2054
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
2055
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
2056

2057
    if (!(vm = qemuDomObjFromDomain(dom)))
2058
        goto cleanup;
2059

2060 2061
    cfg = virQEMUDriverGetConfig(driver);

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

2065 2066
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto endjob;
2067
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
2068
                                        &persistentDef) < 0)
2069
        goto endjob;
2070

2071 2072 2073
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */

2074
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
2075 2076 2077
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot resize the maximum memory on an "
                             "active domain"));
2078
            goto endjob;
2079
        }
2080

2081
        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
E
Eric Blake 已提交
2082 2083
            /* Help clang 2.8 decipher the logic flow.  */
            sa_assert(persistentDef);
2084 2085 2086
            persistentDef->mem.max_balloon = newmem;
            if (persistentDef->mem.cur_balloon > newmem)
                persistentDef->mem.cur_balloon = newmem;
2087
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
2088 2089 2090
            goto endjob;
        }

2091 2092 2093 2094
    } else {
        /* resize the current memory */

        if (newmem > vm->def->mem.max_balloon) {
2095 2096
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
2097 2098 2099
            goto endjob;
        }

2100
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
2101
            priv = vm->privateData;
2102
            qemuDomainObjEnterMonitor(driver, vm);
2103
            r = qemuMonitorSetBalloon(priv->mon, newmem);
2104
            qemuDomainObjExitMonitor(driver, vm);
2105 2106
            virDomainAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update",
                                 r == 1);
2107 2108 2109 2110 2111
            if (r < 0)
                goto endjob;

            /* Lack of balloon support is a fatal error */
            if (r == 0) {
2112 2113 2114
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("Unable to change memory of active domain without "
                                 "the balloon device and guest OS balloon driver"));
2115 2116 2117 2118
                goto endjob;
            }
        }

2119
        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
E
Eric Blake 已提交
2120
            sa_assert(persistentDef);
2121
            persistentDef->mem.cur_balloon = newmem;
2122
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
2123 2124
            goto endjob;
        }
2125
    }
2126

2127
    ret = 0;
2128
endjob:
2129
    if (qemuDomainObjEndJob(driver, vm) == 0)
2130
        vm = NULL;
2131

2132
cleanup:
2133
    if (vm)
2134
        virObjectUnlock(vm);
2135
    virObjectUnref(caps);
2136
    virObjectUnref(cfg);
2137
    return ret;
2138 2139
}

2140
static int qemuDomainSetMemory(virDomainPtr dom, unsigned long newmem)
2141
{
2142
    return qemuDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_AFFECT_LIVE);
2143 2144
}

2145
static int qemuDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
2146
{
2147
    return qemuDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
2148 2149
}

2150 2151
static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
{
2152
    virQEMUDriverPtr driver = domain->conn->privateData;
2153 2154 2155 2156 2157 2158
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

2159 2160
    if (!(vm = qemuDomObjFromDomain(domain)))
        return -1;
2161 2162

    if (!virDomainObjIsActive(vm)) {
2163 2164
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2165 2166 2167 2168 2169
        goto cleanup;
    }

    priv = vm->privateData;

2170
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2171
        goto cleanup;
2172 2173

    if (!virDomainObjIsActive(vm)) {
2174 2175
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2176 2177 2178
        goto endjob;
    }

2179
    qemuDomainObjEnterMonitor(driver, vm);
2180
    ret = qemuMonitorInjectNMI(priv->mon);
2181
    qemuDomainObjExitMonitor(driver, vm);
2182 2183

endjob:
2184
    if (qemuDomainObjEndJob(driver, vm) == 0) {
2185 2186 2187 2188 2189 2190
        vm = NULL;
        goto cleanup;
    }

cleanup:
    if (vm)
2191
        virObjectUnlock(vm);
2192 2193 2194
    return ret;
}

2195 2196 2197 2198 2199 2200 2201
static int qemuDomainSendKey(virDomainPtr domain,
                             unsigned int codeset,
                             unsigned int holdtime,
                             unsigned int *keycodes,
                             int nkeycodes,
                             unsigned int flags)
{
2202
    virQEMUDriverPtr driver = domain->conn->privateData;
2203 2204 2205 2206 2207 2208
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

2209 2210
    /* translate the keycode to RFB for qemu driver */
    if (codeset != VIR_KEYCODE_SET_RFB) {
2211 2212 2213 2214
        int i;
        int keycode;

        for (i = 0; i < nkeycodes; i++) {
2215
            keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_RFB,
2216 2217
                                               keycodes[i]);
            if (keycode < 0) {
2218 2219 2220 2221
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("cannot translate keycode %u of %s codeset to rfb keycode"),
                               keycodes[i],
                               virKeycodeSetTypeToString(codeset));
2222 2223 2224 2225 2226 2227
                return -1;
            }
            keycodes[i] = keycode;
        }
    }

2228
    if (!(vm = qemuDomObjFromDomain(domain)))
2229 2230 2231 2232
        goto cleanup;

    priv = vm->privateData;

2233
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2234 2235 2236
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
2237 2238
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2239
        goto endjob;
2240 2241
    }

2242
    qemuDomainObjEnterMonitor(driver, vm);
2243
    ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
2244
    qemuDomainObjExitMonitor(driver, vm);
2245 2246 2247

endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
2248 2249 2250 2251
        vm = NULL;

cleanup:
    if (vm)
2252
        virObjectUnlock(vm);
2253 2254 2255
    return ret;
}

2256 2257
static int qemuDomainGetInfo(virDomainPtr dom,
                             virDomainInfoPtr info)
2258
{
2259
    virQEMUDriverPtr driver = dom->conn->privateData;
2260 2261
    virDomainObjPtr vm;
    int ret = -1;
2262
    int err;
2263
    unsigned long long balloon;
2264

2265
    if (!(vm = qemuDomObjFromDomain(dom)))
2266
        goto cleanup;
D
Daniel P. Berrange 已提交
2267

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

D
Daniel P. Berrange 已提交
2270
    if (!virDomainObjIsActive(vm)) {
2271
        info->cpuTime = 0;
D
Daniel P. Berrange 已提交
2272
    } else {
2273
        if (qemuGetProcessInfo(&(info->cpuTime), NULL, NULL, vm->pid, 0) < 0) {
2274 2275
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("cannot read cputime for domain"));
2276
            goto cleanup;
D
Daniel P. Berrange 已提交
2277 2278 2279
        }
    }

2280
    info->maxMem = vm->def->mem.max_balloon;
2281

D
Daniel P. Berrange 已提交
2282
    if (virDomainObjIsActive(vm)) {
2283
        qemuDomainObjPrivatePtr priv = vm->privateData;
2284 2285 2286

        if ((vm->def->memballoon != NULL) &&
            (vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_NONE)) {
2287
            info->memory = vm->def->mem.max_balloon;
2288
        } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BALLOON_EVENT)) {
2289
            info->memory = vm->def->mem.cur_balloon;
2290
        } else if (qemuDomainJobAllowed(priv, QEMU_JOB_QUERY)) {
2291
            if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
2292
                goto cleanup;
2293 2294 2295
            if (!virDomainObjIsActive(vm))
                err = 0;
            else {
2296
                qemuDomainObjEnterMonitor(driver, vm);
2297
                err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
2298
                qemuDomainObjExitMonitor(driver, vm);
2299
            }
2300
            if (qemuDomainObjEndJob(driver, vm) == 0) {
2301
                vm = NULL;
2302 2303 2304
                goto cleanup;
            }

2305 2306 2307 2308 2309 2310 2311
            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) {
2312
                /* Balloon not supported, so maxmem is always the allocation */
2313
                info->memory = vm->def->mem.max_balloon;
2314
            } else {
2315
                info->memory = balloon;
2316
            }
2317
        } else {
2318
            info->memory = vm->def->mem.cur_balloon;
2319
        }
2320
    } else {
2321
        info->memory = vm->def->mem.cur_balloon;
2322 2323
    }

2324
    info->nrVirtCpu = vm->def->vcpus;
2325 2326 2327
    ret = 0;

cleanup:
2328
    if (vm)
2329
        virObjectUnlock(vm);
2330
    return ret;
D
Daniel P. Berrange 已提交
2331 2332
}

2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343
static int
qemuDomainGetState(virDomainPtr dom,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

2344
    if (!(vm = qemuDomObjFromDomain(dom)))
2345 2346
        goto cleanup;

J
Jiri Denemark 已提交
2347
    *state = virDomainObjGetState(vm, reason);
2348 2349 2350 2351
    ret = 0;

cleanup:
    if (vm)
2352
        virObjectUnlock(vm);
2353 2354 2355
    return ret;
}

2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366
static int
qemuDomainGetControlInfo(virDomainPtr dom,
                          virDomainControlInfoPtr info,
                          unsigned int flags)
{
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(0, -1);

2367
    if (!(vm = qemuDomObjFromDomain(dom)))
2368 2369 2370
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
2371 2372
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2373 2374 2375 2376 2377 2378 2379 2380 2381
        goto cleanup;
    }

    priv = vm->privateData;

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

    if (priv->monError) {
        info->state = VIR_DOMAIN_CONTROL_ERROR;
2382
    } else if (priv->job.active) {
2383 2384
        if (!priv->monStart) {
            info->state = VIR_DOMAIN_CONTROL_JOB;
2385
            if (virTimeMillisNow(&info->stateTime) < 0)
2386
                goto cleanup;
2387
            info->stateTime -= priv->job.start;
2388 2389
        } else {
            info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
2390
            if (virTimeMillisNow(&info->stateTime) < 0)
2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401
                goto cleanup;
            info->stateTime -= priv->monStart;
        }
    } else {
        info->state = VIR_DOMAIN_CONTROL_OK;
    }

    ret = 0;

cleanup:
    if (vm)
2402
        virObjectUnlock(vm);
2403 2404 2405
    return ret;
}

D
Daniel P. Berrange 已提交
2406

2407 2408 2409 2410 2411 2412
/* 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
2413

2414
verify(sizeof(QEMU_SAVE_MAGIC) == sizeof(QEMU_SAVE_PARTIAL));
E
Eric Blake 已提交
2415

2416
typedef enum {
2417 2418 2419
    QEMU_SAVE_FORMAT_RAW = 0,
    QEMU_SAVE_FORMAT_GZIP = 1,
    QEMU_SAVE_FORMAT_BZIP2 = 2,
2420 2421
    /*
     * Deprecated by xz and never used as part of a release
2422
     * QEMU_SAVE_FORMAT_LZMA
2423
     */
2424 2425
    QEMU_SAVE_FORMAT_XZ = 3,
    QEMU_SAVE_FORMAT_LZOP = 4,
2426 2427 2428
    /* Note: add new members only at the end.
       These values are used in the on-disk format.
       Do not change or re-use numbers. */
2429

2430
    QEMU_SAVE_FORMAT_LAST
2431
} virQEMUSaveFormat;
2432

2433 2434
VIR_ENUM_DECL(qemuSaveCompression)
VIR_ENUM_IMPL(qemuSaveCompression, QEMU_SAVE_FORMAT_LAST,
2435 2436 2437
              "raw",
              "gzip",
              "bzip2",
2438 2439
              "xz",
              "lzop")
2440

2441 2442 2443
typedef struct _virQEMUSaveHeader virQEMUSaveHeader;
typedef virQEMUSaveHeader *virQEMUSaveHeaderPtr;
struct _virQEMUSaveHeader {
2444
    char magic[sizeof(QEMU_SAVE_MAGIC)-1];
2445 2446 2447 2448 2449
    uint32_t version;
    uint32_t xml_len;
    uint32_t was_running;
    uint32_t compressed;
    uint32_t unused[15];
2450 2451
};

2452
static inline void
2453
bswap_header(virQEMUSaveHeaderPtr hdr) {
2454 2455 2456 2457 2458 2459 2460
    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);
}


2461
/* return -errno on failure, or 0 on success */
E
Eric Blake 已提交
2462
static int
2463
qemuDomainSaveHeader(int fd, const char *path, const char *xml,
2464
                     virQEMUSaveHeaderPtr header)
E
Eric Blake 已提交
2465
{
2466 2467
    int ret = 0;

E
Eric Blake 已提交
2468
    if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
2469
        ret = -errno;
2470 2471 2472
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("failed to write header to domain save file '%s'"),
                       path);
2473 2474 2475
        goto endjob;
    }

E
Eric Blake 已提交
2476
    if (safewrite(fd, xml, header->xml_len) != header->xml_len) {
2477
        ret = -errno;
2478 2479
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("failed to write xml to '%s'"), path);
2480 2481 2482 2483 2484 2485
        goto endjob;
    }
endjob:
    return ret;
}

2486
/* Given a virQEMUSaveFormat compression level, return the name
2487 2488 2489 2490
 * of the program to run, or NULL if no program is needed.  */
static const char *
qemuCompressProgramName(int compress)
{
2491 2492
    return (compress == QEMU_SAVE_FORMAT_RAW ? NULL :
            qemuSaveCompressionTypeToString(compress));
2493 2494
}

2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521
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 已提交
2522 2523 2524
/* Internal function to properly create or open existing files, with
 * ownership affected by qemu driver setup.  */
static int
2525
qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
E
Eric Blake 已提交
2526 2527 2528 2529 2530 2531
             bool *needUnlink, bool *bypassSecurityDriver)
{
    struct stat sb;
    bool is_reg = true;
    bool need_unlink = false;
    bool bypass_security = false;
L
Laine Stump 已提交
2532
    unsigned int vfoflags = 0;
E
Eric Blake 已提交
2533
    int fd = -1;
2534
    int path_shared = virStorageFileIsSharedFS(path);
E
Eric Blake 已提交
2535 2536
    uid_t uid = getuid();
    gid_t gid = getgid();
2537
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
E
Eric Blake 已提交
2538 2539 2540 2541 2542 2543

    /* 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;
2544 2545 2546

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

E
Eric Blake 已提交
2550 2551 2552 2553 2554
        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 */
2555
            if (is_reg && !cfg->dynamicOwnership) {
E
Eric Blake 已提交
2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569
                uid = sb.st_uid;
                gid = sb.st_gid;
            }
        }
    }

    /* First try creating the file as root */
    if (!is_reg) {
        fd = open(path, oflags & ~O_CREAT);
        if (fd < 0) {
            virReportSystemError(errno, _("unable to open %s"), path);
            goto cleanup;
        }
    } else {
L
Laine Stump 已提交
2570 2571
        if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR, uid, gid,
                                vfoflags | VIR_FILE_OPEN_NOFORK)) < 0) {
E
Eric Blake 已提交
2572 2573 2574
            /* 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
2575
               qemu user (cfg->user) is non-root, just set a flag to
E
Eric Blake 已提交
2576 2577 2578
               bypass security driver shenanigans, and retry the operation
               after doing setuid to qemu user */
            if ((fd != -EACCES && fd != -EPERM) ||
2579
                cfg->user == getuid()) {
E
Eric Blake 已提交
2580 2581 2582 2583 2584 2585 2586
                virReportSystemError(-fd,
                                     _("Failed to create file '%s'"),
                                     path);
                goto cleanup;
            }

            /* On Linux we can also verify the FS-type of the directory. */
2587
            switch (path_shared) {
E
Eric Blake 已提交
2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609
                case 1:
                   /* it was on a network share, so we'll continue
                    * as outlined above
                    */
                   break;

                case -1:
                   virReportSystemError(errno,
                                        _("Failed to create file "
                                          "'%s': couldn't determine fs type"),
                                        path);
                   goto cleanup;

                case 0:
                default:
                   /* local file - log the error returned by virFileOpenAs */
                   virReportSystemError(-fd,
                                        _("Failed to create file '%s'"),
                                        path);
                   goto cleanup;
            }

2610
            /* Retry creating the file as cfg->user */
E
Eric Blake 已提交
2611 2612 2613

            if ((fd = virFileOpenAs(path, oflags,
                                    S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
2614
                                    cfg->user, cfg->group,
L
Laine Stump 已提交
2615
                                    vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
E
Eric Blake 已提交
2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633
                virReportSystemError(-fd,
                                   _("Error from child process creating '%s'"),
                                     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;
2634
    virObjectUnref(cfg);
E
Eric Blake 已提交
2635 2636 2637
    return fd;
}

2638 2639 2640
/* 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 */
2641
static int
2642
qemuDomainSaveMemory(virQEMUDriverPtr driver,
2643 2644
                     virDomainObjPtr vm,
                     const char *path,
2645
                     const char *domXML,
2646 2647 2648 2649
                     int compressed,
                     bool was_running,
                     unsigned int flags,
                     enum qemuDomainAsyncJob asyncJob)
2650
{
2651
    virQEMUSaveHeader header;
2652
    bool bypassSecurityDriver = false;
E
Eric Blake 已提交
2653
    bool needUnlink = false;
2654
    int ret = -1;
2655
    int fd = -1;
2656
    int directFlag = 0;
J
Jiri Denemark 已提交
2657
    virFileWrapperFdPtr wrapperFd = NULL;
2658
    unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
2659 2660 2661
    unsigned long long pad;
    unsigned long long offset;
    size_t len;
2662
    char *xml = NULL;
2663

2664
    memset(&header, 0, sizeof(header));
2665 2666
    memcpy(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic));
    header.version = QEMU_SAVE_VERSION;
2667
    header.was_running = was_running ? 1 : 0;
2668

2669
    header.compressed = compressed;
2670

2671
    len = strlen(domXML) + 1;
2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
    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));
2685
    if (VIR_ALLOC_N(xml, len + pad) < 0) {
2686
        virReportOOMError();
2687
        goto cleanup;
2688
    }
2689 2690
    strcpy(xml, domXML);

2691 2692
    offset += pad;
    header.xml_len = len;
2693

2694
    /* Obtain the file handle.  */
2695 2696
    if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) {
        wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
2697 2698
        directFlag = virFileDirectFdFlag();
        if (directFlag < 0) {
2699 2700
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("bypass cache unsupported by this system"));
E
Eric Blake 已提交
2701
            goto cleanup;
2702
        }
2703
    }
E
Eric Blake 已提交
2704 2705 2706
    fd = qemuOpenFile(driver, path, O_WRONLY | O_TRUNC | O_CREAT | directFlag,
                      &needUnlink, &bypassSecurityDriver);
    if (fd < 0)
2707 2708
        goto cleanup;

2709
    if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
2710
        goto cleanup;
2711

2712
    /* Write header to file, followed by XML */
2713 2714
    if (qemuDomainSaveHeader(fd, path, xml, &header) < 0)
        goto cleanup;
2715

2716
    /* Perform the migration */
2717
    if (qemuMigrationToFile(driver, vm, fd, offset, path,
2718
                            qemuCompressProgramName(compressed),
E
Eric Blake 已提交
2719
                            bypassSecurityDriver,
2720 2721
                            asyncJob) < 0)
        goto cleanup;
E
Eric Blake 已提交
2722

2723 2724 2725 2726 2727 2728 2729 2730
    /* 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);
2731
        goto cleanup;
E
Eric Blake 已提交
2732
    }
2733

2734
    if (virFileWrapperFdClose(wrapperFd) < 0)
2735 2736 2737 2738
        goto cleanup;

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

2740
    memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic));
2741

E
Eric Blake 已提交
2742 2743
    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
        virReportSystemError(errno, _("unable to write %s"), path);
2744
        goto cleanup;
E
Eric Blake 已提交
2745
    }
2746

2747 2748
    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno, _("unable to close %s"), path);
2749
        goto cleanup;
2750 2751
    }

2752 2753
    ret = 0;

2754 2755 2756
cleanup:
    VIR_FORCE_CLOSE(fd);
    virFileWrapperFdFree(wrapperFd);
2757
    VIR_FREE(xml);
2758 2759 2760 2761 2762 2763 2764

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

    return ret;
}

2765
/* The vm must be active + locked. Vm will be unlocked and
2766 2767 2768 2769 2770
 * 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
2771
qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
2772 2773 2774 2775 2776 2777 2778 2779 2780
                       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;
2781 2782 2783 2784
    virCapsPtr caps;

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

2786
    if (!qemuMigrationIsAllowed(driver, vm, vm->def, false))
2787 2788
        goto cleanup;

2789
    if (qemuDomainObjBeginAsyncJob(driver, vm,
2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821
                                             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;

2822
        if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt,
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845
                                            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;

2846
    /* Shut it down */
2847
    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED, 0);
2848
    virDomainAuditStop(vm, "saved");
2849 2850 2851
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2852
    if (!vm->persistent) {
2853
        if (qemuDomainObjEndAsyncJob(driver, vm) > 0)
2854
            qemuDomainRemoveInactive(driver, vm);
2855 2856
        vm = NULL;
    }
2857

2858
endjob:
2859
    if (vm) {
2860
        if (ret != 0) {
2861
            if (was_running && virDomainObjIsActive(vm)) {
J
Jiri Denemark 已提交
2862
                rc = qemuProcessStartCPUs(driver, vm, dom->conn,
2863 2864
                                          VIR_DOMAIN_RUNNING_SAVE_CANCELED,
                                          QEMU_ASYNC_JOB_SAVE);
2865
                if (rc < 0) {
2866
                    VIR_WARN("Unable to resume guest CPUs after save failure");
2867 2868 2869 2870
                    event = virDomainEventNewFromObj(vm,
                                                     VIR_DOMAIN_EVENT_SUSPENDED,
                                                     VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
                }
2871
            }
2872
        }
2873
        if (qemuDomainObjEndAsyncJob(driver, vm) == 0)
2874
            vm = NULL;
2875
    }
2876

2877 2878
cleanup:
    VIR_FREE(xml);
2879 2880
    if (event)
        qemuDomainEventQueue(driver, event);
2881
    if (vm)
2882
        virObjectUnlock(vm);
2883
    virObjectUnref(caps);
2884
    return ret;
D
Daniel P. Berrange 已提交
2885 2886
}

2887
/* Returns true if a compression program is available in PATH */
2888
static bool qemuCompressProgramAvailable(virQEMUSaveFormat compress)
2889 2890 2891 2892
{
    const char *prog;
    char *c;

2893
    if (compress == QEMU_SAVE_FORMAT_RAW)
2894
        return true;
2895
    prog = qemuSaveCompressionTypeToString(compress);
2896 2897 2898 2899 2900 2901 2902
    c = virFindFileInPath(prog);
    if (!c)
        return false;
    VIR_FREE(c);
    return true;
}

2903 2904 2905
static int
qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
                    unsigned int flags)
2906
{
2907
    virQEMUDriverPtr driver = dom->conn->privateData;
2908
    int compressed;
2909 2910
    int ret = -1;
    virDomainObjPtr vm = NULL;
2911
    virQEMUDriverConfigPtr cfg = NULL;
2912

2913 2914 2915
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
2916

2917 2918
    cfg = virQEMUDriverGetConfig(driver);
    if (cfg->saveImageFormat == NULL)
2919
        compressed = QEMU_SAVE_FORMAT_RAW;
2920
    else {
2921
        compressed = qemuSaveCompressionTypeFromString(cfg->saveImageFormat);
2922
        if (compressed < 0) {
2923 2924 2925
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("Invalid save image format specified "
                                   "in configuration file"));
2926
            goto cleanup;
2927
        }
2928
        if (!qemuCompressProgramAvailable(compressed)) {
2929 2930 2931
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("Compression program for image format "
                                   "in configuration file isn't available"));
2932
            goto cleanup;
2933
        }
2934 2935
    }

2936
    if (!(vm = qemuDomObjFromDomain(dom)))
2937 2938
        goto cleanup;

2939
    if (!virDomainObjIsActive(vm)) {
2940 2941
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2942 2943 2944
        goto cleanup;
    }

2945
    ret = qemuDomainSaveInternal(driver, dom, vm, path, compressed,
2946
                                 dxml, flags);
2947
    vm = NULL;
2948 2949 2950

cleanup:
    if (vm)
2951
        virObjectUnlock(vm);
2952
    virObjectUnref(cfg);
2953
    return ret;
2954 2955
}

2956 2957 2958 2959 2960 2961
static int
qemuDomainSave(virDomainPtr dom, const char *path)
{
    return qemuDomainSaveFlags(dom, path, NULL, 0);
}

2962
static char *
2963 2964
qemuDomainManagedSavePath(virQEMUDriverPtr driver, virDomainObjPtr vm)
{
2965
    char *ret;
2966
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
2967

2968
    if (virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name) < 0) {
2969
        virReportOOMError();
2970
        virObjectUnref(cfg);
2971
        return NULL;
2972 2973
    }

2974
    virObjectUnref(cfg);
2975
    return ret;
2976 2977 2978 2979 2980
}

static int
qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
2981
    virQEMUDriverPtr driver = dom->conn->privateData;
2982
    virDomainObjPtr vm;
2983 2984 2985 2986
    char *name = NULL;
    int ret = -1;
    int compressed;

2987 2988 2989
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
2990

2991
    if (!(vm = qemuDomObjFromDomain(dom)))
2992
        return -1;
2993

2994
    if (!virDomainObjIsActive(vm)) {
2995 2996
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2997 2998
        goto cleanup;
    }
2999
    if (!vm->persistent) {
3000 3001
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
3002 3003
        goto cleanup;
    }
3004

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

3008
    VIR_INFO("Saving state to %s", name);
3009

3010
    compressed = QEMU_SAVE_FORMAT_RAW;
3011 3012 3013 3014
    if ((ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed,
                                      NULL, flags)) == 0)
        vm->hasManagedSave = true;

3015
    vm = NULL;
3016 3017 3018

cleanup:
    if (vm)
3019
        virObjectUnlock(vm);
3020 3021 3022
    VIR_FREE(name);

    return ret;
3023 3024
}

3025 3026
static int
qemuDomainManagedSaveLoad(virDomainObjPtr vm,
3027 3028
                          void *opaque)
{
3029
    virQEMUDriverPtr driver = opaque;
3030
    char *name;
3031
    int ret = -1;
3032

3033
    virObjectLock(vm);
3034 3035 3036 3037 3038 3039

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

    vm->hasManagedSave = virFileExists(name);

3040
    ret = 0;
3041
cleanup:
3042
    virObjectUnlock(vm);
3043
    VIR_FREE(name);
3044
    return ret;
3045 3046
}

3047

3048 3049 3050 3051
static int
qemuDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
3052
    int ret;
3053

3054
    virCheckFlags(0, -1);
3055

3056 3057
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
3058

3059
    ret = vm->hasManagedSave;
3060
    virObjectUnlock(vm);
3061 3062 3063 3064 3065 3066
    return ret;
}

static int
qemuDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
3067
    virQEMUDriverPtr driver = dom->conn->privateData;
3068
    virDomainObjPtr vm;
3069 3070 3071
    int ret = -1;
    char *name = NULL;

3072
    virCheckFlags(0, -1);
3073

3074
    if (!(vm = qemuDomObjFromDomain(dom)))
3075
        return -1;
3076

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

3080 3081 3082 3083 3084 3085 3086
    if (unlink(name) < 0) {
        virReportSystemError(errno,
                             _("Failed to remove managed save file '%s'"),
                             name);
        goto cleanup;
    }

3087
    vm->hasManagedSave = false;
3088
    ret = 0;
3089 3090 3091

cleanup:
    VIR_FREE(name);
3092
    virObjectUnlock(vm);
3093 3094
    return ret;
}
D
Daniel P. Berrange 已提交
3095

3096
static int qemuDumpToFd(virQEMUDriverPtr driver, virDomainObjPtr vm,
3097 3098 3099 3100 3101
                        int fd, enum qemuDomainAsyncJob asyncJob)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int ret = -1;

3102
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY)) {
3103
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3104
                       _("dump-guest-memory is not supported"));
3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116
        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;

3117
    ret = qemuMonitorDumpToFd(priv->mon, fd);
3118
    qemuDomainObjExitMonitor(driver, vm);
3119 3120 3121 3122

    return ret;
}

3123
static int
3124
doCoreDump(virQEMUDriverPtr driver,
3125 3126
           virDomainObjPtr vm,
           const char *path,
3127
           virQEMUSaveFormat compress,
3128
           unsigned int dump_flags)
H
Hu Tao 已提交
3129 3130 3131
{
    int fd = -1;
    int ret = -1;
J
Jiri Denemark 已提交
3132
    virFileWrapperFdPtr wrapperFd = NULL;
3133
    int directFlag = 0;
3134
    unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
H
Hu Tao 已提交
3135 3136

    /* Create an empty file with appropriate ownership.  */
3137
    if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
3138
        flags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
3139 3140
        directFlag = virFileDirectFdFlag();
        if (directFlag < 0) {
3141 3142
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("bypass cache unsupported by this system"));
3143 3144 3145
            goto cleanup;
        }
    }
E
Eric Blake 已提交
3146 3147 3148 3149 3150 3151
    /* 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 已提交
3152 3153
        goto cleanup;

3154
    if (!(wrapperFd = virFileWrapperFdNew(&fd, path, flags)))
3155 3156
        goto cleanup;

3157 3158 3159 3160 3161 3162 3163 3164 3165
    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)
3166 3167
        goto cleanup;

H
Hu Tao 已提交
3168 3169
    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno,
3170
                             _("unable to close file %s"),
H
Hu Tao 已提交
3171 3172 3173
                             path);
        goto cleanup;
    }
J
Jiri Denemark 已提交
3174
    if (virFileWrapperFdClose(wrapperFd) < 0)
3175
        goto cleanup;
H
Hu Tao 已提交
3176

3177
    ret = 0;
H
Hu Tao 已提交
3178 3179

cleanup:
3180
    VIR_FORCE_CLOSE(fd);
3181
    if (ret != 0)
H
Hu Tao 已提交
3182
        unlink(path);
3183
    virFileWrapperFdFree(wrapperFd);
H
Hu Tao 已提交
3184 3185 3186
    return ret;
}

3187
static virQEMUSaveFormat
3188
getCompressionType(virQEMUDriverPtr driver)
3189
{
3190 3191
    int ret = QEMU_SAVE_FORMAT_RAW;
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3192

3193 3194 3195 3196
    /*
     * We reuse "save" flag for "dump" here. Then, we can support the same
     * format in "save" and "dump".
     */
3197 3198
    if (cfg->dumpImageFormat) {
        ret = qemuSaveCompressionTypeFromString(cfg->dumpImageFormat);
3199 3200 3201
        /* Use "raw" as the format if the specified format is not valid,
         * or the compress program is not available.
         */
3202
        if (ret < 0) {
3203 3204
            VIR_WARN("%s", _("Invalid dump image format specified in "
                             "configuration file, using raw"));
3205 3206
            ret = QEMU_SAVE_FORMAT_RAW;
            goto cleanup;
3207
        }
3208
        if (!qemuCompressProgramAvailable(ret)) {
3209 3210 3211
            VIR_WARN("%s", _("Compression program for dump image format "
                             "in configuration file isn't available, "
                             "using raw"));
3212 3213
            ret = QEMU_SAVE_FORMAT_RAW;
            goto cleanup;
3214
        }
3215
    }
3216 3217 3218
cleanup:
    virObjectUnref(cfg);
    return ret;
3219 3220
}

3221 3222 3223
static int qemuDomainCoreDump(virDomainPtr dom,
                              const char *path,
                              unsigned int flags)
3224
{
3225
    virQEMUDriverPtr driver = dom->conn->privateData;
3226
    virDomainObjPtr vm;
M
Michal Privoznik 已提交
3227
    qemuDomainObjPrivatePtr priv;
3228
    int resume = 0, paused = 0;
H
Hu Tao 已提交
3229
    int ret = -1;
3230 3231
    virDomainEventPtr event = NULL;

M
Michal Privoznik 已提交
3232
    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
3233 3234
                  VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET |
                  VIR_DUMP_MEMORY_ONLY, -1);
3235

3236 3237
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
P
Paolo Bonzini 已提交
3238

3239 3240
    if (qemuDomainObjBeginAsyncJob(driver, vm,
                                   QEMU_ASYNC_JOB_DUMP) < 0)
3241 3242
        goto cleanup;

D
Daniel P. Berrange 已提交
3243
    if (!virDomainObjIsActive(vm)) {
3244 3245
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
3246
        goto endjob;
P
Paolo Bonzini 已提交
3247 3248
    }

P
Paolo Bonzini 已提交
3249 3250
    /* Migrate will always stop the VM, so the resume condition is
       independent of whether the stop command is issued.  */
J
Jiri Denemark 已提交
3251
    resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
P
Paolo Bonzini 已提交
3252 3253

    /* Pause domain for non-live dump */
J
Jiri Denemark 已提交
3254 3255
    if (!(flags & VIR_DUMP_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
3256 3257
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_DUMP,
                                QEMU_ASYNC_JOB_DUMP) < 0)
3258
            goto endjob;
P
Paolo Bonzini 已提交
3259
        paused = 1;
3260 3261

        if (!virDomainObjIsActive(vm)) {
3262 3263
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
3264 3265
            goto endjob;
        }
P
Paolo Bonzini 已提交
3266 3267
    }

3268
    ret = doCoreDump(driver, vm, path, getCompressionType(driver), flags);
3269 3270 3271 3272
    if (ret < 0)
        goto endjob;

    paused = 1;
3273 3274

endjob:
3275
    if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
3276
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, 0);
3277
        virDomainAuditStop(vm, "crashed");
3278 3279 3280 3281 3282
        event = virDomainEventNewFromObj(vm,
                                         VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
    }

P
Paolo Bonzini 已提交
3283 3284 3285
    /* 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 已提交
3286 3287 3288 3289
    else if (((resume && paused) || (flags & VIR_DUMP_RESET)) &&
             virDomainObjIsActive(vm)) {
        if ((ret == 0) && (flags & VIR_DUMP_RESET)) {
            priv =  vm->privateData;
3290
            qemuDomainObjEnterMonitor(driver, vm);
M
Michal Privoznik 已提交
3291
            ret = qemuMonitorSystemReset(priv->mon);
3292
            qemuDomainObjExitMonitor(driver, vm);
M
Michal Privoznik 已提交
3293 3294 3295 3296 3297
        }

        if (resume && qemuProcessStartCPUs(driver, vm, dom->conn,
                                           VIR_DOMAIN_RUNNING_UNPAUSED,
                                           QEMU_ASYNC_JOB_DUMP) < 0) {
3298 3299 3300
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_SUSPENDED,
                                             VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
3301
            if (virGetLastError() == NULL)
3302 3303
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("resuming after dump failed"));
P
Paolo Bonzini 已提交
3304 3305
        }
    }
3306

3307
    if (qemuDomainObjEndAsyncJob(driver, vm) == 0)
3308
        vm = NULL;
3309
    else if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) {
3310
        qemuDomainRemoveInactive(driver, vm);
3311 3312
        vm = NULL;
    }
3313 3314

cleanup:
P
Paolo Bonzini 已提交
3315
    if (vm)
3316
        virObjectUnlock(vm);
3317 3318
    if (event)
        qemuDomainEventQueue(driver, event);
P
Paolo Bonzini 已提交
3319 3320 3321
    return ret;
}

3322 3323 3324 3325
static char *
qemuDomainScreenshot(virDomainPtr dom,
                     virStreamPtr st,
                     unsigned int screen,
E
Eric Blake 已提交
3326
                     unsigned int flags)
3327
{
3328
    virQEMUDriverPtr driver = dom->conn->privateData;
3329 3330 3331 3332 3333
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    char *tmp = NULL;
    int tmp_fd = -1;
    char *ret = NULL;
E
Eric Blake 已提交
3334
    bool unlink_tmp = false;
3335
    virQEMUDriverConfigPtr cfg = NULL;
3336

E
Eric Blake 已提交
3337 3338
    virCheckFlags(0, NULL);

3339
    if (!(vm = qemuDomObjFromDomain(dom)))
3340 3341 3342
        goto cleanup;

    priv = vm->privateData;
3343
    cfg = virQEMUDriverGetConfig(driver);
3344

3345
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
3346 3347 3348
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
3349 3350
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
3351 3352 3353 3354 3355 3356
        goto endjob;
    }

    /* Well, even if qemu allows multiple graphic cards, heads, whatever,
     * screenshot command does not */
    if (screen) {
3357 3358 3359
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("currently is supported only taking "
                               "screenshots of screen ID 0"));
3360 3361 3362
        goto endjob;
    }

3363
    if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", cfg->cacheDir) < 0) {
3364 3365 3366 3367
        virReportOOMError();
        goto endjob;
    }

3368 3369
    if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
        virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
3370 3371
        goto endjob;
    }
E
Eric Blake 已提交
3372
    unlink_tmp = true;
3373

3374
    virSecurityManagerSetSavedStateLabel(qemu_driver->securityManager, vm->def, tmp);
3375

3376
    qemuDomainObjEnterMonitor(driver, vm);
3377
    if (qemuMonitorScreendump(priv->mon, tmp) < 0) {
3378
        qemuDomainObjExitMonitor(driver, vm);
3379 3380
        goto endjob;
    }
3381
    qemuDomainObjExitMonitor(driver, vm);
3382 3383 3384 3385 3386 3387

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

E
Eric Blake 已提交
3388
    if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
3389 3390
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("unable to open stream"));
3391 3392 3393 3394 3395 3396 3397
        goto endjob;
    }

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

endjob:
    VIR_FORCE_CLOSE(tmp_fd);
E
Eric Blake 已提交
3398 3399
    if (unlink_tmp)
        unlink(tmp);
E
Eric Blake 已提交
3400
    VIR_FREE(tmp);
3401

3402
    if (qemuDomainObjEndJob(driver, vm) == 0)
3403 3404 3405 3406
        vm = NULL;

cleanup:
    if (vm)
3407
        virObjectUnlock(vm);
3408
    virObjectUnref(cfg);
3409 3410 3411
    return ret;
}

H
Hu Tao 已提交
3412 3413 3414
static void processWatchdogEvent(void *data, void *opaque)
{
    int ret;
3415
    struct qemuDomainWatchdogEvent *wdEvent = data;
3416
    virQEMUDriverPtr driver = opaque;
3417
    virQEMUDriverConfigPtr cfg;
H
Hu Tao 已提交
3418

3419
    virObjectLock(wdEvent->vm);
3420
    cfg = virQEMUDriverGetConfig(driver);
W
Wen Congyang 已提交
3421

H
Hu Tao 已提交
3422 3423 3424 3425
    switch (wdEvent->action) {
    case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
        {
            char *dumpfile;
3426
            unsigned int flags = 0;
H
Hu Tao 已提交
3427

E
Eric Blake 已提交
3428
            if (virAsprintf(&dumpfile, "%s/%s-%u",
3429
                            cfg->autoDumpPath,
H
Hu Tao 已提交
3430
                            wdEvent->vm->def->name,
E
Eric Blake 已提交
3431 3432
                            (unsigned int)time(NULL)) < 0) {
                virReportOOMError();
W
Wen Congyang 已提交
3433
                goto unlock;
E
Eric Blake 已提交
3434
            }
H
Hu Tao 已提交
3435

3436
            if (qemuDomainObjBeginAsyncJob(driver, wdEvent->vm,
3437
                                                     QEMU_ASYNC_JOB_DUMP) < 0) {
W
Wen Congyang 已提交
3438 3439 3440
                VIR_FREE(dumpfile);
                goto unlock;
            }
H
Hu Tao 已提交
3441 3442

            if (!virDomainObjIsActive(wdEvent->vm)) {
3443 3444
                virReportError(VIR_ERR_OPERATION_INVALID,
                               "%s", _("domain is not running"));
W
Wen Congyang 已提交
3445 3446
                VIR_FREE(dumpfile);
                goto endjob;
H
Hu Tao 已提交
3447 3448
            }

3449
            flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
3450
            ret = doCoreDump(driver, wdEvent->vm, dumpfile,
3451
                             getCompressionType(driver), flags);
H
Hu Tao 已提交
3452
            if (ret < 0)
3453 3454
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("Dump failed"));
H
Hu Tao 已提交
3455

J
Jiri Denemark 已提交
3456
            ret = qemuProcessStartCPUs(driver, wdEvent->vm, NULL,
3457 3458
                                       VIR_DOMAIN_RUNNING_UNPAUSED,
                                       QEMU_ASYNC_JOB_DUMP);
H
Hu Tao 已提交
3459 3460

            if (ret < 0)
3461 3462
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("Resuming after dump failed"));
H
Hu Tao 已提交
3463 3464 3465 3466

            VIR_FREE(dumpfile);
        }
        break;
W
Wen Congyang 已提交
3467 3468
    default:
        goto unlock;
H
Hu Tao 已提交
3469 3470
    }

W
Wen Congyang 已提交
3471 3472 3473 3474
endjob:
    /* Safe to ignore value since ref count was incremented in
     * qemuProcessHandleWatchdog().
     */
3475
    ignore_value(qemuDomainObjEndAsyncJob(driver, wdEvent->vm));
W
Wen Congyang 已提交
3476 3477

unlock:
3478
    virObjectUnlock(wdEvent->vm);
3479
    virObjectUnref(wdEvent->vm);
H
Hu Tao 已提交
3480
    VIR_FREE(wdEvent);
3481
    virObjectUnref(cfg);
H
Hu Tao 已提交
3482
}
P
Paolo Bonzini 已提交
3483

3484
static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
3485 3486
                                  virDomainObjPtr vm,
                                  unsigned int nvcpus)
3487 3488
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
3489
    int i, rc = 1;
3490
    int ret = -1;
3491
    int oldvcpus = vm->def->vcpus;
E
Eric Blake 已提交
3492
    int vcpus = oldvcpus;
3493 3494
    pid_t *cpupids = NULL;
    int ncpupids;
3495
    virCgroupPtr cgroup_vcpu = NULL;
3496

3497
    qemuDomainObjEnterMonitor(driver, vm);
3498

3499 3500 3501
    /* 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 已提交
3502 3503
    if (nvcpus > vcpus) {
        for (i = vcpus ; i < nvcpus ; i++) {
3504 3505 3506 3507 3508 3509 3510
            /* Online new CPU */
            rc = qemuMonitorSetCPU(priv->mon, i, 1);
            if (rc == 0)
                goto unsupported;
            if (rc < 0)
                goto cleanup;

E
Eric Blake 已提交
3511
            vcpus++;
3512 3513
        }
    } else {
E
Eric Blake 已提交
3514
        for (i = vcpus - 1 ; i >= nvcpus ; i--) {
3515 3516 3517 3518 3519 3520 3521
            /* Offline old CPU */
            rc = qemuMonitorSetCPU(priv->mon, i, 0);
            if (rc == 0)
                goto unsupported;
            if (rc < 0)
                goto cleanup;

E
Eric Blake 已提交
3522
            vcpus--;
3523 3524 3525
        }
    }

3526 3527
    /* hotplug succeeded */

3528 3529
    ret = 0;

3530 3531 3532 3533 3534 3535 3536 3537 3538 3539
    /* 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;
    }

3540 3541 3542 3543 3544 3545 3546 3547 3548
    /* 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;
    }

3549
    if (ncpupids != vcpus) {
3550 3551 3552 3553
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("got wrong number of vCPU pids from QEMU monitor. "
                         "got %d, wanted %d"),
                       ncpupids, vcpus);
3554 3555 3556 3557
        ret = -1;
        goto cleanup;
    }

3558 3559
    if (nvcpus > oldvcpus) {
        for (i = oldvcpus; i < nvcpus; i++) {
3560
            if (priv->cgroup) {
3561
                int rv = -1;
3562
                /* Create cgroup for the onlined vcpu */
3563
                rv = virCgroupNewVcpu(priv->cgroup, i, true, &cgroup_vcpu);
3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580
                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;
                }
3581
            }
3582

3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605
            /* 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;

3606
                if (cgroup_vcpu) {
3607 3608 3609 3610 3611 3612 3613 3614 3615 3616
                    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 {
3617 3618
                    if (virProcessSetAffinity(cpupids[i],
                                              vcpupin->cpumask) < 0) {
3619 3620 3621 3622 3623 3624 3625
                        virReportError(VIR_ERR_SYSTEM_ERROR,
                                       _("failed to set cpu affinity for vcpu %d"),
                                       i);
                        ret = -1;
                        goto cleanup;
                    }
                }
3626
            }
3627 3628

            virCgroupFree(&cgroup_vcpu);
G
Guido Günther 已提交
3629
        }
3630 3631 3632 3633
    } else {
        for (i = oldvcpus - 1; i >= nvcpus; i--) {
            virDomainVcpuPinDefPtr vcpupin = NULL;

3634
            if (priv->cgroup) {
3635 3636
                int rv = -1;

3637
                rv = virCgroupNewVcpu(priv->cgroup, i, false, &cgroup_vcpu);
3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650
                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);
            }

3651 3652 3653 3654 3655
            /* Free vcpupin setting */
            if ((vcpupin = virDomainLookupVcpuPin(vm->def, i))) {
                VIR_FREE(vcpupin);
            }
        }
3656 3657
    }

3658 3659 3660 3661 3662
    priv->nvcpupids = ncpupids;
    VIR_FREE(priv->vcpupids);
    priv->vcpupids = cpupids;
    cpupids = NULL;

3663
cleanup:
3664
    qemuDomainObjExitMonitor(driver, vm);
E
Eric Blake 已提交
3665
    vm->def->vcpus = vcpus;
3666
    VIR_FREE(cpupids);
3667
    virDomainAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1);
3668 3669
    if (cgroup_vcpu)
        virCgroupFree(&cgroup_vcpu);
3670 3671 3672
    return ret;

unsupported:
3673 3674
    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                   _("cannot change vcpu count of this domain"));
3675 3676 3677 3678
    goto cleanup;
}


3679
static int
3680 3681
qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                        unsigned int flags)
3682
{
3683
    virQEMUDriverPtr driver = dom->conn->privateData;
3684
    virDomainObjPtr vm = NULL;
3685
    virDomainDefPtr persistentDef;
3686
    int ret = -1;
3687
    bool maximum;
3688
    virQEMUDriverConfigPtr cfg = NULL;
3689
    virCapsPtr caps = NULL;
3690

3691 3692
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
3693 3694 3695
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
3696 3697
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
3698 3699 3700
        return -1;
    }

3701
    cfg = virQEMUDriverGetConfig(driver);
3702 3703
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;
3704

3705
    if (!(vm = qemuDomObjFromDomain(dom)))
3706
        goto cleanup;
3707

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

3711 3712 3713
    maximum = (flags & VIR_DOMAIN_VCPU_MAXIMUM) != 0;
    flags &= ~VIR_DOMAIN_VCPU_MAXIMUM;

3714
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
3715 3716
                                        &persistentDef) < 0)
        goto endjob;
3717 3718 3719

    /* MAXIMUM cannot be mixed with LIVE.  */
    if (maximum && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
3720 3721
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("cannot adjust maximum on running domain"));
3722 3723 3724
        goto endjob;
    }

3725
    if (!maximum && nvcpus > vm->def->maxvcpus) {
3726 3727
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpus is greater than max allowable"
3728 3729
                         " vcpus for the domain: %d > %d"),
                       nvcpus, vm->def->maxvcpus);
3730 3731 3732
        goto endjob;
    }

3733
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
3734
        if (qemuDomainHotplugVcpus(driver, vm, nvcpus) < 0)
3735 3736 3737 3738
            goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
3739 3740 3741 3742 3743 3744 3745
        if (maximum) {
            persistentDef->maxvcpus = nvcpus;
            if (nvcpus < persistentDef->vcpus)
                persistentDef->vcpus = nvcpus;
        } else {
            persistentDef->vcpus = nvcpus;
        }
3746

3747
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
3748
            goto endjob;
3749
    }
3750

3751
    ret = 0;
3752

3753
endjob:
3754
    if (qemuDomainObjEndJob(driver, vm) == 0)
3755
        vm = NULL;
3756

3757
cleanup:
3758
    if (vm)
3759
        virObjectUnlock(vm);
3760
    virObjectUnref(caps);
3761
    virObjectUnref(cfg);
3762
    return ret;
3763 3764
}

3765
static int
3766
qemuDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
3767
{
3768
    return qemuDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE);
3769 3770
}

3771 3772

static int
3773 3774 3775 3776 3777
qemuDomainPinVcpuFlags(virDomainPtr dom,
                       unsigned int vcpu,
                       unsigned char *cpumap,
                       int maplen,
                       unsigned int flags) {
3778

3779
    virQEMUDriverPtr driver = dom->conn->privateData;
3780
    virDomainObjPtr vm;
3781
    virDomainDefPtr persistentDef = NULL;
3782
    virCgroupPtr cgroup_vcpu = NULL;
3783
    int ret = -1;
3784
    qemuDomainObjPrivatePtr priv;
3785
    bool doReset = false;
3786 3787
    int newVcpuPinNum = 0;
    virDomainVcpuPinDefPtr *newVcpuPin = NULL;
3788
    virBitmapPtr pcpumap = NULL;
3789
    virQEMUDriverConfigPtr cfg = NULL;
3790
    virCapsPtr caps = NULL;
3791

3792 3793 3794
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

3795 3796
    cfg = virQEMUDriverGetConfig(driver);

3797
    if (!(vm = qemuDomObjFromDomain(dom)))
3798 3799
        goto cleanup;

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

3803
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
3804
                                        &persistentDef) < 0)
3805
        goto cleanup;
3806

3807 3808 3809
    priv = vm->privateData;

    if (vcpu > (priv->nvcpupids-1)) {
3810 3811 3812
        virReportError(VIR_ERR_INVALID_ARG,
                       _("vcpu number out of range %d > %d"),
                       vcpu, priv->nvcpupids);
3813
        goto cleanup;
3814 3815
    }

3816 3817 3818 3819
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
        goto cleanup;

3820 3821 3822 3823 3824 3825
    if (virBitmapIsAllClear(pcpumap)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Empty cpu list for pinning"));
        goto cleanup;
    }

3826 3827 3828
    /* pinning to all physical cpus means resetting,
     * so check if we can reset setting.
     */
3829 3830
    if (virBitmapIsAllSet(pcpumap))
        doReset = true;
3831

3832
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
3833

3834
        if (priv->vcpupids == NULL) {
3835 3836
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cpu affinity is not supported"));
3837 3838 3839
            goto cleanup;
        }

3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854
        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;
        }

3855
        if (virDomainVcpuPinAdd(&newVcpuPin, &newVcpuPinNum, cpumap, maplen, vcpu) < 0) {
3856 3857
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("failed to update vcpupin"));
H
Hu Tao 已提交
3858
            virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
3859 3860 3861 3862
            goto cleanup;
        }

        /* Configure the corresponding cpuset cgroup before set affinity. */
3863
        if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
3864
            if (virCgroupNewVcpu(priv->cgroup, vcpu, false, &cgroup_vcpu) == 0 &&
3865 3866 3867 3868
                qemuSetupCgroupVcpuPin(cgroup_vcpu, newVcpuPin, newVcpuPinNum, vcpu) < 0) {
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("failed to set cpuset.cpus in cgroup"
                                 " for vcpu %d"), vcpu);
3869 3870 3871
                goto cleanup;
            }
        } else {
3872
            if (virProcessSetAffinity(priv->vcpupids[vcpu], pcpumap) < 0) {
3873 3874 3875 3876
                virReportError(VIR_ERR_SYSTEM_ERROR,
                               _("failed to set cpu affinity for vcpu %d"),
                               vcpu);
                goto cleanup;
H
Hu Tao 已提交
3877
            }
3878 3879
        }

3880
        if (doReset) {
3881
            if (virDomainVcpuPinDel(vm->def, vcpu) < 0) {
3882
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3883
                               _("failed to delete vcpupin xml of "
3884
                                 "a running domain"));
3885 3886
                goto cleanup;
            }
3887 3888
        } else {
            if (vm->def->cputune.vcpupin)
H
Hu Tao 已提交
3889
                virDomainVcpuPinDefArrayFree(vm->def->cputune.vcpupin, vm->def->cputune.nvcpupin);
3890 3891 3892 3893

            vm->def->cputune.vcpupin = newVcpuPin;
            vm->def->cputune.nvcpupin = newVcpuPinNum;
            newVcpuPin = NULL;
3894 3895
        }

3896
        if (newVcpuPin)
H
Hu Tao 已提交
3897
            virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
3898

3899
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3900
            goto cleanup;
3901
    }
3902

3903 3904
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {

3905
        if (doReset) {
E
Eric Blake 已提交
3906
            if (virDomainVcpuPinDel(persistentDef, vcpu) < 0) {
3907 3908 3909
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to delete vcpupin xml of "
                                 "a persistent domain"));
3910 3911 3912
                goto cleanup;
            }
        } else {
H
Hu Tao 已提交
3913 3914 3915 3916 3917 3918 3919
            if (!persistentDef->cputune.vcpupin) {
                if (VIR_ALLOC(persistentDef->cputune.vcpupin) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }
                persistentDef->cputune.nvcpupin = 0;
            }
3920
            if (virDomainVcpuPinAdd(&persistentDef->cputune.vcpupin,
H
Hu Tao 已提交
3921 3922 3923 3924
                                    &persistentDef->cputune.nvcpupin,
                                    cpumap,
                                    maplen,
                                    vcpu) < 0) {
3925 3926 3927
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to update or add vcpupin xml of "
                                 "a persistent domain"));
3928 3929
                goto cleanup;
            }
3930
        }
3931

3932
        ret = virDomainSaveConfig(cfg->configDir, persistentDef);
3933 3934 3935
        goto cleanup;
    }

3936
    ret = 0;
3937

3938
cleanup:
3939 3940
    if (cgroup_vcpu)
        virCgroupFree(&cgroup_vcpu);
3941
    if (vm)
3942
        virObjectUnlock(vm);
3943
    virBitmapFree(pcpumap);
3944
    virObjectUnref(caps);
3945
    virObjectUnref(cfg);
3946
    return ret;
3947 3948
}

3949
static int
3950
qemuDomainPinVcpu(virDomainPtr dom,
3951 3952 3953
                   unsigned int vcpu,
                   unsigned char *cpumap,
                   int maplen) {
3954 3955
    return qemuDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
                                  VIR_DOMAIN_AFFECT_LIVE);
3956 3957
}

3958
static int
3959 3960 3961 3962 3963
qemuDomainGetVcpuPinInfo(virDomainPtr dom,
                         int ncpumaps,
                         unsigned char *cpumaps,
                         int maplen,
                         unsigned int flags) {
3964

3965
    virQEMUDriverPtr driver = dom->conn->privateData;
E
Eric Blake 已提交
3966
    virDomainObjPtr vm = NULL;
3967 3968 3969 3970
    virDomainDefPtr targetDef = NULL;
    int ret = -1;
    int maxcpu, hostcpus, vcpu, pcpu;
    int n;
E
Eric Blake 已提交
3971
    virDomainVcpuPinDefPtr *vcpupin_list;
H
Hu Tao 已提交
3972
    virBitmapPtr cpumask = NULL;
3973
    unsigned char *cpumap;
H
Hu Tao 已提交
3974
    bool pinned;
3975
    virCapsPtr caps = NULL;
3976 3977 3978 3979

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

3980
    if (!(vm = qemuDomObjFromDomain(dom)))
3981 3982
        goto cleanup;

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

3986
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
3987 3988
                                        &targetDef) < 0)
        goto cleanup;
3989 3990 3991 3992 3993

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

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

3997
    if ((hostcpus = nodeGetCPUCount()) < 0)
3998
        goto cleanup;
3999

4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027
    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 已提交
4028 4029 4030
            if (virBitmapGetBit(cpumask, pcpu, &pinned) < 0)
                goto cleanup;
            if (!pinned)
4031 4032 4033 4034 4035 4036 4037
                VIR_UNUSE_CPU(cpumap, pcpu);
        }
    }
    ret = ncpumaps;

cleanup:
    if (vm)
4038
        virObjectUnlock(vm);
4039
    virObjectUnref(caps);
4040 4041 4042
    return ret;
}

H
Hu Tao 已提交
4043
static int
4044 4045 4046 4047
qemuDomainPinEmulator(virDomainPtr dom,
                      unsigned char *cpumap,
                      int maplen,
                      unsigned int flags)
H
Hu Tao 已提交
4048
{
4049
    virQEMUDriverPtr driver = dom->conn->privateData;
H
Hu Tao 已提交
4050 4051 4052 4053 4054 4055
    virDomainObjPtr vm;
    virCgroupPtr cgroup_emulator = NULL;
    pid_t pid;
    virDomainDefPtr persistentDef = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
4056
    bool doReset = false;
H
Hu Tao 已提交
4057 4058
    int newVcpuPinNum = 0;
    virDomainVcpuPinDefPtr *newVcpuPin = NULL;
4059
    virBitmapPtr pcpumap = NULL;
4060
    virQEMUDriverConfigPtr cfg = NULL;
4061
    virCapsPtr caps = NULL;
H
Hu Tao 已提交
4062 4063 4064 4065

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

4066 4067
    cfg = virQEMUDriverGetConfig(driver);

4068
    if (!(vm = qemuDomObjFromDomain(dom)))
H
Hu Tao 已提交
4069 4070
        goto cleanup;

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

4074 4075 4076 4077 4078 4079 4080
    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;
    }

4081
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
H
Hu Tao 已提交
4082 4083 4084 4085 4086
                                        &persistentDef) < 0)
        goto cleanup;

    priv = vm->privateData;

4087 4088 4089 4090
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
        goto cleanup;

4091 4092 4093 4094 4095 4096
    if (virBitmapIsAllClear(pcpumap)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Empty cpu list for pinning"));
        goto cleanup;
    }

H
Hu Tao 已提交
4097 4098 4099
    /* pinning to all physical cpus means resetting,
     * so check if we can reset setting.
     */
4100 4101
    if (virBitmapIsAllSet(pcpumap))
        doReset = true;
H
Hu Tao 已提交
4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112

    pid = vm->pid;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {

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

4113
            if (virDomainVcpuPinAdd(&newVcpuPin, &newVcpuPinNum, cpumap, maplen, -1) < 0) {
H
Hu Tao 已提交
4114 4115
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to update vcpupin"));
H
Hu Tao 已提交
4116
                virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
H
Hu Tao 已提交
4117 4118 4119
                goto cleanup;
            }

4120 4121
            if (virCgroupHasController(priv->cgroup,
                                       VIR_CGROUP_CONTROLLER_CPUSET)) {
H
Hu Tao 已提交
4122 4123 4124 4125
                /*
                 * Configure the corresponding cpuset cgroup.
                 * If no cgroup for domain or hypervisor exists, do nothing.
                 */
4126
                if (virCgroupNewEmulator(priv->cgroup, false, &cgroup_emulator) == 0) {
4127 4128 4129 4130 4131 4132
                    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 已提交
4133 4134 4135
                    }
                }
            } else {
4136
                if (virProcessSetAffinity(pid, pcpumap) < 0) {
H
Hu Tao 已提交
4137 4138 4139 4140 4141 4142 4143
                    virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
                                   _("failed to set cpu affinity for "
                                     "emulator threads"));
                    goto cleanup;
                }
            }

4144
            if (doReset) {
H
Hu Tao 已提交
4145 4146 4147 4148 4149 4150 4151
                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 已提交
4152
                virDomainVcpuPinDefFree(vm->def->cputune.emulatorpin);
H
Hu Tao 已提交
4153 4154 4155 4156 4157
                vm->def->cputune.emulatorpin = newVcpuPin[0];
                VIR_FREE(newVcpuPin);
            }

            if (newVcpuPin)
H
Hu Tao 已提交
4158
                virDomainVcpuPinDefArrayFree(newVcpuPin, newVcpuPinNum);
H
Hu Tao 已提交
4159 4160 4161 4162 4163 4164
        } else {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cpu affinity is not supported"));
            goto cleanup;
        }

4165
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
H
Hu Tao 已提交
4166 4167 4168 4169 4170
            goto cleanup;
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {

4171
        if (doReset) {
H
Hu Tao 已提交
4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186
            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;
            }
        }

4187
        ret = virDomainSaveConfig(cfg->configDir, persistentDef);
H
Hu Tao 已提交
4188 4189 4190 4191 4192 4193 4194 4195
        goto cleanup;
    }

    ret = 0;

cleanup:
    if (cgroup_emulator)
        virCgroupFree(&cgroup_emulator);
4196
    virBitmapFree(pcpumap);
4197
    virObjectUnref(caps);
H
Hu Tao 已提交
4198
    if (vm)
4199
        virObjectUnlock(vm);
4200
    virObjectUnref(cfg);
H
Hu Tao 已提交
4201 4202 4203 4204
    return ret;
}

static int
4205 4206 4207 4208
qemuDomainGetEmulatorPinInfo(virDomainPtr dom,
                             unsigned char *cpumaps,
                             int maplen,
                             unsigned int flags)
H
Hu Tao 已提交
4209
{
4210
    virQEMUDriverPtr driver = dom->conn->privateData;
H
Hu Tao 已提交
4211 4212 4213 4214
    virDomainObjPtr vm = NULL;
    virDomainDefPtr targetDef = NULL;
    int ret = -1;
    int maxcpu, hostcpus, pcpu;
H
Hu Tao 已提交
4215 4216
    virBitmapPtr cpumask = NULL;
    bool pinned;
4217
    virCapsPtr caps = NULL;
H
Hu Tao 已提交
4218 4219 4220 4221

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

4222
    if (!(vm = qemuDomObjFromDomain(dom)))
H
Hu Tao 已提交
4223 4224
        goto cleanup;

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

4228
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
4229
                                        vm, &flags, &targetDef) < 0)
H
Hu Tao 已提交
4230 4231 4232 4233 4234 4235 4236 4237
        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);

4238
    if ((hostcpus = nodeGetCPUCount()) < 0)
H
Hu Tao 已提交
4239
        goto cleanup;
4240

H
Hu Tao 已提交
4241 4242 4243 4244 4245 4246 4247 4248 4249 4250
    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

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

4251 4252 4253 4254 4255
    if (targetDef->cputune.emulatorpin) {
        cpumask = targetDef->cputune.emulatorpin->cpumask;
    } else if (targetDef->cpumask) {
        cpumask = targetDef->cpumask;
    } else {
H
Hu Tao 已提交
4256 4257 4258 4259 4260
        ret = 0;
        goto cleanup;
    }

    for (pcpu = 0; pcpu < maxcpu; pcpu++) {
H
Hu Tao 已提交
4261 4262 4263
        if (virBitmapGetBit(cpumask, pcpu, &pinned) < 0)
            goto cleanup;
        if (!pinned)
H
Hu Tao 已提交
4264 4265 4266 4267 4268 4269 4270
            VIR_UNUSE_CPU(cpumaps, pcpu);
    }

    ret = 1;

cleanup:
    if (vm)
4271
        virObjectUnlock(vm);
4272
    virObjectUnref(caps);
H
Hu Tao 已提交
4273 4274 4275
    return ret;
}

4276
static int
4277 4278 4279 4280 4281
qemuDomainGetVcpus(virDomainPtr dom,
                   virVcpuInfoPtr info,
                   int maxinfo,
                   unsigned char *cpumaps,
                   int maplen) {
4282
    virDomainObjPtr vm;
4283
    int i, v, maxcpu, hostcpus;
4284
    int ret = -1;
4285
    qemuDomainObjPrivatePtr priv;
4286

4287
    if (!(vm = qemuDomObjFromDomain(dom)))
4288 4289
        goto cleanup;

D
Daniel P. Berrange 已提交
4290
    if (!virDomainObjIsActive(vm)) {
4291 4292 4293
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",
                       _("cannot list vcpu pinning for an inactive domain"));
4294
        goto cleanup;
4295 4296
    }

4297 4298
    priv = vm->privateData;

4299
    if ((hostcpus = nodeGetCPUCount()) < 0)
4300
        goto cleanup;
4301 4302

    maxcpu = maplen * 8;
4303 4304
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;
4305 4306

    /* Clamp to actual number of vcpus */
4307 4308
    if (maxinfo > priv->nvcpupids)
        maxinfo = priv->nvcpupids;
4309

4310 4311 4312 4313 4314 4315
    if (maxinfo >= 1) {
        if (info != NULL) {
            memset(info, 0, sizeof(*info) * maxinfo);
            for (i = 0 ; i < maxinfo ; i++) {
                info[i].number = i;
                info[i].state = VIR_VCPU_RUNNING;
4316

4317
                if (priv->vcpupids != NULL &&
4318 4319 4320 4321 4322
                    qemuGetProcessInfo(&(info[i].cpuTime),
                                       &(info[i].cpu),
                                       NULL,
                                       vm->pid,
                                       priv->vcpupids[i]) < 0) {
4323
                    virReportSystemError(errno, "%s",
4324 4325 4326
                                         _("cannot get vCPU placement & pCPU time"));
                    goto cleanup;
                }
4327
            }
4328 4329
        }

4330 4331
        if (cpumaps != NULL) {
            memset(cpumaps, 0, maplen * maxinfo);
4332
            if (priv->vcpupids != NULL) {
4333 4334
                for (v = 0 ; v < maxinfo ; v++) {
                    unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
4335 4336 4337
                    virBitmapPtr map = NULL;
                    unsigned char *tmpmap = NULL;
                    int tmpmapLen = 0;
4338

4339 4340
                    if (virProcessGetAffinity(priv->vcpupids[v],
                                              &map, maxcpu) < 0)
4341
                        goto cleanup;
4342 4343 4344 4345 4346 4347 4348
                    virBitmapToData(map, &tmpmap, &tmpmapLen);
                    if (tmpmapLen > maplen)
                        tmpmapLen = maplen;
                    memcpy(cpumap, tmpmap, tmpmapLen);

                    VIR_FREE(tmpmap);
                    virBitmapFree(map);
4349
                }
4350
            } else {
4351 4352
                virReportError(VIR_ERR_OPERATION_INVALID,
                               "%s", _("cpu affinity is not available"));
4353
                goto cleanup;
4354 4355 4356
            }
        }
    }
4357
    ret = maxinfo;
4358

4359
cleanup:
4360
    if (vm)
4361
        virObjectUnlock(vm);
4362
    return ret;
4363 4364 4365
}


4366
static int
4367
qemuDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
4368
{
4369
    virQEMUDriverPtr driver = dom->conn->privateData;
4370
    virDomainObjPtr vm;
4371
    virDomainDefPtr def;
4372
    int ret = -1;
4373
    virCapsPtr caps = NULL;
4374

4375 4376
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
4377 4378
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

4379
    if (!(vm = qemuDomObjFromDomain(dom)))
4380
        goto cleanup;
4381

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

4385
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt,
4386
                                        vm, &flags, &def) < 0)
4387
        goto cleanup;
4388

4389
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
4390
        def = vm->def;
4391 4392
    }

4393
    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
4394

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

4402
static int
4403
qemuDomainGetMaxVcpus(virDomainPtr dom)
4404
{
4405 4406
    return qemuDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
                                         VIR_DOMAIN_VCPU_MAXIMUM));
4407 4408
}

4409
static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
4410
{
4411
    virQEMUDriverPtr driver = dom->conn->privateData;
4412 4413 4414
    virDomainObjPtr vm;
    int ret = -1;

4415 4416
    memset(seclabel, 0, sizeof(*seclabel));

4417 4418
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
4419

4420
    if (!virDomainVirtTypeToString(vm->def->virtType)) {
4421 4422 4423
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown virt type in domain definition '%d'"),
                       vm->def->virtType);
4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440
        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 已提交
4441
    if (virDomainObjIsActive(vm)) {
4442
        if (virSecurityManagerGetProcessLabel(driver->securityManager,
4443
                                              vm->def, vm->pid, seclabel) < 0) {
4444 4445
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Failed to get security label"));
4446
            goto cleanup;
4447 4448 4449 4450 4451 4452 4453
        }
    }

    ret = 0;

cleanup:
    if (vm)
4454
        virObjectUnlock(vm);
4455 4456 4457
    return ret;
}

M
Marcelo Cerri 已提交
4458 4459 4460
static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
                                          virSecurityLabelPtr* seclabels)
{
4461
    virQEMUDriverPtr driver = dom->conn->privateData;
M
Marcelo Cerri 已提交
4462 4463 4464
    virDomainObjPtr vm;
    int i, ret = -1;

4465 4466
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
M
Marcelo Cerri 已提交
4467 4468 4469 4470 4471 4472 4473 4474 4475

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

    /*
4476
     * Check the comment in qemuDomainGetSecurityLabel function.
M
Marcelo Cerri 已提交
4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516
     */
    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)
4517
        virObjectUnlock(vm);
M
Marcelo Cerri 已提交
4518 4519
    return ret;
}
4520 4521


4522 4523
static int qemuNodeGetSecurityModel(virConnectPtr conn,
                                    virSecurityModelPtr secmodel)
4524
{
4525
    virQEMUDriverPtr driver = conn->privateData;
4526
    char *p;
4527
    int ret = 0;
4528
    virCapsPtr caps = NULL;
4529

4530 4531
    memset(secmodel, 0, sizeof(*secmodel));

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

4535
    /* We treat no driver as success, but simply return no data in *secmodel */
4536 4537
    if (caps->host.nsecModels == 0 ||
        caps->host.secModels[0].model == NULL)
4538
        goto cleanup;
4539

4540
    p = caps->host.secModels[0].model;
4541
    if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
4542 4543 4544
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("security model string exceeds max %d bytes"),
                       VIR_SECURITY_MODEL_BUFLEN-1);
4545 4546
        ret = -1;
        goto cleanup;
4547 4548 4549
    }
    strcpy(secmodel->model, p);

4550
    p = caps->host.secModels[0].doi;
4551
    if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
4552 4553 4554
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("security DOI string exceeds max %d bytes"),
                       VIR_SECURITY_DOI_BUFLEN-1);
4555 4556
        ret = -1;
        goto cleanup;
4557 4558
    }
    strcpy(secmodel->doi, p);
4559 4560

cleanup:
4561
    virObjectUnref(caps);
4562
    return ret;
4563 4564
}

E
Eric Blake 已提交
4565
/* Return -1 on most failures after raising error, -2 if edit was specified
4566 4567 4568
 * 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.  */
4569
static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
4570
qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
4571 4572
                        const char *path,
                        virDomainDefPtr *ret_def,
4573
                        virQEMUSaveHeaderPtr ret_header,
J
Jiri Denemark 已提交
4574 4575
                        bool bypass_cache,
                        virFileWrapperFdPtr *wrapperFd,
4576 4577
                        const char *xmlin, int state, bool edit,
                        bool unlink_corrupt)
J
Jiri Denemark 已提交
4578
{
W
Wen Congyang 已提交
4579
    int fd = -1;
4580
    virQEMUSaveHeader header;
J
Jiri Denemark 已提交
4581 4582
    char *xml = NULL;
    virDomainDefPtr def = NULL;
4583
    int oflags = edit ? O_RDWR : O_RDONLY;
4584
    virCapsPtr caps = NULL;
4585

4586
    if (bypass_cache) {
4587
        int directFlag = virFileDirectFdFlag();
4588
        if (directFlag < 0) {
4589 4590
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("bypass cache unsupported by this system"));
4591 4592
            goto error;
        }
4593
        oflags |= directFlag;
4594
    }
4595

4596 4597 4598
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto error;

E
Eric Blake 已提交
4599 4600
    if ((fd = qemuOpenFile(driver, path, oflags, NULL, NULL)) < 0)
        goto error;
J
Jiri Denemark 已提交
4601 4602 4603
    if (bypass_cache &&
        !(*wrapperFd = virFileWrapperFdNew(&fd, path,
                                           VIR_FILE_WRAPPER_BYPASS_CACHE)))
4604
        goto error;
4605 4606

    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
4607 4608 4609 4610 4611 4612 4613 4614 4615
        if (unlink_corrupt) {
            if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
                virReportSystemError(errno,
                                     _("cannot remove corrupt file: %s"),
                                     path);
                goto error;
            }
            return -3;
        }
4616 4617
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("failed to read qemu header"));
J
Jiri Denemark 已提交
4618
        goto error;
4619 4620
    }

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

4624
        if (memcmp(header.magic, QEMU_SAVE_PARTIAL,
E
Eric Blake 已提交
4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636
                   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;
            }
        }
4637
        virReportError(VIR_ERR_OPERATION_FAILED, "%s", msg);
J
Jiri Denemark 已提交
4638
        goto error;
4639 4640
    }

4641
    if (header.version > QEMU_SAVE_VERSION) {
4642 4643 4644 4645
        /* convert endianess and try again */
        bswap_header(&header);
    }

4646
    if (header.version > QEMU_SAVE_VERSION) {
4647 4648
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("image version is not supported (%d > %d)"),
4649
                       header.version, QEMU_SAVE_VERSION);
J
Jiri Denemark 已提交
4650
        goto error;
4651 4652
    }

4653
    if (header.xml_len <= 0) {
4654 4655
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("invalid XML length: %d"), header.xml_len);
J
Jiri Denemark 已提交
4656
        goto error;
4657 4658
    }

4659 4660
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
        virReportOOMError();
J
Jiri Denemark 已提交
4661
        goto error;
4662 4663 4664
    }

    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
4665 4666
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("failed to read XML"));
J
Jiri Denemark 已提交
4667
        goto error;
4668 4669
    }

4670 4671
    if (edit && STREQ(xml, xmlin) &&
        (state < 0 || state == header.was_running)) {
4672 4673 4674 4675 4676 4677 4678
        VIR_FREE(xml);
        if (VIR_CLOSE(fd) < 0) {
            virReportSystemError(errno, _("cannot close file: %s"), path);
            goto error;
        }
        return -2;
    }
4679 4680
    if (state >= 0)
        header.was_running = state;
4681

4682
    /* Create a domain from this XML */
4683
    if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
M
Matthias Bolte 已提交
4684
                                        QEMU_EXPECTED_VIRT_TYPES,
4685
                                        VIR_DOMAIN_XML_INACTIVE)))
J
Jiri Denemark 已提交
4686
        goto error;
4687 4688 4689
    if (xmlin) {
        virDomainDefPtr def2 = NULL;

4690
        if (!(def2 = virDomainDefParseString(xmlin, caps, driver->xmlopt,
4691 4692 4693 4694 4695 4696 4697 4698 4699 4700
                                             QEMU_EXPECTED_VIRT_TYPES,
                                             VIR_DOMAIN_XML_INACTIVE)))
            goto error;
        if (!virDomainDefCheckABIStability(def, def2)) {
            virDomainDefFree(def2);
            goto error;
        }
        virDomainDefFree(def);
        def = def2;
    }
4701

J
Jiri Denemark 已提交
4702
    VIR_FREE(xml);
4703

J
Jiri Denemark 已提交
4704 4705
    *ret_def = def;
    *ret_header = header;
4706

4707 4708
    virObjectUnref(caps);

J
Jiri Denemark 已提交
4709
    return fd;
4710

J
Jiri Denemark 已提交
4711 4712 4713
error:
    virDomainDefFree(def);
    VIR_FREE(xml);
4714
    VIR_FORCE_CLOSE(fd);
4715
    virObjectUnref(caps);
J
Jiri Denemark 已提交
4716 4717 4718 4719

    return -1;
}

4720 4721
static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6)
qemuDomainSaveImageStartVM(virConnectPtr conn,
4722
                           virQEMUDriverPtr driver,
4723 4724
                           virDomainObjPtr vm,
                           int *fd,
4725
                           const virQEMUSaveHeaderPtr header,
4726 4727
                           const char *path,
                           bool start_paused)
J
Jiri Denemark 已提交
4728 4729 4730 4731
{
    int ret = -1;
    virDomainEventPtr event;
    int intermediatefd = -1;
4732
    virCommandPtr cmd = NULL;
4733
    char *errbuf = NULL;
4734
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
J
Jiri Denemark 已提交
4735

4736 4737 4738
    if ((header->version == 2) &&
        (header->compressed != QEMU_SAVE_FORMAT_RAW)) {
        if (!(cmd = qemuCompressGetCommand(header->compressed)))
4739
            goto cleanup;
4740

4741 4742
        intermediatefd = *fd;
        *fd = -1;
4743

4744 4745 4746 4747
        virCommandSetInputFD(cmd, intermediatefd);
        virCommandSetOutputFD(cmd, fd);
        virCommandSetErrorBuffer(cmd, &errbuf);
        virCommandDoAsyncIO(cmd);
4748

4749 4750 4751
        if (virCommandRunAsync(cmd, NULL) < 0) {
            *fd = intermediatefd;
            goto cleanup;
4752 4753
        }
    }
J
Jiri Denemark 已提交
4754

4755
    /* Set the migration source and start it up. */
4756 4757 4758
    ret = qemuProcessStart(conn, driver, vm, "stdio", *fd, path, NULL,
                           VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
                           VIR_QEMU_PROCESS_START_PAUSED);
J
Jiri Denemark 已提交
4759

4760
    if (intermediatefd != -1) {
4761
        if (ret < 0) {
4762 4763 4764
            /* if there was an error setting up qemu, the intermediate
             * process will wait forever to write to stdout, so we
             * must manually kill it.
4765 4766
             */
            VIR_FORCE_CLOSE(intermediatefd);
4767
            VIR_FORCE_CLOSE(*fd);
4768 4769
        }

4770 4771
        if (virCommandWait(cmd, NULL) < 0) {
            qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0);
4772
            ret = -1;
4773
        }
4774
        VIR_DEBUG("Decompression binary stderr: %s", NULLSTR(errbuf));
4775
    }
4776
    VIR_FORCE_CLOSE(intermediatefd);
J
Jiri Denemark 已提交
4777

4778 4779 4780
    if (VIR_CLOSE(*fd) < 0) {
        virReportSystemError(errno, _("cannot close file: %s"), path);
        ret = -1;
4781
    }
J
Jiri Denemark 已提交
4782

4783
    if (ret < 0) {
4784
        virDomainAuditStart(vm, "restored", false);
4785
        goto cleanup;
4786
    }
4787

4788 4789 4790
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
4791
    virDomainAuditStart(vm, "restored", true);
J
Jiri Denemark 已提交
4792 4793 4794
    if (event)
        qemuDomainEventQueue(driver, event);

4795

4796 4797
    /* If it was running before, resume it now unless caller requested pause. */
    if (header->was_running && !start_paused) {
J
Jiri Denemark 已提交
4798
        if (qemuProcessStartCPUs(driver, vm, conn,
4799 4800
                                 VIR_DOMAIN_RUNNING_RESTORED,
                                 QEMU_ASYNC_JOB_NONE) < 0) {
4801
            if (virGetLastError() == NULL)
4802 4803
                virReportError(VIR_ERR_OPERATION_FAILED,
                               "%s", _("failed to resume domain"));
4804
            goto cleanup;
4805
        }
4806
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
4807
            VIR_WARN("Failed to save status on vm %s", vm->def->name);
4808
            goto cleanup;
4809
        }
4810 4811 4812 4813 4814 4815 4816 4817
    } 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);
4818
    }
J
Jiri Denemark 已提交
4819

4820
    ret = 0;
4821

4822
cleanup:
4823
    virCommandFree(cmd);
4824
    VIR_FREE(errbuf);
4825
    if (virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
4826
                                                 vm->def, path) < 0)
4827
        VIR_WARN("failed to restore save state label on %s", path);
4828
    virObjectUnref(cfg);
J
Jiri Denemark 已提交
4829 4830 4831
    return ret;
}

4832
static int
4833 4834 4835 4836
qemuDomainRestoreFlags(virConnectPtr conn,
                       const char *path,
                       const char *dxml,
                       unsigned int flags)
4837
{
4838
    virQEMUDriverPtr driver = conn->privateData;
J
Jiri Denemark 已提交
4839 4840 4841 4842
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    int fd = -1;
    int ret = -1;
4843
    virQEMUSaveHeader header;
J
Jiri Denemark 已提交
4844
    virFileWrapperFdPtr wrapperFd = NULL;
4845
    int state = -1;
J
Jiri Denemark 已提交
4846

4847 4848 4849
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                  VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
4850

J
Jiri Denemark 已提交
4851

4852 4853 4854 4855 4856
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
        state = 1;
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
        state = 0;

4857 4858
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
                                 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
J
Jiri Denemark 已提交
4859
                                 &wrapperFd, dxml, state, false, false);
J
Jiri Denemark 已提交
4860 4861 4862
    if (fd < 0)
        goto cleanup;

4863
    if (!(vm = virDomainObjListAdd(driver->domains, def,
4864
                                   driver->xmlopt,
4865 4866 4867
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jiri Denemark 已提交
4868 4869 4870
        goto cleanup;
    def = NULL;

4871
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
J
Jiri Denemark 已提交
4872 4873
        goto cleanup;

4874 4875
    ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path,
                                     false);
J
Jiri Denemark 已提交
4876
    if (virFileWrapperFdClose(wrapperFd) < 0)
4877
        VIR_WARN("Failed to close %s", path);
J
Jiri Denemark 已提交
4878

4879
    if (qemuDomainObjEndJob(driver, vm) == 0)
4880
        vm = NULL;
J
Jiri Denemark 已提交
4881
    else if (ret < 0 && !vm->persistent) {
4882
        qemuDomainRemoveInactive(driver, vm);
J
Jiri Denemark 已提交
4883 4884
        vm = NULL;
    }
4885

4886 4887
cleanup:
    virDomainDefFree(def);
4888
    VIR_FORCE_CLOSE(fd);
J
Jiri Denemark 已提交
4889
    virFileWrapperFdFree(wrapperFd);
4890
    if (vm)
4891
        virObjectUnlock(vm);
4892
    return ret;
D
Daniel P. Berrange 已提交
4893 4894
}

4895 4896 4897 4898 4899 4900 4901
static int
qemuDomainRestore(virConnectPtr conn,
                  const char *path)
{
    return qemuDomainRestoreFlags(conn, path, NULL, 0);
}

4902 4903 4904 4905
static char *
qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
                              unsigned int flags)
{
4906
    virQEMUDriverPtr driver = conn->privateData;
4907 4908 4909
    char *ret = NULL;
    virDomainDefPtr def = NULL;
    int fd = -1;
4910
    virQEMUSaveHeader header;
4911 4912 4913 4914 4915

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

    fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
4916
                                 NULL, -1, false, false);
4917 4918 4919 4920

    if (fd < 0)
        goto cleanup;

4921
    ret = qemuDomainDefFormatXML(driver, def, flags);
4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932

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

static int
qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
                             const char *dxml, unsigned int flags)
{
4933
    virQEMUDriverPtr driver = conn->privateData;
4934 4935 4936
    int ret = -1;
    virDomainDefPtr def = NULL;
    int fd = -1;
4937
    virQEMUSaveHeader header;
4938 4939
    char *xml = NULL;
    size_t len;
4940
    int state = -1;
4941

4942 4943
    virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);
4944

4945 4946 4947 4948 4949
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
        state = 1;
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
        state = 0;

4950
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
4951
                                 dxml, state, true, false);
4952 4953 4954 4955 4956 4957 4958 4959

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

4960 4961
    xml = qemuDomainDefFormatXML(driver, def,
                                 VIR_DOMAIN_XML_INACTIVE |
4962 4963
                                 VIR_DOMAIN_XML_SECURE |
                                 VIR_DOMAIN_XML_MIGRATABLE);
4964 4965 4966 4967 4968
    if (!xml)
        goto cleanup;
    len = strlen(xml) + 1;

    if (len > header.xml_len) {
4969 4970
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("new xml too large to fit in file"));
4971 4972 4973 4974 4975 4976 4977
        goto cleanup;
    }
    if (VIR_EXPAND_N(xml, len, header.xml_len - len) < 0) {
        virReportOOMError();
        goto cleanup;
    }

4978
    if (lseek(fd, 0, SEEK_SET) != 0) {
4979 4980 4981
        virReportSystemError(errno, _("cannot seek in '%s'"), path);
        goto cleanup;
    }
4982 4983
    if (safewrite(fd, &header, sizeof(header)) != sizeof(header) ||
        safewrite(fd, xml, len) != len ||
4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997
        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 已提交
4998 4999
/* Return 0 on success, 1 if incomplete saved image was silently unlinked,
 * and -1 on failure with error raised.  */
5000 5001
static int
qemuDomainObjRestore(virConnectPtr conn,
5002
                     virQEMUDriverPtr driver,
5003
                     virDomainObjPtr vm,
5004
                     const char *path,
5005
                     bool start_paused,
5006
                     bool bypass_cache)
J
Jiri Denemark 已提交
5007 5008 5009 5010
{
    virDomainDefPtr def = NULL;
    int fd = -1;
    int ret = -1;
5011
    virQEMUSaveHeader header;
J
Jiri Denemark 已提交
5012
    virFileWrapperFdPtr wrapperFd = NULL;
J
Jiri Denemark 已提交
5013

5014
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
J
Jiri Denemark 已提交
5015
                                 bypass_cache, &wrapperFd, NULL, -1, false,
5016
                                 true);
E
Eric Blake 已提交
5017 5018 5019
    if (fd < 0) {
        if (fd == -3)
            ret = 1;
J
Jiri Denemark 已提交
5020
        goto cleanup;
E
Eric Blake 已提交
5021
    }
J
Jiri Denemark 已提交
5022 5023 5024 5025 5026 5027 5028

    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);
5029 5030 5031 5032 5033
        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 已提交
5034 5035 5036
        goto cleanup;
    }

5037
    virDomainObjAssignDef(vm, def, true, NULL);
J
Jiri Denemark 已提交
5038 5039
    def = NULL;

5040 5041
    ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path,
                                     start_paused);
J
Jiri Denemark 已提交
5042
    if (virFileWrapperFdClose(wrapperFd) < 0)
5043
        VIR_WARN("Failed to close %s", path);
J
Jiri Denemark 已提交
5044 5045 5046

cleanup:
    virDomainDefFree(def);
5047
    VIR_FORCE_CLOSE(fd);
J
Jiri Denemark 已提交
5048
    virFileWrapperFdFree(wrapperFd);
J
Jiri Denemark 已提交
5049 5050 5051
    return ret;
}

D
Daniel P. Berrange 已提交
5052

5053
static char *qemuDomainGetXMLDesc(virDomainPtr dom,
5054 5055
                                  unsigned int flags)
{
5056
    virQEMUDriverPtr driver = dom->conn->privateData;
5057 5058
    virDomainObjPtr vm;
    char *ret = NULL;
5059
    unsigned long long balloon;
5060
    int err = 0;
5061
    qemuDomainObjPrivatePtr priv;
5062

5063
    /* Flags checked by virDomainDefFormat */
5064

5065
    if (!(vm = qemuDomObjFromDomain(dom)))
5066
        goto cleanup;
D
Daniel P. Berrange 已提交
5067

5068 5069
    priv = vm->privateData;

5070 5071 5072
    /* Refresh current memory based on balloon info if supported */
    if ((vm->def->memballoon != NULL) &&
        (vm->def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE) &&
5073
        !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BALLOON_EVENT) &&
5074
        (virDomainObjIsActive(vm))) {
5075 5076
        /* Don't delay if someone's using the monitor, just use
         * existing most recent data instead */
5077
        if (qemuDomainJobAllowed(priv, QEMU_JOB_QUERY)) {
5078
            if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
5079 5080
                goto cleanup;

5081
            if (!virDomainObjIsActive(vm)) {
5082 5083
                virReportError(VIR_ERR_OPERATION_INVALID,
                               "%s", _("domain is not running"));
5084 5085 5086
                goto endjob;
            }

5087
            qemuDomainObjEnterMonitor(driver, vm);
5088
            err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
5089
            qemuDomainObjExitMonitor(driver, vm);
5090 5091

endjob:
5092
            if (qemuDomainObjEndJob(driver, vm) == 0) {
5093 5094 5095
                vm = NULL;
                goto cleanup;
            }
5096 5097 5098
            if (err < 0)
                goto cleanup;
            if (err > 0)
5099
                vm->def->mem.cur_balloon = balloon;
5100 5101
            /* err == 0 indicates no balloon support, so ignore it */
        }
5102
    }
5103

5104 5105 5106 5107
    if ((flags & VIR_DOMAIN_XML_MIGRATABLE))
        flags |= QEMU_DOMAIN_FORMAT_LIVE_FLAGS;

    ret = qemuDomainFormatXML(driver, vm, flags);
5108 5109

cleanup:
5110
    if (vm)
5111
        virObjectUnlock(vm);
5112
    return ret;
D
Daniel P. Berrange 已提交
5113 5114 5115
}


5116 5117 5118
static char *qemuDomainXMLFromNative(virConnectPtr conn,
                                     const char *format,
                                     const char *config,
E
Eric Blake 已提交
5119 5120
                                     unsigned int flags)
{
5121
    virQEMUDriverPtr driver = conn->privateData;
5122 5123
    virDomainDefPtr def = NULL;
    char *xml = NULL;
5124
    virCapsPtr caps = NULL;
5125

E
Eric Blake 已提交
5126 5127
    virCheckFlags(0, NULL);

5128
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
5129 5130
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
5131 5132 5133
        goto cleanup;
    }

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

5137
    def = qemuParseCommandLineString(caps, driver->xmlopt, config,
5138
                                     NULL, NULL, NULL);
5139 5140 5141
    if (!def)
        goto cleanup;

5142 5143 5144 5145 5146 5147
    if (!def->name &&
        !(def->name = strdup("unnamed"))) {
        virReportOOMError();
        goto cleanup;
    }

5148
    xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE);
5149 5150 5151

cleanup:
    virDomainDefFree(def);
5152
    virObjectUnref(caps);
5153 5154 5155
    return xml;
}

5156 5157 5158
static char *qemuDomainXMLToNative(virConnectPtr conn,
                                   const char *format,
                                   const char *xmlData,
E
Eric Blake 已提交
5159 5160
                                   unsigned int flags)
{
5161
    virQEMUDriverPtr driver = conn->privateData;
5162
    virDomainDefPtr def = NULL;
5163
    virDomainChrSourceDef monConfig;
5164
    virQEMUCapsPtr qemuCaps = NULL;
T
tangchen 已提交
5165
    bool monitor_json = false;
E
Eric Blake 已提交
5166
    virCommandPtr cmd = NULL;
5167 5168
    char *ret = NULL;
    int i;
5169
    virQEMUDriverConfigPtr cfg;
5170
    virCapsPtr caps = NULL;
5171

E
Eric Blake 已提交
5172 5173
    virCheckFlags(0, NULL);

5174
    cfg = virQEMUDriverGetConfig(driver);
5175

5176
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
5177 5178
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
5179 5180 5181
        goto cleanup;
    }

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

5185
    def = virDomainDefParseString(xmlData, caps, driver->xmlopt,
M
Matthias Bolte 已提交
5186
                                  QEMU_EXPECTED_VIRT_TYPES, 0);
5187 5188 5189
    if (!def)
        goto cleanup;

5190
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
5191 5192
        goto cleanup;

5193 5194
    /* Since we're just exporting args, we can't do bridge/network/direct
     * setups, since libvirt will normally create TAP/macvtap devices
5195 5196 5197 5198 5199
     * directly. We convert those configs into generic 'ethernet'
     * config and assume the user has suitable 'ifup-qemu' scripts
     */
    for (i = 0 ; i < def->nnets ; i++) {
        virDomainNetDefPtr net = def->nets[i];
5200
        int bootIndex = net->info.bootIndex;
5201 5202
        char *model = net->model;

5203 5204 5205 5206
        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
            int actualType = virDomainNetGetActualType(net);
            const char *brname;

5207
            VIR_FREE(net->data.network.name);
5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219
            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);

5220
                memset(net, 0, sizeof(*net));
5221 5222

                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5223
                net->script = NULL;
5224 5225 5226 5227 5228 5229 5230
                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);
5231
                memset(net, 0, sizeof(*net));
5232 5233

                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5234
                net->script = NULL;
5235 5236 5237 5238 5239
                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);
5240

5241
            memset(net, 0, sizeof(*net));
5242 5243

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5244
            net->script = NULL;
5245 5246 5247
            net->data.ethernet.dev = NULL;
            net->data.ethernet.ipaddr = NULL;
        } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
5248
            char *script = net->script;
5249 5250 5251
            char *brname = net->data.bridge.brname;
            char *ipaddr = net->data.bridge.ipaddr;

5252
            memset(net, 0, sizeof(*net));
5253 5254

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
5255
            net->script = script;
5256 5257 5258
            net->data.ethernet.dev = brname;
            net->data.ethernet.ipaddr = ipaddr;
        }
5259

5260
        VIR_FREE(net->virtPortProfile);
5261
        net->info.bootIndex = bootIndex;
5262
        net->model = model;
5263 5264
    }

5265
    monitor_json = virQEMUCapsGet(qemuCaps, QEMU_CAPS_MONITOR_JSON);
T
tangchen 已提交
5266

5267
    if (qemuProcessPrepareMonitorChr(cfg, &monConfig, def->name) < 0)
5268
        goto cleanup;
5269

5270
    if (qemuAssignDeviceAliases(def, qemuCaps) < 0)
5271 5272
        goto cleanup;

5273
    if (!(cmd = qemuBuildCommandLine(conn, driver, def,
5274
                                     &monConfig, monitor_json, qemuCaps,
5275
                                     NULL, -1, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP)))
5276 5277
        goto cleanup;

E
Eric Blake 已提交
5278
    ret = virCommandToString(cmd);
5279 5280 5281

cleanup:

5282
    virObjectUnref(qemuCaps);
E
Eric Blake 已提交
5283
    virCommandFree(cmd);
5284
    virDomainDefFree(def);
5285
    virObjectUnref(caps);
5286
    virObjectUnref(cfg);
5287 5288 5289 5290
    return ret;
}


5291 5292
static int qemuListDefinedDomains(virConnectPtr conn,
                                  char **const names, int nnames) {
5293
    virQEMUDriverPtr driver = conn->privateData;
5294
    int n;
5295

5296
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames);
5297
    return n;
D
Daniel P. Berrange 已提交
5298 5299
}

5300
static int qemuNumDefinedDomains(virConnectPtr conn) {
5301
    virQEMUDriverPtr driver = conn->privateData;
5302
    int n;
5303

5304
    n = virDomainObjListNumOfDomains(driver->domains, 0);
5305

5306
    return n;
D
Daniel P. Berrange 已提交
5307 5308 5309
}


5310 5311
static int
qemuDomainObjStart(virConnectPtr conn,
5312
                   virQEMUDriverPtr driver,
5313
                   virDomainObjPtr vm,
5314
                   unsigned int flags)
J
Jiri Denemark 已提交
5315 5316 5317
{
    int ret = -1;
    char *managed_save;
5318 5319 5320 5321
    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;
5322 5323 5324
    unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;

    start_flags |= start_paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
5325
    start_flags |= autodestroy ? VIR_QEMU_PROCESS_START_AUTODESTROY : 0;
J
Jiri Denemark 已提交
5326 5327 5328

    /*
     * If there is a managed saved state restore it instead of starting
5329
     * from scratch. The old state is removed once the restoring succeeded.
J
Jiri Denemark 已提交
5330 5331
     */
    managed_save = qemuDomainManagedSavePath(driver, vm);
5332 5333 5334 5335

    if (!managed_save)
        goto cleanup;

E
Eric Blake 已提交
5336
    if (virFileExists(managed_save)) {
5337 5338 5339 5340 5341 5342 5343
        if (force_boot) {
            if (unlink(managed_save) < 0) {
                virReportSystemError(errno,
                                     _("cannot remove managed save file %s"),
                                     managed_save);
                goto cleanup;
            }
5344
            vm->hasManagedSave = false;
5345 5346
        } else {
            ret = qemuDomainObjRestore(conn, driver, vm, managed_save,
5347
                                       start_paused, bypass_cache);
J
Jiri Denemark 已提交
5348

5349 5350 5351 5352 5353 5354 5355
            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 已提交
5356 5357 5358 5359
            if (ret > 0)
                VIR_WARN("Ignoring incomplete managed state %s", managed_save);
            else
                goto cleanup;
5360
        }
J
Jiri Denemark 已提交
5361 5362
    }

5363 5364
    ret = qemuProcessStart(conn, driver, vm, NULL, -1, NULL, NULL,
                           VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
5365
    virDomainAuditStart(vm, "booted", ret >= 0);
5366
    if (ret >= 0) {
J
Jiri Denemark 已提交
5367 5368 5369 5370
        virDomainEventPtr event =
            virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_STARTED,
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
5371
        if (event) {
J
Jiri Denemark 已提交
5372
            qemuDomainEventQueue(driver, event);
5373 5374 5375 5376 5377 5378 5379 5380
            if (start_paused) {
                event = virDomainEventNewFromObj(vm,
                                                 VIR_DOMAIN_EVENT_SUSPENDED,
                                                 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
                if (event)
                    qemuDomainEventQueue(driver, event);
            }
        }
J
Jiri Denemark 已提交
5381 5382 5383 5384 5385 5386 5387
    }

cleanup:
    VIR_FREE(managed_save);
    return ret;
}

5388
static int
5389
qemuDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
5390
{
5391
    virQEMUDriverPtr driver = dom->conn->privateData;
5392 5393
    virDomainObjPtr vm;
    int ret = -1;
5394

5395
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
5396
                  VIR_DOMAIN_START_AUTODESTROY |
5397 5398
                  VIR_DOMAIN_START_BYPASS_CACHE |
                  VIR_DOMAIN_START_FORCE_BOOT, -1);
5399

5400 5401
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
5402

5403
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5404 5405 5406
        goto cleanup;

    if (virDomainObjIsActive(vm)) {
5407 5408
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is already running"));
5409 5410 5411
        goto endjob;
    }

5412
    if (qemuDomainObjStart(dom->conn, driver, vm, flags) < 0)
5413 5414 5415
        goto endjob;

    ret = 0;
5416

5417
endjob:
5418
    if (qemuDomainObjEndJob(driver, vm) == 0)
5419
        vm = NULL;
5420

5421
cleanup:
5422
    if (vm)
5423
        virObjectUnlock(vm);
5424
    return ret;
D
Daniel P. Berrange 已提交
5425 5426
}

5427
static int
5428
qemuDomainStart(virDomainPtr dom)
5429
{
5430
    return qemuDomainStartWithFlags(dom, 0);
5431 5432
}

5433
static virDomainPtr qemuDomainDefine(virConnectPtr conn, const char *xml) {
5434
    virQEMUDriverPtr driver = conn->privateData;
5435
    virDomainDefPtr def = NULL;
5436
    virDomainDefPtr oldDef = NULL;
5437
    virDomainObjPtr vm = NULL;
5438
    virDomainPtr dom = NULL;
5439
    virDomainEventPtr event = NULL;
5440
    virQEMUCapsPtr qemuCaps = NULL;
5441
    virQEMUDriverConfigPtr cfg;
5442
    virCapsPtr caps = NULL;
5443

5444
    cfg = virQEMUDriverGetConfig(driver);
5445 5446 5447 5448

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

5449
    if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
M
Matthias Bolte 已提交
5450
                                        QEMU_EXPECTED_VIRT_TYPES,
5451
                                        VIR_DOMAIN_XML_INACTIVE)))
5452
        goto cleanup;
5453

5454
    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
5455 5456
        goto cleanup;

5457
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
5458 5459
        goto cleanup;

5460
    if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
5461 5462
        goto cleanup;

5463
    if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
5464 5465
        goto cleanup;

5466
    if (!(vm = virDomainObjListAdd(driver->domains, def,
5467
                                   driver->xmlopt,
5468
                                   0, &oldDef)))
5469 5470
        goto cleanup;

5471
    def = NULL;
E
Eric Blake 已提交
5472 5473 5474
    if (virDomainHasDiskMirror(vm)) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, "%s",
                       _("domain has active block copy job"));
5475
        virDomainObjAssignDef(vm, NULL, false, NULL);
E
Eric Blake 已提交
5476 5477
        goto cleanup;
    }
5478
    vm->persistent = 1;
5479

5480
    if (virDomainSaveConfig(cfg->configDir,
5481
                            vm->newDef ? vm->newDef : vm->def) < 0) {
5482
        if (oldDef) {
M
Michal Privoznik 已提交
5483 5484 5485 5486
            /* 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))
5487
                vm->newDef = oldDef;
M
Michal Privoznik 已提交
5488
            else
5489 5490
                vm->def = oldDef;
            oldDef = NULL;
M
Michal Privoznik 已提交
5491 5492 5493 5494 5495 5496
        } else {
            /* Brand new domain. Remove it */
            VIR_INFO("Deleting domain '%s'", vm->def->name);
            qemuDomainRemoveInactive(driver, vm);
            vm = NULL;
        }
5497
        goto cleanup;
5498 5499
    }

5500 5501
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_DEFINED,
5502
                                     !oldDef ?
5503 5504
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
5505

5506
    VIR_INFO("Creating domain '%s'", vm->def->name);
5507
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
5508
    if (dom) dom->id = vm->def->id;
5509 5510

cleanup:
5511
    virDomainDefFree(oldDef);
5512
    virDomainDefFree(def);
5513
    if (vm)
5514
        virObjectUnlock(vm);
5515 5516
    if (event)
        qemuDomainEventQueue(driver, event);
5517
    virObjectUnref(qemuCaps);
5518
    virObjectUnref(caps);
5519
    virObjectUnref(cfg);
5520
    return dom;
D
Daniel P. Berrange 已提交
5521 5522
}

5523 5524
static int
qemuDomainUndefineFlags(virDomainPtr dom,
5525
                        unsigned int flags)
5526
{
5527
    virQEMUDriverPtr driver = dom->conn->privateData;
5528
    virDomainObjPtr vm;
5529
    virDomainEventPtr event = NULL;
5530
    char *name = NULL;
5531
    int ret = -1;
5532
    int nsnapshots;
5533
    virQEMUDriverConfigPtr cfg = NULL;
D
Daniel P. Berrange 已提交
5534

5535 5536
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
5537

5538 5539
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
5540

5541
    cfg = virQEMUDriverGetConfig(driver);
D
Daniel P. Berrange 已提交
5542

5543
    if (!vm->persistent) {
5544 5545
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
5546 5547 5548
        goto cleanup;
    }

5549
    if (!virDomainObjIsActive(vm) &&
5550
        (nsnapshots = virDomainSnapshotObjListNum(vm->snapshots, NULL, 0))) {
5551
        if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
5552 5553 5554 5555
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("cannot delete inactive domain with %d "
                             "snapshots"),
                           nsnapshots);
5556 5557
            goto cleanup;
        }
5558
        if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0)
5559
            goto cleanup;
5560 5561
    }

5562 5563 5564 5565 5566 5567 5568
    name = qemuDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
5569 5570 5571
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed "
                                 "save image"));
5572 5573 5574
                goto cleanup;
            }
        } else {
5575 5576 5577
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
5578 5579 5580 5581
            goto cleanup;
        }
    }

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

5585 5586 5587
    event = virDomainEventNewFromObj(vm,
                                     VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
5588

5589
    VIR_INFO("Undefining domain '%s'", vm->def->name);
5590 5591 5592 5593 5594 5595 5596 5597

    /* 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 {
5598
        qemuDomainRemoveInactive(driver, vm);
5599 5600 5601
        vm = NULL;
    }

5602
    ret = 0;
D
Daniel P. Berrange 已提交
5603

5604
cleanup:
5605
    VIR_FREE(name);
5606
    if (vm)
5607
        virObjectUnlock(vm);
5608 5609
    if (event)
        qemuDomainEventQueue(driver, event);
5610
    virObjectUnref(cfg);
5611
    return ret;
D
Daniel P. Berrange 已提交
5612 5613
}

5614
static int
5615
qemuDomainUndefine(virDomainPtr dom)
5616 5617 5618 5619
{
    return qemuDomainUndefineFlags(dom, 0);
}

5620
static int
5621
qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
5622
                               virQEMUDriverPtr driver,
5623
                               virDomainObjPtr vm,
5624
                               virDomainDeviceDefPtr dev)
5625 5626
{
    virDomainDiskDefPtr disk = dev->data.disk;
5627 5628 5629
    virDomainDiskDefPtr orig_disk = NULL;
    virDomainDeviceDefPtr dev_copy = NULL;
    virDomainDiskDefPtr tmp = NULL;
5630
    virCgroupPtr cgroup = NULL;
5631
    virCapsPtr caps = NULL;
5632
    int ret = -1;
5633

5634
    if (disk->driverName != NULL && !STREQ(disk->driverName, "qemu")) {
5635 5636 5637
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported driver name '%s' for disk '%s'"),
                       disk->driverName, disk->src);
5638 5639 5640
        goto end;
    }

5641 5642 5643
    if (qemuTranslateDiskSourcePool(conn, disk) < 0)
        goto end;

5644 5645 5646 5647 5648 5649
    if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0)
        goto end;

    if (qemuSetUnprivSGIO(disk) < 0)
        goto end;

5650 5651 5652
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
        goto end;

5653 5654
    if (qemuSetupDiskCgroup(vm, disk) < 0)
        goto end;
5655

5656 5657 5658
    switch (disk->device)  {
    case VIR_DOMAIN_DISK_DEVICE_CDROM:
    case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673
        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;

5674 5675
        if (!(dev_copy = virDomainDeviceDefCopy(dev, vm->def,
                                                caps, driver->xmlopt))) {
5676 5677 5678 5679 5680 5681
            dev->data.disk = tmp;
            goto end;
        }
        dev->data.disk = tmp;

        ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, false);
5682 5683 5684
        /* '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 */
5685 5686 5687 5688

        /* Need to remove the shared disk entry for the original disk src
         * if the operation is either ejecting or updating.
         */
5689
        if (ret == 0)
5690 5691
            ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk,
                                              vm->def->name));
5692 5693
        break;
    case VIR_DOMAIN_DISK_DEVICE_DISK:
5694
    case VIR_DOMAIN_DISK_DEVICE_LUN:
5695 5696
        if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
5697 5698
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("disk device='lun' is not supported for usb bus"));
5699 5700
                break;
            }
5701
            ret = qemuDomainAttachUsbMassstorageDevice(conn, driver, vm,
5702
                                                       disk);
5703
        } else if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
5704
            ret = qemuDomainAttachVirtioDiskDevice(conn, driver, vm, disk);
5705
        } else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
5706
            ret = qemuDomainAttachSCSIDisk(conn, driver, vm, disk);
5707
        } else {
5708 5709 5710
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk bus '%s' cannot be hotplugged."),
                           virDomainDiskBusTypeToString(disk->bus));
5711
        }
5712 5713
        break;
    default:
5714 5715 5716
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk device type '%s' cannot be hotplugged"),
                       virDomainDiskDeviceTypeToString(disk->device));
5717 5718 5719 5720
        break;
    }

    if (ret != 0 && cgroup) {
5721
        if (qemuTeardownDiskCgroup(vm, disk) < 0)
5722 5723 5724
            VIR_WARN("Failed to teardown cgroup for disk path %s",
                     NULLSTR(disk->src));
    }
5725

5726
end:
5727 5728
    if (ret != 0)
        ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
5729 5730
    virObjectUnref(caps);
    virDomainDeviceDefFree(dev_copy);
5731 5732 5733 5734
    return ret;
}

static int
5735
qemuDomainAttachDeviceControllerLive(virQEMUDriverPtr driver,
5736
                                     virDomainObjPtr vm,
5737
                                     virDomainDeviceDefPtr dev)
5738 5739 5740 5741 5742 5743
{
    virDomainControllerDefPtr cont = dev->data.controller;
    int ret = -1;

    switch (cont->type) {
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5744
        ret = qemuDomainAttachPciControllerDevice(driver, vm, cont);
5745 5746
        break;
    default:
5747 5748 5749
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk controller bus '%s' cannot be hotplugged."),
                       virDomainControllerTypeToString(cont->type));
5750 5751 5752 5753 5754 5755 5756 5757
        break;
    }
    return ret;
}

static int
qemuDomainAttachDeviceLive(virDomainObjPtr vm,
                           virDomainDeviceDefPtr dev,
5758
                           virDomainPtr dom)
5759
{
5760
    virQEMUDriverPtr driver = dom->conn->privateData;
5761 5762 5763 5764
    int ret = -1;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
5765
        qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, -1);
5766
        ret = qemuDomainAttachDeviceDiskLive(dom->conn, driver, vm, dev);
5767 5768 5769 5770 5771
        if (!ret)
            dev->data.disk = NULL;
        break;

    case VIR_DOMAIN_DEVICE_CONTROLLER:
5772
        ret = qemuDomainAttachDeviceControllerLive(driver, vm, dev);
5773 5774 5775 5776
        if (!ret)
            dev->data.controller = NULL;
        break;

5777 5778 5779 5780 5781 5782 5783
    case VIR_DOMAIN_DEVICE_LEASE:
        ret = qemuDomainAttachLease(driver, vm,
                                    dev->data.lease);
        if (ret == 0)
            dev->data.lease = NULL;
        break;

5784
    case VIR_DOMAIN_DEVICE_NET:
5785
        qemuDomainObjCheckNetTaint(driver, vm, dev->data.net, -1);
5786
        ret = qemuDomainAttachNetDevice(dom->conn, driver, vm,
5787
                                        dev->data.net);
5788 5789 5790 5791 5792 5793
        if (!ret)
            dev->data.net = NULL;
        break;

    case VIR_DOMAIN_DEVICE_HOSTDEV:
        ret = qemuDomainAttachHostDevice(driver, vm,
5794
                                         dev->data.hostdev);
5795 5796 5797 5798
        if (!ret)
            dev->data.hostdev = NULL;
        break;

5799 5800 5801 5802 5803 5804 5805
    case VIR_DOMAIN_DEVICE_REDIRDEV:
        ret = qemuDomainAttachRedirdevDevice(driver, vm,
                                             dev->data.redirdev);
        if (!ret)
            dev->data.redirdev = NULL;
        break;

5806
    default:
5807 5808 5809
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("device type '%s' cannot be attached"),
                       virDomainDeviceTypeToString(dev->type));
5810 5811 5812 5813 5814 5815 5816
        break;
    }

    return ret;
}

static int
5817
qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
5818
                               virDomainObjPtr vm,
5819
                               virDomainDeviceDefPtr dev)
5820 5821 5822 5823 5824 5825
{
    virDomainDiskDefPtr disk = dev->data.disk;
    int ret = -1;

    switch (disk->device) {
    case VIR_DOMAIN_DISK_DEVICE_DISK:
5826
    case VIR_DOMAIN_DISK_DEVICE_LUN:
5827
        if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)
5828
            ret = qemuDomainDetachVirtioDiskDevice(driver, vm, dev);
O
Osier Yang 已提交
5829 5830
        else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
                 disk->bus == VIR_DOMAIN_DISK_BUS_USB)
5831
            ret = qemuDomainDetachDiskDevice(driver, vm, dev);
5832
        else
5833 5834
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This type of disk cannot be hot unplugged"));
5835 5836
        break;
    default:
5837 5838
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk device type '%s' cannot be detached"),
5839
                       virDomainDiskDeviceTypeToString(disk->device));
5840 5841
        break;
    }
5842

5843 5844
    if (ret == 0)
        ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
5845

5846 5847 5848 5849
    return ret;
}

static int
5850
qemuDomainDetachDeviceControllerLive(virQEMUDriverPtr driver,
5851
                                     virDomainObjPtr vm,
5852
                                     virDomainDeviceDefPtr dev)
5853 5854 5855 5856 5857 5858
{
    virDomainControllerDefPtr cont = dev->data.controller;
    int ret = -1;

    switch (cont->type) {
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5859
        ret = qemuDomainDetachPciControllerDevice(driver, vm, dev);
5860 5861
        break;
    default :
5862 5863 5864
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk controller bus '%s' cannot be hotunplugged."),
                       virDomainControllerTypeToString(cont->type));
5865 5866 5867 5868 5869 5870 5871
    }
    return ret;
}

static int
qemuDomainDetachDeviceLive(virDomainObjPtr vm,
                           virDomainDeviceDefPtr dev,
5872
                           virDomainPtr dom)
5873
{
5874
    virQEMUDriverPtr driver = dom->conn->privateData;
5875 5876 5877 5878
    int ret = -1;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
5879
        ret = qemuDomainDetachDeviceDiskLive(driver, vm, dev);
5880 5881
        break;
    case VIR_DOMAIN_DEVICE_CONTROLLER:
5882
        ret = qemuDomainDetachDeviceControllerLive(driver, vm, dev);
5883
        break;
5884 5885 5886
    case VIR_DOMAIN_DEVICE_LEASE:
        ret = qemuDomainDetachLease(driver, vm, dev->data.lease);
        break;
5887
    case VIR_DOMAIN_DEVICE_NET:
5888
        ret = qemuDomainDetachNetDevice(driver, vm, dev);
5889 5890
        break;
    case VIR_DOMAIN_DEVICE_HOSTDEV:
5891
        ret = qemuDomainDetachHostDevice(driver, vm, dev);
5892 5893
        break;
    default:
5894 5895
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("This type of device cannot be hot unplugged"));
5896 5897 5898 5899 5900 5901
        break;
    }

    return ret;
}

5902
static int
5903 5904
qemuDomainChangeDiskMediaLive(virConnectPtr conn,
                              virDomainObjPtr vm,
5905
                              virDomainDeviceDefPtr dev,
5906
                              virQEMUDriverPtr driver,
5907 5908 5909
                              bool force)
{
    virDomainDiskDefPtr disk = dev->data.disk;
5910 5911 5912 5913
    virDomainDiskDefPtr orig_disk = NULL;
    virDomainDiskDefPtr tmp = NULL;
    virDomainDeviceDefPtr dev_copy = NULL;
    virCapsPtr caps = NULL;
5914
    int ret = -1;
5915

5916 5917 5918
    if (qemuTranslateDiskSourcePool(conn, disk) < 0)
        goto end;

5919 5920 5921
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
        goto end;

5922 5923
    if (qemuSetupDiskCgroup(vm, disk) < 0)
        goto end;
5924 5925 5926 5927

    switch (disk->device) {
    case VIR_DOMAIN_DISK_DEVICE_CDROM:
    case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942
        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;

5943 5944
        if (!(dev_copy = virDomainDeviceDefCopy(dev, vm->def,
                                                caps, driver->xmlopt))) {
5945 5946 5947 5948 5949
            dev->data.disk = tmp;
            goto end;
        }
        dev->data.disk = tmp;

5950 5951 5952 5953
        /* Add the new disk src into shared disk hash table */
        if (qemuAddSharedDisk(driver, dev->data.disk, vm->def->name) < 0)
            goto end;

5954
        ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, force);
5955 5956 5957 5958 5959 5960 5961
        /* '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.
         */
5962
        if (ret == 0) {
5963
            dev->data.disk = NULL;
5964 5965
            ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk,
                                              vm->def->name));
5966
        }
5967 5968
        break;
    default:
5969 5970 5971
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("disk bus '%s' cannot be updated."),
                       virDomainDiskBusTypeToString(disk->bus));
5972 5973 5974
        break;
    }

5975 5976 5977 5978 5979
    if (ret != 0 &&
        qemuTeardownDiskCgroup(vm, disk) < 0)
        VIR_WARN("Failed to teardown cgroup for disk path %s",
                 NULLSTR(disk->src));

5980
end:
5981 5982
    virObjectUnref(caps);
    virDomainDeviceDefFree(dev_copy);
5983 5984 5985 5986
    return ret;
}

static int
5987 5988
qemuDomainUpdateDeviceLive(virConnectPtr conn,
                           virDomainObjPtr vm,
5989 5990 5991 5992
                           virDomainDeviceDefPtr dev,
                           virDomainPtr dom,
                           bool force)
{
5993
    virQEMUDriverPtr driver = dom->conn->privateData;
5994 5995 5996 5997
    int ret = -1;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
5998
        ret = qemuDomainChangeDiskMediaLive(conn, vm, dev, driver, force);
5999 6000 6001 6002
        break;
    case VIR_DOMAIN_DEVICE_GRAPHICS:
        ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
        break;
6003
    case VIR_DOMAIN_DEVICE_NET:
6004
        ret = qemuDomainChangeNet(driver, vm, dom, dev);
6005
        break;
6006
    default:
6007 6008 6009
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("device type '%s' cannot be updated"),
                       virDomainDeviceTypeToString(dev->type));
6010 6011 6012 6013 6014 6015
        break;
    }

    return ret;
}

6016
static int
6017
qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps,
6018
                             virDomainDefPtr vmdef,
6019 6020
                             virDomainDeviceDefPtr dev)
{
6021
    virDomainDiskDefPtr disk;
6022
    virDomainNetDefPtr net;
6023
    virDomainHostdevDefPtr hostdev;
6024
    virDomainLeaseDefPtr lease;
6025
    virDomainControllerDefPtr controller;
6026

6027
    switch (dev->type) {
6028 6029
    case VIR_DOMAIN_DEVICE_DISK:
        disk = dev->data.disk;
6030
        if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
6031 6032
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("target %s already exists"), disk->dst);
6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043
            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;
6044
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6045 6046 6047
            return -1;
        break;

6048 6049 6050 6051 6052 6053 6054
    case VIR_DOMAIN_DEVICE_NET:
        net = dev->data.net;
        if (virDomainNetInsert(vmdef, net)) {
            virReportOOMError();
            return -1;
        }
        dev->data.net = NULL;
6055
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6056 6057
            return -1;
        break;
6058

6059 6060 6061
    case VIR_DOMAIN_DEVICE_HOSTDEV:
        hostdev = dev->data.hostdev;
        if (virDomainHostdevFind(vmdef, hostdev, NULL) >= 0) {
6062
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6063
                           _("device is already in the domain configuration"));
6064 6065 6066 6067 6068 6069 6070
            return -1;
        }
        if (virDomainHostdevInsert(vmdef, hostdev)) {
            virReportOOMError();
            return -1;
        }
        dev->data.hostdev = NULL;
6071
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6072 6073 6074
            return -1;
        break;

6075 6076 6077
    case VIR_DOMAIN_DEVICE_LEASE:
        lease = dev->data.lease;
        if (virDomainLeaseIndex(vmdef, lease) >= 0) {
6078
            virReportError(VIR_ERR_OPERATION_INVALID,
6079 6080
                           _("Lease %s in lockspace %s already exists"),
                           lease->key, NULLSTR(lease->lockspace));
6081 6082 6083 6084 6085 6086 6087 6088 6089
            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;

6090 6091 6092 6093
    case VIR_DOMAIN_DEVICE_CONTROLLER:
        controller = dev->data.controller;
        if (virDomainControllerFind(vmdef, controller->type,
                                    controller->idx) > 0) {
6094
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6095 6096 6097 6098 6099 6100 6101 6102
                           _("Target already exists"));
            return -1;
        }

        if (virDomainControllerInsert(vmdef, controller) < 0)
            return -1;
        dev->data.controller = NULL;

6103
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6104 6105 6106
            return -1;
        break;

6107
    default:
6108 6109
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("persistent attach of device is not supported"));
6110 6111 6112 6113 6114 6115 6116
         return -1;
    }
    return 0;
}


static int
6117
qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
6118 6119
                             virDomainDeviceDefPtr dev)
{
6120
    virDomainDiskDefPtr disk, det_disk;
6121
    virDomainNetDefPtr net;
6122
    virDomainHostdevDefPtr hostdev, det_hostdev;
6123
    virDomainLeaseDefPtr lease, det_lease;
6124 6125
    virDomainControllerDefPtr cont, det_cont;
    int idx;
6126
    char mac[VIR_MAC_STRING_BUFLEN];
6127

6128
    switch (dev->type) {
6129 6130
    case VIR_DOMAIN_DEVICE_DISK:
        disk = dev->data.disk;
6131
        if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
6132 6133
            virReportError(VIR_ERR_INVALID_ARG,
                           _("no target device %s"), disk->dst);
6134 6135
            return -1;
        }
6136
        virDomainDiskDefFree(det_disk);
6137
        break;
6138

6139 6140
    case VIR_DOMAIN_DEVICE_NET:
        net = dev->data.net;
6141 6142 6143 6144 6145 6146 6147 6148 6149
        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"));
6150 6151
            return -1;
        }
6152 6153
        /* this is guaranteed to succeed */
        virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
6154
        break;
6155

6156 6157 6158
    case VIR_DOMAIN_DEVICE_HOSTDEV: {
        hostdev = dev->data.hostdev;
        if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
6159 6160
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("device not present in domain configuration"));
6161 6162 6163 6164 6165 6166 6167
            return -1;
        }
        virDomainHostdevRemove(vmdef, idx);
        virDomainHostdevDefFree(det_hostdev);
        break;
    }

6168 6169
    case VIR_DOMAIN_DEVICE_LEASE:
        lease = dev->data.lease;
6170
        if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
6171 6172 6173
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Lease %s in lockspace %s does not exist"),
                           lease->key, NULLSTR(lease->lockspace));
6174 6175
            return -1;
        }
6176
        virDomainLeaseDefFree(det_lease);
6177 6178
        break;

6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191
    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;

6192
    default:
6193 6194
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("persistent detach of device is not supported"));
6195 6196 6197 6198 6199 6200
        return -1;
    }
    return 0;
}

static int
6201
qemuDomainUpdateDeviceConfig(virQEMUCapsPtr qemuCaps,
6202
                             virDomainDefPtr vmdef,
6203 6204
                             virDomainDeviceDefPtr dev)
{
6205
    virDomainDiskDefPtr orig, disk;
6206
    virDomainNetDefPtr net;
6207
    int pos;
6208 6209
    char mac[VIR_MAC_STRING_BUFLEN];

6210

6211
    switch (dev->type) {
6212 6213
    case VIR_DOMAIN_DEVICE_DISK:
        disk = dev->data.disk;
6214
        pos = virDomainDiskIndexByName(vmdef, disk->dst, false);
6215
        if (pos < 0) {
6216 6217
            virReportError(VIR_ERR_INVALID_ARG,
                           _("target %s doesn't exist."), disk->dst);
6218 6219 6220 6221 6222
            return -1;
        }
        orig = vmdef->disks[pos];
        if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
            !(orig->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) {
6223 6224
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("this disk doesn't support update"));
6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239
            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;
        }
6240 6241
        if (disk->format)
            orig->format = disk->format;
6242 6243
        disk->src = NULL;
        break;
6244 6245 6246

    case VIR_DOMAIN_DEVICE_NET:
        net = dev->data.net;
6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258
        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);
6259 6260 6261
            return -1;
        }

6262
        virDomainNetDefFree(vmdef->nets[pos]);
6263 6264 6265 6266

        vmdef->nets[pos] = net;
        dev->data.net = NULL;

6267
        if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
6268 6269 6270
            return -1;
        break;

6271
    default:
6272 6273
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("persistent update of device is not supported"));
6274 6275 6276 6277 6278
        return -1;
    }
    return 0;
}

6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289
/* Actions for qemuDomainModifyDeviceFlags */
enum {
    QEMU_DEVICE_ATTACH,
    QEMU_DEVICE_DETACH,
    QEMU_DEVICE_UPDATE,
};


static int
qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
                            unsigned int flags, int action)
6290
{
6291
    virQEMUDriverPtr driver = dom->conn->privateData;
6292
    virDomainObjPtr vm = NULL;
6293
    virDomainDefPtr vmdef = NULL;
6294
    virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
6295
    bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
6296
    int ret = -1;
6297
    unsigned int affect;
6298
    virQEMUCapsPtr qemuCaps = NULL;
6299
    qemuDomainObjPrivatePtr priv;
6300
    virQEMUDriverConfigPtr cfg = NULL;
6301
    virCapsPtr caps = NULL;
6302

6303 6304
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
6305 6306 6307
                  (action == QEMU_DEVICE_UPDATE ?
                   VIR_DOMAIN_DEVICE_MODIFY_FORCE : 0), -1);

6308 6309
    cfg = virQEMUDriverGetConfig(driver);

6310 6311
    affect = flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG);

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

6315
    if (!(vm = qemuDomObjFromDomain(dom)))
6316
        goto cleanup;
6317

6318
    priv = vm->privateData;
6319

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

6323
    if (virDomainObjIsActive(vm)) {
6324
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
6325
            flags |= VIR_DOMAIN_AFFECT_LIVE;
6326
    } else {
6327
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
6328
            flags |= VIR_DOMAIN_AFFECT_CONFIG;
6329
        /* check consistency between flags and the vm state */
6330
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6331
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6332 6333
                           _("cannot do live update a device on "
                             "inactive domain"));
6334 6335
            goto endjob;
        }
6336
    }
6337

6338
    if ((flags & VIR_DOMAIN_AFFECT_CONFIG) && !vm->persistent) {
6339 6340
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                        _("cannot modify device on transient domain"));
6341 6342
         goto endjob;
    }
6343

6344 6345
    dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
                                             caps, driver->xmlopt,
6346 6347 6348 6349 6350 6351 6352 6353 6354 6355
                                             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.
         */
6356
        dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
6357
        if (!dev_copy)
6358
            goto endjob;
6359
    }
6360

6361 6362 6363
    if (priv->qemuCaps)
        qemuCaps = virObjectRef(priv->qemuCaps);
    else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, vm->def->emulator)))
6364 6365
        goto cleanup;

6366
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6367
        if (virDomainDefCompatibleDevice(vm->def, dev) < 0)
6368 6369
            goto endjob;

6370
        /* Make a copy for updated domain. */
6371
        vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
6372 6373 6374 6375
        if (!vmdef)
            goto endjob;
        switch (action) {
        case QEMU_DEVICE_ATTACH:
6376
            ret = qemuDomainAttachDeviceConfig(qemuCaps, vmdef, dev);
6377 6378 6379 6380 6381
            break;
        case QEMU_DEVICE_DETACH:
            ret = qemuDomainDetachDeviceConfig(vmdef, dev);
            break;
        case QEMU_DEVICE_UPDATE:
6382
            ret = qemuDomainUpdateDeviceConfig(qemuCaps, vmdef, dev);
6383 6384
            break;
        default:
6385 6386
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown domain modify action %d"), action);
6387 6388
            break;
        }
6389

6390 6391 6392 6393 6394
        if (ret == -1)
            goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6395 6396 6397
        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
            goto endjob;

6398 6399
        switch (action) {
        case QEMU_DEVICE_ATTACH:
6400
            ret = qemuDomainAttachDeviceLive(vm, dev_copy, dom);
6401 6402
            break;
        case QEMU_DEVICE_DETACH:
6403
            ret = qemuDomainDetachDeviceLive(vm, dev_copy, dom);
6404 6405
            break;
        case QEMU_DEVICE_UPDATE:
6406
            ret = qemuDomainUpdateDeviceLive(dom->conn, vm, dev_copy, dom, force);
6407 6408
            break;
        default:
6409 6410
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown domain modify action %d"), action);
6411
            ret = -1;
6412 6413
            break;
        }
6414 6415 6416

        if (ret == -1)
            goto endjob;
6417 6418
        /*
         * update domain status forcibly because the domain status may be
6419 6420
         * changed even if we failed to attach the device. For example,
         * a new controller may be created.
6421
         */
6422
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
6423
            ret = -1;
6424 6425
            goto endjob;
        }
6426
    }
6427

6428
    /* Finally, if no error until here, we can save config. */
6429
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6430
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
6431
        if (!ret) {
6432
            virDomainObjAssignDef(vm, vmdef, false, NULL);
6433 6434 6435
            vmdef = NULL;
        }
    }
6436 6437

endjob:
6438
    if (qemuDomainObjEndJob(driver, vm) == 0)
6439 6440 6441
        vm = NULL;

cleanup:
6442
    virObjectUnref(qemuCaps);
6443
    virDomainDefFree(vmdef);
6444 6445
    if (dev != dev_copy)
        virDomainDeviceDefFree(dev_copy);
6446 6447
    virDomainDeviceDefFree(dev);
    if (vm)
6448
        virObjectUnlock(vm);
6449
    virObjectUnref(caps);
6450
    virObjectUnref(cfg);
6451 6452 6453
    return ret;
}

6454 6455 6456 6457 6458 6459
static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                       unsigned int flags)
{
    return qemuDomainModifyDeviceFlags(dom, xml, flags, QEMU_DEVICE_ATTACH);
}

6460 6461 6462
static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml)
{
    return qemuDomainAttachDeviceFlags(dom, xml,
6463
                                       VIR_DOMAIN_AFFECT_LIVE);
6464
}
6465

6466

6467 6468 6469 6470
static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
                                       const char *xml,
                                       unsigned int flags)
{
6471
    return qemuDomainModifyDeviceFlags(dom, xml, flags, QEMU_DEVICE_UPDATE);
6472 6473
}

6474 6475 6476
static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                       unsigned int flags)
{
6477
    return qemuDomainModifyDeviceFlags(dom, xml, flags, QEMU_DEVICE_DETACH);
6478 6479
}

6480 6481 6482
static int qemuDomainDetachDevice(virDomainPtr dom, const char *xml)
{
    return qemuDomainDetachDeviceFlags(dom, xml,
6483
                                       VIR_DOMAIN_AFFECT_LIVE);
6484 6485
}

6486 6487
static int qemuDomainGetAutostart(virDomainPtr dom,
                                  int *autostart) {
6488 6489
    virDomainObjPtr vm;
    int ret = -1;
6490

6491
    if (!(vm = qemuDomObjFromDomain(dom)))
6492
        goto cleanup;
6493 6494

    *autostart = vm->autostart;
6495
    ret = 0;
6496

6497
cleanup:
6498
    if (vm)
6499
        virObjectUnlock(vm);
6500
    return ret;
6501 6502
}

6503 6504
static int qemuDomainSetAutostart(virDomainPtr dom,
                                  int autostart) {
6505
    virQEMUDriverPtr driver = dom->conn->privateData;
6506
    virDomainObjPtr vm;
6507 6508
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;
6509
    virQEMUDriverConfigPtr cfg = NULL;
6510

6511 6512 6513
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

6514
    cfg = virQEMUDriverGetConfig(driver);
6515

6516
    if (!vm->persistent) {
6517 6518
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
6519
        goto cleanup;
6520 6521
    }

6522 6523
    autostart = (autostart != 0);

6524
    if (vm->autostart != autostart) {
6525
        if ((configFile = virDomainConfigFile(cfg->configDir, vm->def->name)) == NULL)
6526
            goto cleanup;
6527
        if ((autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)) == NULL)
6528
            goto cleanup;
6529

6530
        if (autostart) {
6531
            if (virFileMakePath(cfg->autostartDir) < 0) {
6532
                virReportSystemError(errno,
6533
                                     _("cannot create autostart directory %s"),
6534
                                     cfg->autostartDir);
6535 6536
                goto cleanup;
            }
6537

6538
            if (symlink(configFile, autostartLink) < 0) {
6539
                virReportSystemError(errno,
6540 6541
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
6542 6543 6544 6545
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
6546
                virReportSystemError(errno,
6547 6548
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
6549 6550
                goto cleanup;
            }
6551 6552
        }

6553
        vm->autostart = autostart;
6554
    }
6555
    ret = 0;
6556

6557 6558 6559
cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
6560
    if (vm)
6561
        virObjectUnlock(vm);
6562
    virObjectUnref(cfg);
6563
    return ret;
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
/*
 * 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;
}


6600 6601 6602
static char *qemuGetSchedulerType(virDomainPtr dom,
                                  int *nparams)
{
6603
    virQEMUDriverPtr driver = dom->conn->privateData;
6604
    char *ret = NULL;
6605
    int rc;
6606 6607 6608 6609 6610 6611 6612 6613 6614 6615
    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;
6616

6617
    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
6618 6619
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cgroup CPU controller is not mounted"));
6620
        goto cleanup;
6621 6622
    }

6623
    if (nparams) {
6624
        rc = qemuGetCpuBWStatus(priv->cgroup);
6625 6626 6627 6628 6629
        if (rc < 0)
            goto cleanup;
        else if (rc == 0)
            *nparams = 1;
        else
6630
            *nparams = 5;
6631
    }
6632 6633 6634

    ret = strdup("posix");
    if (!ret)
6635
        virReportOOMError();
6636 6637

cleanup:
6638 6639
    if (vm)
        virObjectUnlock(vm);
6640 6641 6642
    return ret;
}

6643 6644 6645 6646
/* 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
6647 6648
qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
                               virBlkioDeviceWeightPtr *dw, size_t *size)
6649 6650 6651 6652 6653 6654 6655
{
    char *temp;
    int ndevices = 0;
    int nsep = 0;
    int i;
    virBlkioDeviceWeightPtr result = NULL;

6656 6657 6658 6659 6660 6661
    *dw = NULL;
    *size = 0;

    if (STREQ(deviceWeightStr, ""))
        return 0;

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
    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:
6723 6724
    virReportError(VIR_ERR_INVALID_ARG,
                   _("unable to parse device weight '%s'"), deviceWeightStr);
6725 6726 6727 6728 6729 6730
cleanup:
    virBlkioDeviceWeightArrayClear(result, ndevices);
    VIR_FREE(result);
    return -1;
}

6731 6732
/* Modify dest_array to reflect all device weight changes described in
 * src_array.  */
6733
static int
6734 6735 6736 6737
qemuDomainMergeDeviceWeights(virBlkioDeviceWeightPtr *dest_array,
                             size_t *dest_size,
                             virBlkioDeviceWeightPtr src_array,
                             size_t src_size)
6738 6739
{
    int i, j;
6740
    virBlkioDeviceWeightPtr dest, src;
6741

6742
    for (i = 0; i < src_size; i++) {
6743 6744
        bool found = false;

6745 6746 6747 6748
        src = &src_array[i];
        for (j = 0; j < *dest_size; j++) {
            dest = &(*dest_array)[j];
            if (STREQ(src->path, dest->path)) {
6749
                found = true;
6750
                dest->weight = src->weight;
6751 6752 6753 6754
                break;
            }
        }
        if (!found) {
6755
            if (!src->weight)
6756
                continue;
6757
            if (VIR_EXPAND_N(*dest_array, *dest_size, 1) < 0) {
6758 6759 6760
                virReportOOMError();
                return -1;
            }
6761 6762 6763 6764
            dest = &(*dest_array)[*dest_size - 1];
            dest->path = src->path;
            dest->weight = src->weight;
            src->path = NULL;
6765 6766 6767 6768 6769 6770
        }
    }

    return 0;
}

6771 6772 6773 6774 6775
static int
qemuDomainSetBlkioParameters(virDomainPtr dom,
                             virTypedParameterPtr params,
                             int nparams,
                             unsigned int flags)
6776
{
6777
    virQEMUDriverPtr driver = dom->conn->privateData;
6778 6779
    int i;
    virDomainObjPtr vm = NULL;
6780
    virDomainDefPtr persistentDef = NULL;
6781
    int ret = -1;
6782
    virQEMUDriverConfigPtr cfg = NULL;
6783
    virCapsPtr caps = NULL;
6784
    qemuDomainObjPrivatePtr priv;
6785

6786 6787
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
6788 6789 6790 6791 6792 6793 6794
    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;
6795

6796 6797 6798
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

6799
    priv = vm->privateData;
6800
    cfg = virQEMUDriverGetConfig(driver);
6801 6802
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;
6803

6804
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
6805 6806
                                        &persistentDef) < 0)
        goto cleanup;
6807

6808
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6809
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
6810 6811
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("blkio cgroup isn't mounted"));
6812 6813 6814 6815
            goto cleanup;
        }
    }

6816
    ret = 0;
6817 6818
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        for (i = 0; i < nparams; i++) {
6819
            int rc;
6820 6821 6822 6823
            virTypedParameterPtr param = &params[i];

            if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
                if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
6824 6825
                    virReportError(VIR_ERR_INVALID_ARG, "%s",
                                   _("out of blkio weight range."));
6826 6827 6828
                    ret = -1;
                    continue;
                }
6829

6830
                rc = virCgroupSetBlkioWeight(priv->cgroup, params[i].value.ui);
6831 6832 6833 6834 6835
                if (rc != 0) {
                    virReportSystemError(-rc, "%s",
                                         _("unable to set blkio weight tunable"));
                    ret = -1;
                }
6836
            } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
6837
                size_t ndevices;
6838
                virBlkioDeviceWeightPtr devices = NULL;
6839 6840
                int j;

6841 6842 6843
                if (qemuDomainParseDeviceWeightStr(params[i].value.s,
                                                   &devices,
                                                   &ndevices) < 0) {
6844 6845 6846
                    ret = -1;
                    continue;
                }
6847
                for (j = 0; j < ndevices; j++) {
6848
                    rc = virCgroupSetBlkioDeviceWeight(priv->cgroup,
6849 6850
                                                       devices[j].path,
                                                       devices[j].weight);
6851 6852 6853 6854
                    if (rc < 0) {
                        virReportSystemError(-rc,
                                             _("Unable to set io device weight "
                                               "for path %s"),
6855
                                             devices[j].path);
6856 6857 6858
                        break;
                    }
                }
6859 6860
                if (j != ndevices ||
                    qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
6861 6862 6863 6864 6865
                                                 &vm->def->blkio.ndevices,
                                                 devices, ndevices) < 0)
                    ret = -1;
                virBlkioDeviceWeightArrayClear(devices, ndevices);
                VIR_FREE(devices);
6866
            }
6867
        }
E
Eric Blake 已提交
6868 6869 6870 6871
    }
    if (ret < 0)
        goto cleanup;
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
E
Eric Blake 已提交
6872 6873 6874
        /* Clang can't see that if we get here, persistentDef was set.  */
        sa_assert(persistentDef);

6875 6876 6877 6878 6879
        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) {
6880 6881
                    virReportError(VIR_ERR_INVALID_ARG, "%s",
                                   _("out of blkio weight range."));
6882 6883 6884 6885 6886
                    ret = -1;
                    continue;
                }

                persistentDef->blkio.weight = params[i].value.ui;
6887 6888
            } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
                virBlkioDeviceWeightPtr devices = NULL;
6889
                size_t ndevices;
6890

6891 6892 6893
                if (qemuDomainParseDeviceWeightStr(params[i].value.s,
                                                   &devices,
                                                   &ndevices) < 0) {
6894 6895 6896
                    ret = -1;
                    continue;
                }
6897 6898
                if (qemuDomainMergeDeviceWeights(&persistentDef->blkio.devices,
                                                 &persistentDef->blkio.ndevices,
6899 6900 6901 6902
                                                 devices, ndevices) < 0)
                    ret = -1;
                virBlkioDeviceWeightArrayClear(devices, ndevices);
                VIR_FREE(devices);
6903 6904
            }
        }
A
Alex Jia 已提交
6905

6906
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
A
Alex Jia 已提交
6907
            ret = -1;
6908 6909 6910 6911
    }

cleanup:
    if (vm)
6912
        virObjectUnlock(vm);
6913
    virObjectUnref(caps);
6914
    virObjectUnref(cfg);
6915 6916 6917
    return ret;
}

6918 6919 6920 6921 6922
static int
qemuDomainGetBlkioParameters(virDomainPtr dom,
                             virTypedParameterPtr params,
                             int *nparams,
                             unsigned int flags)
6923
{
6924
    virQEMUDriverPtr driver = dom->conn->privateData;
6925
    int i, j;
6926
    virDomainObjPtr vm = NULL;
6927
    virDomainDefPtr persistentDef = NULL;
6928 6929 6930
    unsigned int val;
    int ret = -1;
    int rc;
6931
    virCapsPtr caps = NULL;
6932
    qemuDomainObjPrivatePtr priv;
6933

6934
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6935 6936
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
6937

6938 6939 6940
    /* 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.  */
6941 6942
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

6943 6944
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
6945

6946 6947
    priv = vm->privateData;

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

6951 6952 6953 6954 6955 6956 6957
    if ((*nparams) == 0) {
        /* Current number of blkio parameters supported by cgroups */
        *nparams = QEMU_NB_BLKIO_PARAM;
        ret = 0;
        goto cleanup;
    }

6958
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
6959 6960
                                        &persistentDef) < 0)
        goto cleanup;
6961

6962
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6963
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
6964 6965
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("blkio cgroup isn't mounted"));
6966 6967 6968 6969 6970
            goto cleanup;
        }
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6971
        for (i = 0; i < *nparams && i < QEMU_NB_BLKIO_PARAM; i++) {
6972 6973 6974 6975 6976
            virTypedParameterPtr param = &params[i];
            val = 0;

            switch (i) {
            case 0: /* fill blkio weight here */
6977
                rc = virCgroupGetBlkioWeight(priv->cgroup, &val);
6978 6979 6980 6981 6982
                if (rc != 0) {
                    virReportSystemError(-rc, "%s",
                                         _("unable to get blkio weight"));
                    goto cleanup;
                }
6983 6984
                if (virTypedParameterAssign(param, VIR_DOMAIN_BLKIO_WEIGHT,
                                            VIR_TYPED_PARAM_UINT, val) < 0)
6985 6986
                    goto cleanup;
                break;
6987 6988 6989 6990
            case 1: /* blkiotune.device_weight */
                if (vm->def->blkio.ndevices > 0) {
                    virBuffer buf = VIR_BUFFER_INITIALIZER;
                    bool comma = false;
6991

6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008
                    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);
                }
7009 7010 7011 7012
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
                                            VIR_TYPED_PARAM_STRING,
                                            param->value.s) < 0)
7013 7014
                    goto cleanup;
                break;
7015 7016 7017 7018

            default:
                break;
                /* should not hit here */
7019
            }
7020 7021
        }
    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7022
        for (i = 0; i < *nparams && i < QEMU_NB_BLKIO_PARAM; i++) {
7023 7024 7025 7026 7027 7028 7029 7030
            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) {
7031 7032 7033
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Field name '%s' too long"),
                                   VIR_DOMAIN_BLKIO_WEIGHT);
7034 7035 7036 7037
                    goto cleanup;
                }
                param->value.ui = persistentDef->blkio.weight;
                break;
7038

7039 7040 7041
            case 1: /* blkiotune.device_weight */
                if (persistentDef->blkio.ndevices > 0) {
                    virBuffer buf = VIR_BUFFER_INITIALIZER;
7042 7043
                    bool comma = false;

7044
                    for (j = 0; j < persistentDef->blkio.ndevices; j++) {
7045 7046 7047
                        if (!persistentDef->blkio.devices[j].weight)
                            continue;
                        if (comma)
7048
                            virBufferAddChar(&buf, ',');
7049 7050
                        else
                            comma = true;
7051 7052 7053 7054 7055 7056 7057 7058 7059
                        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);
7060 7061
                }
                if (!param->value.s) {
7062 7063 7064 7065 7066 7067 7068 7069 7070
                    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) {
7071 7072 7073
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Field name '%s' too long"),
                                   VIR_DOMAIN_BLKIO_DEVICE_WEIGHT);
7074 7075 7076 7077
                    goto cleanup;
                }
                break;

7078 7079 7080 7081
            default:
                break;
                /* should not hit here */
            }
7082 7083 7084
        }
    }

7085 7086
    if (QEMU_NB_BLKIO_PARAM < *nparams)
        *nparams = QEMU_NB_BLKIO_PARAM;
7087 7088 7089 7090
    ret = 0;

cleanup:
    if (vm)
7091
        virObjectUnlock(vm);
7092
    virObjectUnref(caps);
7093 7094
    return ret;
}
7095

7096 7097 7098 7099 7100
static int
qemuDomainSetMemoryParameters(virDomainPtr dom,
                              virTypedParameterPtr params,
                              int nparams,
                              unsigned int flags)
7101
{
7102
    virQEMUDriverPtr driver = dom->conn->privateData;
7103
    virDomainDefPtr persistentDef = NULL;
7104
    virDomainObjPtr vm = NULL;
7105
    unsigned long long swap_hard_limit;
7106 7107
    unsigned long long hard_limit = 0;
    unsigned long long soft_limit = 0;
7108
    bool set_swap_hard_limit = false;
7109 7110
    bool set_hard_limit = false;
    bool set_soft_limit = false;
7111
    virQEMUDriverConfigPtr cfg = NULL;
7112
    int ret = -1;
7113
    int rc;
7114
    virCapsPtr caps = NULL;
7115
    qemuDomainObjPrivatePtr priv;
7116

7117 7118
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
7119

7120 7121 7122 7123 7124 7125 7126 7127 7128
    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;
7129 7130


7131 7132
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7133

7134
    priv = vm->privateData;
7135 7136
    cfg = virQEMUDriverGetConfig(driver);

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

7140
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7141 7142
                                        &persistentDef) < 0)
        goto cleanup;
7143

7144
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7145
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
7146 7147
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup memory controller is not mounted"));
7148 7149 7150 7151
            goto cleanup;
        }
    }

7152
#define VIR_GET_LIMIT_PARAMETER(PARAM, VALUE)                                \
7153
    if ((rc = virTypedParamsGetULLong(params, nparams, PARAM, &VALUE)) < 0)  \
7154 7155 7156 7157 7158 7159
        goto cleanup;                                                        \
                                                                             \
    if (rc == 1)                                                             \
        set_ ## VALUE = true;

    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit)
7160 7161
    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit)
    VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit)
7162 7163 7164

#undef VIR_GET_LIMIT_PARAMETER

7165 7166 7167 7168 7169
    /* 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;
7170

7171 7172
        if (set_swap_hard_limit)
            swap_limit = swap_hard_limit;
7173

7174 7175 7176 7177 7178 7179 7180 7181
        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;
7182
        }
7183
    }
7184

7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198
#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;                                   \
7199 7200
    }

7201 7202
    /* Soft limit doesn't clash with the others */
    QEMU_SET_MEM_PARAMETER(virCgroupSetMemorySoftLimit, soft_limit);
7203

7204 7205 7206 7207 7208
    /* 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;
7209
    }
7210

7211
    QEMU_SET_MEM_PARAMETER(virCgroupSetMemSwapHardLimit, swap_hard_limit);
7212

7213 7214 7215 7216
    /* otherwise increase it after swap hard limit */
    QEMU_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);

#undef QEMU_SET_MEM_PARAMETER
7217

7218 7219 7220 7221 7222 7223
    if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
        virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
        goto cleanup;

    ret = 0;

7224
cleanup:
7225
    virObjectUnlock(vm);
7226
    virObjectUnref(caps);
7227
    virObjectUnref(cfg);
7228 7229 7230
    return ret;
}

7231 7232 7233 7234 7235
static int
qemuDomainGetMemoryParameters(virDomainPtr dom,
                              virTypedParameterPtr params,
                              int *nparams,
                              unsigned int flags)
7236
{
7237
    virQEMUDriverPtr driver = dom->conn->privateData;
7238 7239
    int i;
    virDomainObjPtr vm = NULL;
7240
    virDomainDefPtr persistentDef = NULL;
7241 7242
    int ret = -1;
    int rc;
7243
    virCapsPtr caps = NULL;
7244
    qemuDomainObjPrivatePtr priv;
7245

7246
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
7247 7248
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
7249

7250 7251 7252
    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

7253 7254
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7255

7256
    priv = vm->privateData;
7257 7258 7259
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

7260
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7261 7262
                                        &persistentDef) < 0)
        goto cleanup;
7263

7264
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7265
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
7266 7267
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup memory controller is not mounted"));
7268 7269 7270 7271
            goto cleanup;
        }
    }

7272 7273 7274 7275 7276 7277 7278
    if ((*nparams) == 0) {
        /* Current number of memory parameters supported by cgroups */
        *nparams = QEMU_NB_MEM_PARAM;
        ret = 0;
        goto cleanup;
    }

7279
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7280
        for (i = 0; i < *nparams && i < QEMU_NB_MEM_PARAM; i++) {
7281 7282 7283 7284
            virMemoryParameterPtr param = &params[i];

            switch (i) {
            case 0: /* fill memory hard limit here */
7285 7286 7287 7288
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_MEMORY_HARD_LIMIT,
                                            VIR_TYPED_PARAM_ULLONG,
                                            persistentDef->mem.hard_limit) < 0)
7289 7290 7291 7292
                    goto cleanup;
                break;

            case 1: /* fill memory soft limit here */
7293 7294 7295 7296
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_MEMORY_SOFT_LIMIT,
                                            VIR_TYPED_PARAM_ULLONG,
                                            persistentDef->mem.soft_limit) < 0)
7297 7298 7299 7300
                    goto cleanup;
                break;

            case 2: /* fill swap hard limit here */
7301 7302 7303 7304
                if (virTypedParameterAssign(param,
                                            VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
                                            VIR_TYPED_PARAM_ULLONG,
                                            persistentDef->mem.swap_hard_limit) < 0)
7305 7306 7307 7308 7309 7310 7311 7312 7313
                    goto cleanup;
                break;

            default:
                break;
                /* should not hit here */
            }
        }
        goto out;
7314 7315
    }

7316
    for (i = 0; i < *nparams && i < QEMU_NB_MEM_PARAM; i++) {
7317
        virTypedParameterPtr param = &params[i];
7318
        unsigned long long val = 0;
7319

7320
        switch (i) {
7321
        case 0: /* fill memory hard limit here */
7322
            rc = virCgroupGetMemoryHardLimit(priv->cgroup, &val);
7323 7324 7325
            if (rc != 0) {
                virReportSystemError(-rc, "%s",
                                     _("unable to get memory hard limit"));
7326
                goto cleanup;
7327
            }
7328 7329 7330
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_MEMORY_HARD_LIMIT,
                                        VIR_TYPED_PARAM_ULLONG, val) < 0)
7331
                goto cleanup;
7332 7333 7334
            break;

        case 1: /* fill memory soft limit here */
7335
            rc = virCgroupGetMemorySoftLimit(priv->cgroup, &val);
7336 7337 7338
            if (rc != 0) {
                virReportSystemError(-rc, "%s",
                                     _("unable to get memory soft limit"));
7339
                goto cleanup;
7340
            }
7341 7342 7343
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_MEMORY_SOFT_LIMIT,
                                        VIR_TYPED_PARAM_ULLONG, val) < 0)
7344
                goto cleanup;
7345 7346 7347
            break;

        case 2: /* fill swap hard limit here */
7348
            rc = virCgroupGetMemSwapHardLimit(priv->cgroup, &val);
7349 7350 7351
            if (rc != 0) {
                virReportSystemError(-rc, "%s",
                                     _("unable to get swap hard limit"));
7352
                goto cleanup;
7353
            }
7354 7355 7356
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
                                        VIR_TYPED_PARAM_ULLONG, val) < 0)
7357
                goto cleanup;
7358 7359 7360 7361 7362 7363 7364 7365
            break;

        default:
            break;
            /* should not hit here */
        }
    }

7366
out:
7367 7368
    if (QEMU_NB_MEM_PARAM < *nparams)
        *nparams = QEMU_NB_MEM_PARAM;
7369 7370
    ret = 0;

7371 7372
cleanup:
    if (vm)
7373
        virObjectUnlock(vm);
7374
    virObjectUnref(caps);
7375 7376 7377
    return ret;
}

7378 7379 7380 7381 7382 7383
static int
qemuDomainSetNumaParameters(virDomainPtr dom,
                            virTypedParameterPtr params,
                            int nparams,
                            unsigned int flags)
{
7384
    virQEMUDriverPtr driver = dom->conn->privateData;
7385 7386 7387 7388
    int i;
    virDomainDefPtr persistentDef = NULL;
    virDomainObjPtr vm = NULL;
    int ret = -1;
7389
    virQEMUDriverConfigPtr cfg = NULL;
7390
    virCapsPtr caps = NULL;
7391
    qemuDomainObjPrivatePtr priv;
7392 7393 7394

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
7395 7396 7397 7398 7399 7400 7401
    if (virTypedParameterArrayValidate(params, nparams,
                                       VIR_DOMAIN_NUMA_MODE,
                                       VIR_TYPED_PARAM_INT,
                                       VIR_DOMAIN_NUMA_NODESET,
                                       VIR_TYPED_PARAM_STRING,
                                       NULL) < 0)
        return -1;
7402

7403 7404
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7405

7406
    priv = vm->privateData;
7407
    cfg = virQEMUDriverGetConfig(driver);
7408

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

7412
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7413 7414 7415 7416
                                        &persistentDef) < 0)
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7417
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
7418 7419
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup cpuset controller is not mounted"));
7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430
            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) {
7431 7432
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("can't change numa mode for running domain"));
7433 7434 7435 7436 7437 7438 7439 7440 7441
                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;
7442
            virBitmapPtr nodeset = NULL;
7443 7444
            char *nodeset_str = NULL;

7445 7446 7447
            if (virBitmapParse(params[i].value.s,
                               0, &nodeset,
                               VIR_DOMAIN_CPUMASK_LEN) < 0) {
7448 7449 7450 7451 7452
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to parse nodeset"));
                ret = -1;
                continue;
            }
7453 7454 7455 7456

            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
                if (vm->def->numatune.memory.mode !=
                    VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
7457 7458 7459
                    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                                   _("change of nodeset for running domain "
                                     "requires strict numa mode"));
7460
                    virBitmapFree(nodeset);
7461 7462 7463
                    ret = -1;
                    continue;
                }
7464 7465

                /* Ensure the cpuset string is formated before passing to cgroup */
7466
                if (!(nodeset_str = virBitmapFormat(nodeset))) {
7467 7468
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("Failed to format nodeset"));
7469
                    virBitmapFree(nodeset);
7470 7471 7472 7473
                    ret = -1;
                    continue;
                }

O
Osier Yang 已提交
7474
                if ((rc = virCgroupSetCpusetMems(priv->cgroup, nodeset_str)) != 0) {
7475 7476
                    virReportSystemError(-rc, "%s",
                                         _("unable to set numa tunable"));
7477
                    virBitmapFree(nodeset);
7478
                    VIR_FREE(nodeset_str);
7479 7480 7481
                    ret = -1;
                    continue;
                }
7482
                VIR_FREE(nodeset_str);
7483 7484 7485

                /* update vm->def here so that dumpxml can read the new
                 * values from vm->def. */
7486
                virBitmapFree(vm->def->numatune.memory.nodemask);
7487

7488
                vm->def->numatune.memory.placement_mode =
G
Gao feng 已提交
7489
                    VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_STATIC;
7490
                vm->def->numatune.memory.nodemask = virBitmapNewCopy(nodeset);
7491 7492 7493
            }

            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7494
                virBitmapFree(persistentDef->numatune.memory.nodemask);
7495 7496

                persistentDef->numatune.memory.nodemask = nodeset;
7497
                persistentDef->numatune.memory.placement_mode =
G
Gao feng 已提交
7498
                    VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_STATIC;
7499
                nodeset = NULL;
7500
            }
7501
            virBitmapFree(nodeset);
7502 7503 7504 7505
        }
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7506 7507
        if (!persistentDef->numatune.memory.placement_mode)
            persistentDef->numatune.memory.placement_mode =
G
Gao feng 已提交
7508
                VIR_NUMA_TUNE_MEM_PLACEMENT_MODE_AUTO;
7509
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
7510 7511 7512 7513 7514
            ret = -1;
    }

cleanup:
    if (vm)
7515
        virObjectUnlock(vm);
7516
    virObjectUnref(caps);
7517
    virObjectUnref(cfg);
7518 7519 7520 7521 7522 7523 7524 7525 7526
    return ret;
}

static int
qemuDomainGetNumaParameters(virDomainPtr dom,
                            virTypedParameterPtr params,
                            int *nparams,
                            unsigned int flags)
{
7527
    virQEMUDriverPtr driver = dom->conn->privateData;
7528 7529 7530 7531 7532 7533
    int i;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr persistentDef = NULL;
    char *nodeset = NULL;
    int ret = -1;
    int rc;
7534
    virCapsPtr caps = NULL;
7535
    qemuDomainObjPrivatePtr priv;
7536 7537 7538 7539 7540 7541 7542 7543 7544 7545

    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;

7546 7547
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7548

7549 7550
    priv = vm->privateData;

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

7554
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7555 7556 7557 7558 7559 7560 7561 7562 7563 7564
                                        &persistentDef) < 0)
        goto cleanup;

    if ((*nparams) == 0) {
        *nparams = QEMU_NB_NUMA_PARAM;
        ret = 0;
        goto cleanup;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7565
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
7566 7567
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup memory controller is not mounted"));
7568 7569 7570 7571 7572 7573 7574 7575 7576
            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 */
7577 7578
            if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
                                        VIR_TYPED_PARAM_INT, 0) < 0)
7579 7580 7581 7582 7583 7584 7585 7586 7587
                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) {
7588 7589
                nodeset = virBitmapFormat(persistentDef->numatune.memory.nodemask);
                if (!nodeset)
7590 7591
                    nodeset = strdup("");
            } else {
7592
                rc = virCgroupGetCpusetMems(priv->cgroup, &nodeset);
7593 7594 7595 7596 7597 7598
                if (rc != 0) {
                    virReportSystemError(-rc, "%s",
                                         _("unable to get numa nodeset"));
                    goto cleanup;
                }
            }
7599 7600
            if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
                                        VIR_TYPED_PARAM_STRING, nodeset) < 0)
7601
                goto cleanup;
S
Stefan Berger 已提交
7602 7603 7604

            nodeset = NULL;

7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617
            break;

        default:
            break;
            /* should not hit here */
        }
    }

    if (*nparams > QEMU_NB_NUMA_PARAM)
        *nparams = QEMU_NB_NUMA_PARAM;
    ret = 0;

cleanup:
S
Stefan Berger 已提交
7618
    VIR_FREE(nodeset);
7619
    if (vm)
7620
        virObjectUnlock(vm);
7621
    virObjectUnref(caps);
7622 7623 7624
    return ret;
}

7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636
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 已提交
7637 7638 7639 7640 7641 7642
    /* 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++) {
7643
            rc = virCgroupNewVcpu(cgroup, i, false, &cgroup_vcpu);
W
Wen Congyang 已提交
7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656
            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);
        }
7657 7658 7659 7660 7661 7662 7663 7664 7665
    }

    return 0;

cleanup:
    virCgroupFree(&cgroup_vcpu);
    return -1;
}

7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680
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;
    }

7681
    rc = virCgroupNewEmulator(cgroup, false, &cgroup_emulator);
7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699
    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;
}

7700 7701 7702 7703 7704 7705 7706 7707 7708
#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;                                                       \
    }

7709 7710 7711 7712 7713
static int
qemuSetSchedulerParametersFlags(virDomainPtr dom,
                                virTypedParameterPtr params,
                                int nparams,
                                unsigned int flags)
7714
{
7715
    virQEMUDriverPtr driver = dom->conn->privateData;
7716 7717 7718
    int i;
    virCgroupPtr group = NULL;
    virDomainObjPtr vm = NULL;
7719
    virDomainDefPtr vmdef = NULL;
7720 7721
    unsigned long long value_ul;
    long long value_l;
7722
    int ret = -1;
7723
    int rc;
7724
    virQEMUDriverConfigPtr cfg = NULL;
7725
    virCapsPtr caps = NULL;
7726
    qemuDomainObjPrivatePtr priv;
7727

7728 7729
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
7730 7731 7732 7733 7734 7735 7736
    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,
7737 7738 7739 7740
                                       VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
                                       VIR_TYPED_PARAM_ULLONG,
                                       VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
                                       VIR_TYPED_PARAM_LLONG,
7741 7742
                                       NULL) < 0)
        return -1;
7743

7744 7745
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
7746

7747
    priv = vm->privateData;
7748 7749
    cfg = virQEMUDriverGetConfig(driver);

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

7753
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
7754 7755
                                        &vmdef) < 0)
        goto cleanup;
7756

7757 7758
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        /* Make a copy for updated domain. */
7759
        vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
7760 7761
        if (!vmdef)
            goto cleanup;
7762 7763
    }

7764
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7765
        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
7766 7767
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("cgroup CPU controller is not mounted"));
7768 7769 7770 7771
            goto cleanup;
        }
    }

7772
    for (i = 0; i < nparams; i++) {
7773
        virTypedParameterPtr param = &params[i];
7774 7775
        value_ul = param->value.ul;
        value_l = param->value.l;
7776

7777
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
7778
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7779
                if ((rc = virCgroupSetCpuShares(priv->cgroup, value_ul))) {
7780 7781 7782 7783
                    virReportSystemError(-rc, "%s",
                                         _("unable to set cpu shares tunable"));
                    goto cleanup;
                }
7784
                vm->def->cputune.shares = value_ul;
7785
            }
7786

7787 7788 7789
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.shares = value_ul;

7790
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
7791 7792 7793
            SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
                              QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);

7794 7795
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
                if ((rc = qemuSetVcpusBWLive(vm, group, value_ul, 0)))
7796
                    goto cleanup;
7797

7798
                vm->def->cputune.period = value_ul;
7799 7800
            }

7801
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
7802
                vmdef->cputune.period = params[i].value.ul;
7803

7804
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
7805 7806 7807
            SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
                              QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);

7808 7809
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
                if ((rc = qemuSetVcpusBWLive(vm, group, 0, value_l)))
7810
                    goto cleanup;
7811

7812
                vm->def->cputune.quota = value_l;
7813 7814
            }

7815 7816 7817
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.quota = value_l;

7818
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD)) {
7819 7820 7821
            SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
                              QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);

7822 7823
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_ul) {
                if ((rc = qemuSetEmulatorBandwidthLive(vm, group, value_ul, 0)))
7824 7825
                    goto cleanup;

7826
                vm->def->cputune.emulator_period = value_ul;
7827 7828
            }

7829 7830 7831
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.emulator_period = value_ul;

7832
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA)) {
7833 7834 7835
            SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
                              QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);

7836 7837
            if (flags & VIR_DOMAIN_AFFECT_LIVE && value_l) {
                if ((rc = qemuSetEmulatorBandwidthLive(vm, group, 0, value_l)))
7838 7839
                    goto cleanup;

7840
                vm->def->cputune.emulator_quota = value_l;
7841 7842
            }

7843 7844
            if (flags & VIR_DOMAIN_AFFECT_CONFIG)
                vmdef->cputune.emulator_quota = value_l;
7845 7846
        }
    }
7847

7848
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
7849 7850 7851 7852
        goto cleanup;


    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7853
        rc = virDomainSaveConfig(cfg->configDir, vmdef);
7854 7855 7856
        if (rc < 0)
            goto cleanup;

7857
        virDomainObjAssignDef(vm, vmdef, false, NULL);
7858 7859 7860
        vmdef = NULL;
    }

7861 7862 7863
    ret = 0;

cleanup:
7864
    virDomainDefFree(vmdef);
7865
    if (vm)
7866
        virObjectUnlock(vm);
7867
    virObjectUnref(caps);
7868
    virObjectUnref(cfg);
7869 7870
    return ret;
}
7871
#undef SCHED_RANGE_CHECK
7872

7873 7874 7875 7876
static int
qemuSetSchedulerParameters(virDomainPtr dom,
                           virTypedParameterPtr params,
                           int nparams)
7877 7878 7879 7880
{
    return qemuSetSchedulerParametersFlags(dom,
                                           params,
                                           nparams,
7881
                                           VIR_DOMAIN_AFFECT_CURRENT);
7882 7883
}

7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907
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
7908
qemuGetVcpusBWLive(virDomainObjPtr vm,
7909 7910 7911 7912 7913 7914 7915 7916 7917 7918
                   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 */
7919
        rc = qemuGetVcpuBWLive(priv->cgroup, period, quota);
7920 7921 7922 7923 7924 7925 7926 7927 7928
        if (rc < 0)
            goto cleanup;

        if (*quota > 0)
            *quota /= vm->def->vcpus;
        goto out;
    }

    /* get period and quota for vcpu0 */
7929
    rc = virCgroupNewVcpu(priv->cgroup, 0, false, &cgroup_vcpu);
7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948
    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;
}

7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966
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 */
7967
    rc = virCgroupNewEmulator(cgroup, false, &cgroup_emulator);
7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985
    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;
}

7986 7987 7988 7989 7990
static int
qemuGetSchedulerParametersFlags(virDomainPtr dom,
                                virTypedParameterPtr params,
                                int *nparams,
                                unsigned int flags)
7991
{
7992
    virQEMUDriverPtr driver = dom->conn->privateData;
7993
    virDomainObjPtr vm = NULL;
7994 7995 7996
    unsigned long long shares;
    unsigned long long period;
    long long quota;
7997 7998
    unsigned long long emulator_period;
    long long emulator_quota;
7999 8000
    int ret = -1;
    int rc;
8001
    bool cpu_bw_status = false;
8002
    int saved_nparams = 0;
8003
    virDomainDefPtr persistentDef;
8004
    virCapsPtr caps = NULL;
8005
    qemuDomainObjPrivatePtr priv;
8006

8007
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8008 8009
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
8010

8011 8012 8013
    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

8014 8015 8016 8017 8018
    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;

    priv = vm->privateData;

8019
    if (*nparams > 1) {
8020
        rc = qemuGetCpuBWStatus(priv->cgroup);
8021 8022 8023 8024 8025
        if (rc < 0)
            goto cleanup;
        cpu_bw_status = !!rc;
    }

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

8029
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
8030 8031
                                        &persistentDef) < 0)
        goto cleanup;
8032

8033
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8034 8035 8036 8037
        shares = persistentDef->cputune.shares;
        if (*nparams > 1 && cpu_bw_status) {
            period = persistentDef->cputune.period;
            quota = persistentDef->cputune.quota;
8038 8039
            emulator_period = persistentDef->cputune.emulator_period;
            emulator_quota = persistentDef->cputune.emulator_quota;
8040
        }
8041
        goto out;
8042 8043
    }

8044
    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
8045 8046
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cgroup CPU controller is not mounted"));
8047 8048 8049
        goto cleanup;
    }

8050
    rc = virCgroupGetCpuShares(priv->cgroup, &shares);
8051
    if (rc != 0) {
8052
        virReportSystemError(-rc, "%s",
8053 8054 8055
                             _("unable to get cpu shares tunable"));
        goto cleanup;
    }
8056 8057

    if (*nparams > 1 && cpu_bw_status) {
8058
        rc = qemuGetVcpusBWLive(vm, &period, &quota);
8059 8060 8061
        if (rc != 0)
            goto cleanup;
    }
8062 8063

    if (*nparams > 3 && cpu_bw_status) {
8064
        rc = qemuGetEmulatorBandwidthLive(vm, priv->cgroup, &emulator_period,
8065 8066 8067 8068 8069
                                          &emulator_quota);
        if (rc != 0)
            goto cleanup;
    }

8070
out:
8071 8072
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CPU_SHARES,
                                VIR_TYPED_PARAM_ULLONG, shares) < 0)
C
Chris Lalancette 已提交
8073
        goto cleanup;
8074 8075 8076 8077
    saved_nparams++;

    if (cpu_bw_status) {
        if (*nparams > saved_nparams) {
8078 8079 8080
            if (virTypedParameterAssign(&params[1],
                                        VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
                                        VIR_TYPED_PARAM_ULLONG, period) < 0)
8081 8082 8083 8084 8085
                goto cleanup;
            saved_nparams++;
        }

        if (*nparams > saved_nparams) {
8086 8087 8088
            if (virTypedParameterAssign(&params[2],
                                        VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
                                        VIR_TYPED_PARAM_LLONG, quota) < 0)
8089 8090 8091
                goto cleanup;
            saved_nparams++;
        }
8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109

        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++;
        }
8110 8111 8112 8113
    }

    *nparams = saved_nparams;

8114 8115 8116 8117
    ret = 0;

cleanup:
    if (vm)
8118
        virObjectUnlock(vm);
8119
    virObjectUnref(caps);
8120 8121 8122
    return ret;
}

8123 8124 8125 8126 8127 8128
static int
qemuGetSchedulerParameters(virDomainPtr dom,
                           virTypedParameterPtr params,
                           int *nparams)
{
    return qemuGetSchedulerParametersFlags(dom, params, nparams,
8129
                                           VIR_DOMAIN_AFFECT_CURRENT);
8130
}
8131

8132 8133 8134 8135 8136 8137 8138
/**
 * 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 已提交
8139 8140 8141 8142
qemuDomainBlockResize(virDomainPtr dom,
                      const char *path,
                      unsigned long long size,
                      unsigned int flags)
8143
{
8144
    virQEMUDriverPtr driver = dom->conn->privateData;
8145 8146 8147 8148 8149 8150
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1, i;
    char *device = NULL;
    virDomainDiskDefPtr disk = NULL;

E
Eric Blake 已提交
8151
    virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
8152 8153

    if (path[0] == '\0') {
8154 8155
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("empty path"));
8156 8157 8158
        return -1;
    }

E
Eric Blake 已提交
8159 8160 8161
    /* We prefer operating on bytes.  */
    if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) {
        if (size > ULLONG_MAX / 1024) {
8162 8163 8164
            virReportError(VIR_ERR_OVERFLOW,
                           _("size must be less than %llu"),
                           ULLONG_MAX / 1024);
E
Eric Blake 已提交
8165 8166 8167
            return -1;
        }
        size *= 1024;
8168 8169
    }

8170
    if (!(vm = qemuDomObjFromDomain(dom)))
8171 8172 8173 8174 8175 8176 8177 8178
        goto cleanup;

    priv = vm->privateData;

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

    if (!virDomainObjIsActive(vm)) {
8179 8180
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8181 8182 8183 8184
        goto endjob;
    }

    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
8185 8186
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
8187
        goto endjob;
8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212
    }
    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)
8213
        virObjectUnlock(vm);
8214 8215 8216
    return ret;
}

8217 8218 8219 8220 8221
/* 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
8222 8223 8224
qemuDomainBlockStats(virDomainPtr dom,
                     const char *path,
                     struct _virDomainBlockStats *stats)
8225
{
8226
    virQEMUDriverPtr driver = dom->conn->privateData;
8227
    int i, ret = -1;
8228
    virDomainObjPtr vm;
8229
    virDomainDiskDefPtr disk = NULL;
8230
    qemuDomainObjPrivatePtr priv;
8231

8232
    if (!(vm = qemuDomObjFromDomain(dom)))
8233
        goto cleanup;
8234

8235
    if (!virDomainObjIsActive(vm)) {
8236 8237
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8238 8239 8240
        goto cleanup;
    }

8241
    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
8242 8243
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path: %s"), path);
8244
        goto cleanup;
8245
    }
8246
    disk = vm->def->disks[i];
8247

8248
    if (!disk->info.alias) {
8249 8250
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("missing disk device alias name for %s"), disk->dst);
8251
        goto cleanup;
8252
    }
8253

8254
    priv = vm->privateData;
8255 8256
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
        goto cleanup;
8257

8258
    if (!virDomainObjIsActive(vm)) {
8259 8260
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8261 8262
        goto endjob;
    }
8263

8264
    qemuDomainObjEnterMonitor(driver, vm);
8265 8266 8267 8268
    ret = qemuMonitorGetBlockStatsInfo(priv->mon,
                                       disk->info.alias,
                                       &stats->rd_req,
                                       &stats->rd_bytes,
8269
                                       NULL,
8270 8271
                                       &stats->wr_req,
                                       &stats->wr_bytes,
8272 8273 8274
                                       NULL,
                                       NULL,
                                       NULL,
8275 8276
                                       &stats->errs);
    qemuDomainObjExitMonitor(driver, vm);
8277

8278
endjob:
8279 8280
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;
8281

8282
cleanup:
8283
    if (vm)
8284
        virObjectUnlock(vm);
8285
    return ret;
8286 8287
}

8288
static int
8289 8290 8291 8292 8293
qemuDomainBlockStatsFlags(virDomainPtr dom,
                          const char *path,
                          virTypedParameterPtr params,
                          int *nparams,
                          unsigned int flags)
8294
{
8295
    virQEMUDriverPtr driver = dom->conn->privateData;
8296 8297 8298 8299 8300 8301
    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;
8302
    virTypedParameterPtr param;
8303

8304 8305 8306 8307
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
8308

8309
    if (!(vm = qemuDomObjFromDomain(dom)))
8310 8311
        goto cleanup;

8312 8313 8314
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
        goto cleanup;

8315
    if (!virDomainObjIsActive(vm)) {
8316 8317
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8318
        goto endjob;
8319 8320 8321
    }

    if (*nparams != 0) {
8322
        if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
8323 8324
            virReportError(VIR_ERR_INVALID_ARG,
                           _("invalid path: %s"), path);
8325
            goto endjob;
8326
        }
8327
        disk = vm->def->disks[i];
8328 8329

        if (!disk->info.alias) {
8330 8331 8332
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("missing disk device alias name for %s"),
                            disk->dst);
8333
             goto endjob;
8334 8335 8336 8337 8338 8339 8340 8341 8342 8343
        }
    }

    priv = vm->privateData;
    VIR_DEBUG("priv=%p, params=%p, flags=%x", priv, params, flags);

    qemuDomainObjEnterMonitor(driver, vm);
    tmp = *nparams;
    ret = qemuMonitorGetBlockStatsParamsNumber(priv->mon, nparams);

8344
    if (tmp == 0 || ret < 0) {
8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365
        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;

8366 8367
    tmp = 0;
    ret = -1;
8368

8369 8370
    if (tmp < *nparams && wr_bytes != -1) {
        param = &params[tmp];
8371 8372
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES,
                                    VIR_TYPED_PARAM_LLONG, wr_bytes) < 0)
8373 8374 8375
            goto endjob;
        tmp++;
    }
8376

8377
    if (tmp < *nparams && wr_req != -1) {
8378
        param = &params[tmp];
8379 8380
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ,
                                    VIR_TYPED_PARAM_LLONG, wr_req) < 0)
8381 8382 8383
            goto endjob;
        tmp++;
    }
8384

8385
    if (tmp < *nparams && rd_bytes != -1) {
8386
        param = &params[tmp];
8387 8388
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_READ_BYTES,
                                    VIR_TYPED_PARAM_LLONG, rd_bytes) < 0)
8389 8390 8391
            goto endjob;
        tmp++;
    }
8392

8393
    if (tmp < *nparams && rd_req != -1) {
8394
        param = &params[tmp];
8395 8396
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_READ_REQ,
                                    VIR_TYPED_PARAM_LLONG, rd_req) < 0)
8397 8398 8399
            goto endjob;
        tmp++;
    }
8400

8401
    if (tmp < *nparams && flush_req != -1) {
8402
        param = &params[tmp];
8403 8404
        if (virTypedParameterAssign(param, VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ,
                                    VIR_TYPED_PARAM_LLONG, flush_req) < 0)
8405 8406 8407
            goto endjob;
        tmp++;
    }
8408

8409
    if (tmp < *nparams && wr_total_times != -1) {
8410
        param = &params[tmp];
8411 8412 8413
        if (virTypedParameterAssign(param,
                                    VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES,
                                    VIR_TYPED_PARAM_LLONG, wr_total_times) < 0)
8414 8415 8416
            goto endjob;
        tmp++;
    }
8417

8418
    if (tmp < *nparams && rd_total_times != -1) {
8419
        param = &params[tmp];
8420 8421 8422
        if (virTypedParameterAssign(param,
                                    VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES,
                                    VIR_TYPED_PARAM_LLONG, rd_total_times) < 0)
8423 8424 8425
            goto endjob;
        tmp++;
    }
8426

8427
    if (tmp < *nparams && flush_total_times != -1) {
8428
        param = &params[tmp];
8429 8430 8431 8432
        if (virTypedParameterAssign(param,
                                    VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES,
                                    VIR_TYPED_PARAM_LLONG,
                                    flush_total_times) < 0)
8433 8434
            goto endjob;
        tmp++;
8435 8436
    }

8437 8438 8439 8440 8441
    /* Field 'errs' is meaningless for QEMU, won't set it. */

    ret = 0;
    *nparams = tmp;

8442 8443 8444 8445 8446 8447
endjob:
    if (qemuDomainObjEndJob(driver, vm) == 0)
        vm = NULL;

cleanup:
    if (vm)
8448
        virObjectUnlock(vm);
8449 8450 8451
    return ret;
}

8452
#ifdef __linux__
8453
static int
8454 8455 8456
qemuDomainInterfaceStats(virDomainPtr dom,
                         const char *path,
                         struct _virDomainInterfaceStats *stats)
8457
{
8458
    virDomainObjPtr vm;
8459
    int i;
8460
    int ret = -1;
8461

8462
    if (!(vm = qemuDomObjFromDomain(dom)))
8463
        goto cleanup;
8464

D
Daniel P. Berrange 已提交
8465
    if (!virDomainObjIsActive(vm)) {
8466 8467
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8468
        goto cleanup;
8469 8470 8471
    }

    /* Check the path is one of the domain's network interfaces. */
8472 8473
    for (i = 0 ; i < vm->def->nnets ; i++) {
        if (vm->def->nets[i]->ifname &&
8474
            STREQ(vm->def->nets[i]->ifname, path)) {
8475 8476 8477
            ret = 0;
            break;
        }
8478 8479
    }

8480
    if (ret == 0)
8481
        ret = linuxDomainInterfaceStats(path, stats);
8482
    else
8483 8484
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path, '%s' is not a known interface"), path);
8485

8486
cleanup:
8487
    if (vm)
8488
        virObjectUnlock(vm);
8489 8490
    return ret;
}
8491
#else
8492
static int
E
Eric Blake 已提交
8493
qemuDomainInterfaceStats(virDomainPtr dom ATTRIBUTE_UNUSED,
8494 8495
                         const char *path ATTRIBUTE_UNUSED,
                         struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
8496
{
8497 8498
    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                   _("interface stats not implemented on this platform"));
8499 8500
    return -1;
}
8501
#endif
8502

8503 8504 8505 8506 8507 8508 8509
static int
qemuDomainSetInterfaceParameters(virDomainPtr dom,
                                 const char *device,
                                 virTypedParameterPtr params,
                                 int nparams,
                                 unsigned int flags)
{
8510
    virQEMUDriverPtr driver = dom->conn->privateData;
8511 8512 8513 8514 8515
    int i;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr persistentDef = NULL;
    int ret = -1;
    virDomainNetDefPtr net = NULL, persistentNet = NULL;
8516
    virNetDevBandwidthPtr bandwidth = NULL, newBandwidth = NULL;
8517
    virQEMUDriverConfigPtr cfg = NULL;
8518
    virCapsPtr caps = NULL;
8519 8520 8521

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536
    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;
8537

8538 8539
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
8540

8541 8542
    cfg = virQEMUDriverGetConfig(driver);

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

8546
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
8547 8548 8549 8550 8551 8552
                                        &persistentDef) < 0)
        goto cleanup;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        net = virDomainNetFind(vm->def, device);
        if (!net) {
8553 8554
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Can't find device %s"), device);
8555 8556 8557 8558 8559 8560
            goto cleanup;
        }
    }
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        persistentNet = virDomainNetFind(persistentDef, device);
        if (!persistentNet) {
8561 8562
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Can't find device %s"), device);
8563 8564 8565 8566
            goto cleanup;
        }
    }

8567 8568 8569
    if ((VIR_ALLOC(bandwidth) < 0) ||
        (VIR_ALLOC(bandwidth->in) < 0) ||
        (VIR_ALLOC(bandwidth->out) < 0)) {
8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591
        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;
        }
    }

8592
    /* average is mandatory, peak and burst are optional. So if no
8593
     * average is given, we free inbound/outbound here which causes
8594
     * inbound/outbound to not be set. */
8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609
    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
8610
         * here to prevent them from being lost. */
8611 8612
        if (bandwidth->in ||
            (net->bandwidth && net->bandwidth->in)) {
8613 8614 8615 8616
            if (VIR_ALLOC(newBandwidth->in) < 0) {
                virReportOOMError();
                goto cleanup;
            }
8617 8618 8619 8620 8621 8622 8623

            memcpy(newBandwidth->in,
                   bandwidth->in ? bandwidth->in : net->bandwidth->in,
                   sizeof(*newBandwidth->in));
        }
        if (bandwidth->out ||
            (net->bandwidth && net->bandwidth->out)) {
8624 8625 8626 8627
            if (VIR_ALLOC(newBandwidth->out) < 0) {
                virReportOOMError();
                goto cleanup;
            }
8628 8629 8630 8631

            memcpy(newBandwidth->out,
                   bandwidth->out ? bandwidth->out : net->bandwidth->out,
                   sizeof(*newBandwidth->out));
8632 8633
        }

8634
        if (virNetDevBandwidthSet(net->ifname, newBandwidth, false) < 0) {
8635 8636 8637
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("cannot set bandwidth limits on %s"),
                           device);
8638 8639 8640 8641 8642
            goto cleanup;
        }

        virNetDevBandwidthFree(net->bandwidth);
        net->bandwidth = newBandwidth;
E
Eric Blake 已提交
8643
        newBandwidth = NULL;
8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661
    }
    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;
            }
        }

8662
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
8663 8664 8665 8666 8667 8668
            goto cleanup;
    }

    ret = 0;
cleanup:
    virNetDevBandwidthFree(bandwidth);
8669
    virNetDevBandwidthFree(newBandwidth);
8670
    if (vm)
8671
        virObjectUnlock(vm);
8672
    virObjectUnref(caps);
8673
    virObjectUnref(cfg);
8674 8675 8676 8677 8678 8679 8680 8681 8682 8683
    return ret;
}

static int
qemuDomainGetInterfaceParameters(virDomainPtr dom,
                                 const char *device,
                                 virTypedParameterPtr params,
                                 int *nparams,
                                 unsigned int flags)
{
8684
    virQEMUDriverPtr driver = dom->conn->privateData;
8685 8686 8687 8688 8689 8690
    int i;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainDefPtr persistentDef = NULL;
    virDomainNetDefPtr net = NULL;
    int ret = -1;
8691
    virCapsPtr caps = NULL;
8692 8693 8694 8695 8696 8697 8698

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

8699 8700
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
8701

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

8705
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720
                                        &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) {
8721 8722
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Can't find device %s"), device);
8723 8724 8725 8726
        goto cleanup;
    }

    for (i = 0; i < *nparams && i < QEMU_NB_BANDWIDTH_PARAM; i++) {
8727
        switch (i) {
8728
        case 0: /* inbound.average */
8729 8730 8731
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
8732 8733 8734 8735 8736
                goto cleanup;
            if (net->bandwidth && net->bandwidth->in)
                params[i].value.ui = net->bandwidth->in->average;
            break;
        case 1: /* inbound.peak */
8737 8738 8739
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_IN_PEAK,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
8740 8741 8742 8743 8744
                goto cleanup;
            if (net->bandwidth && net->bandwidth->in)
                params[i].value.ui = net->bandwidth->in->peak;
            break;
        case 2: /* inbound.burst */
8745 8746 8747
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_IN_BURST,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
8748 8749 8750 8751 8752
                goto cleanup;
            if (net->bandwidth && net->bandwidth->in)
                params[i].value.ui = net->bandwidth->in->burst;
            break;
        case 3: /* outbound.average */
8753 8754 8755
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
8756 8757 8758 8759 8760
                goto cleanup;
            if (net->bandwidth && net->bandwidth->out)
                params[i].value.ui = net->bandwidth->out->average;
            break;
        case 4: /* outbound.peak */
8761 8762 8763
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
8764 8765 8766 8767 8768
                goto cleanup;
            if (net->bandwidth && net->bandwidth->out)
                params[i].value.ui = net->bandwidth->out->peak;
            break;
        case 5: /* outbound.burst */
8769 8770 8771
            if (virTypedParameterAssign(&params[i],
                                        VIR_DOMAIN_BANDWIDTH_OUT_BURST,
                                        VIR_TYPED_PARAM_UINT, 0) < 0)
8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787
                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)
8788
        virObjectUnlock(vm);
8789
    virObjectUnref(caps);
8790 8791 8792
    return ret;
}

8793
static int
8794 8795 8796 8797
qemuDomainMemoryStats(virDomainPtr dom,
                      struct _virDomainMemoryStat *stats,
                      unsigned int nr_stats,
                      unsigned int flags)
8798
{
8799
    virQEMUDriverPtr driver = dom->conn->privateData;
8800
    virDomainObjPtr vm;
M
Martin Kletzander 已提交
8801
    int ret = -1;
8802

8803 8804
    virCheckFlags(0, -1);

8805
    if (!(vm = qemuDomObjFromDomain(dom)))
8806 8807
        goto cleanup;

8808
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
8809 8810
        goto cleanup;

M
Martin Kletzander 已提交
8811
    if (!virDomainObjIsActive(vm)) {
8812 8813
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
M
Martin Kletzander 已提交
8814
    } else {
8815
        qemuDomainObjPrivatePtr priv = vm->privateData;
8816
        qemuDomainObjEnterMonitor(driver, vm);
8817
        ret = qemuMonitorGetMemoryStats(priv->mon, stats, nr_stats);
8818
        qemuDomainObjExitMonitor(driver, vm);
M
Martin Kletzander 已提交
8819 8820 8821

        if (ret >= 0 && ret < nr_stats) {
            long rss;
8822
            if (qemuGetProcessInfo(NULL, NULL, &rss, vm->pid, 0) < 0) {
8823 8824
                virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                               _("cannot get RSS for domain"));
M
Martin Kletzander 已提交
8825 8826 8827 8828 8829 8830 8831
            } else {
                stats[ret].tag = VIR_DOMAIN_MEMORY_STAT_RSS;
                stats[ret].val = rss;
                ret++;
            }

        }
8832 8833
    }

8834
    if (qemuDomainObjEndJob(driver, vm) == 0)
8835 8836
        vm = NULL;

8837 8838
cleanup:
    if (vm)
8839
        virObjectUnlock(vm);
8840 8841 8842
    return ret;
}

8843
static int
8844 8845 8846 8847 8848
qemuDomainBlockPeek(virDomainPtr dom,
                    const char *path,
                    unsigned long long offset, size_t size,
                    void *buffer,
                    unsigned int flags)
8849
{
8850
    virDomainObjPtr vm;
8851 8852
    int fd = -1, ret = -1;
    const char *actual;
8853

E
Eric Blake 已提交
8854 8855
    virCheckFlags(0, -1);

8856
    if (!(vm = qemuDomObjFromDomain(dom)))
8857
        goto cleanup;
8858 8859

    if (!path || path[0] == '\0') {
8860 8861
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("NULL or empty path"));
8862
        goto cleanup;
8863 8864
    }

8865 8866
    /* Check the path belongs to this domain.  */
    if (!(actual = virDomainDiskPathByName(vm->def, path))) {
8867 8868
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path '%s'"), path);
8869
        goto cleanup;
8870
    }
8871
    path = actual;
8872

8873 8874 8875 8876 8877 8878 8879
    /* 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;
    }
8880

8881 8882 8883 8884 8885 8886 8887 8888 8889
    /* 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;
8890 8891
    }

8892 8893
    ret = 0;

8894
cleanup:
8895
    VIR_FORCE_CLOSE(fd);
8896
    if (vm)
8897
        virObjectUnlock(vm);
8898 8899 8900
    return ret;
}

R
Richard W.M. Jones 已提交
8901
static int
8902 8903 8904 8905
qemuDomainMemoryPeek(virDomainPtr dom,
                     unsigned long long offset, size_t size,
                     void *buffer,
                     unsigned int flags)
R
Richard W.M. Jones 已提交
8906
{
8907
    virQEMUDriverPtr driver = dom->conn->privateData;
8908
    virDomainObjPtr vm;
8909
    char *tmp = NULL;
R
Richard W.M. Jones 已提交
8910
    int fd = -1, ret = -1;
8911
    qemuDomainObjPrivatePtr priv;
8912
    virQEMUDriverConfigPtr cfg = NULL;
R
Richard W.M. Jones 已提交
8913

8914 8915
    virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);

8916
    if (!(vm = qemuDomObjFromDomain(dom)))
8917 8918
        goto cleanup;

8919 8920
    cfg = virQEMUDriverGetConfig(driver);

8921
    if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
8922 8923
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
8924
        goto cleanup;
R
Richard W.M. Jones 已提交
8925 8926
    }

8927
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
8928 8929
        goto cleanup;

D
Daniel P. Berrange 已提交
8930
    if (!virDomainObjIsActive(vm)) {
8931 8932
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
8933
        goto endjob;
R
Richard W.M. Jones 已提交
8934 8935
    }

8936
    if (virAsprintf(&tmp, "%s/qemu.mem.XXXXXX", cfg->cacheDir) < 0) {
8937
        virReportOOMError();
8938
        goto endjob;
8939 8940
    }

R
Richard W.M. Jones 已提交
8941
    /* Create a temporary filename. */
8942
    if ((fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
8943
        virReportSystemError(errno,
8944
                             _("mkostemp(\"%s\") failed"), tmp);
8945
        goto endjob;
R
Richard W.M. Jones 已提交
8946 8947
    }

8948
    virSecurityManagerSetSavedStateLabel(qemu_driver->securityManager, vm->def, tmp);
8949

8950
    priv = vm->privateData;
8951
    qemuDomainObjEnterMonitor(driver, vm);
8952
    if (flags == VIR_MEMORY_VIRTUAL) {
8953
        if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
8954
            qemuDomainObjExitMonitor(driver, vm);
8955
            goto endjob;
8956
        }
8957
    } else {
8958
        if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
8959
            qemuDomainObjExitMonitor(driver, vm);
8960
            goto endjob;
8961
        }
R
Richard W.M. Jones 已提交
8962
    }
8963
    qemuDomainObjExitMonitor(driver, vm);
R
Richard W.M. Jones 已提交
8964 8965

    /* Read the memory file into buffer. */
8966
    if (saferead(fd, buffer, size) == (ssize_t) -1) {
8967 8968 8969
        virReportSystemError(errno,
                             _("failed to read temporary file "
                               "created with template %s"), tmp);
8970
        goto endjob;
R
Richard W.M. Jones 已提交
8971 8972 8973
    }

    ret = 0;
8974

8975
endjob:
8976
    if (qemuDomainObjEndJob(driver, vm) == 0)
8977
        vm = NULL;
8978

8979
cleanup:
8980
    VIR_FORCE_CLOSE(fd);
8981 8982
    if (tmp)
        unlink(tmp);
W
Wen Congyang 已提交
8983
    VIR_FREE(tmp);
8984
    if (vm)
8985
        virObjectUnlock(vm);
8986
    virObjectUnref(cfg);
R
Richard W.M. Jones 已提交
8987 8988 8989
    return ret;
}

8990

8991 8992 8993 8994
static int qemuDomainGetBlockInfo(virDomainPtr dom,
                                  const char *path,
                                  virDomainBlockInfoPtr info,
                                  unsigned int flags) {
8995
    virQEMUDriverPtr driver = dom->conn->privateData;
8996 8997 8998 8999
    virDomainObjPtr vm;
    int ret = -1;
    int fd = -1;
    off_t end;
9000
    virStorageFileMetadata *meta = NULL;
9001
    virDomainDiskDefPtr disk = NULL;
9002
    struct stat sb;
9003
    int i;
9004
    int format;
9005
    virQEMUDriverConfigPtr cfg = NULL;
9006 9007 9008

    virCheckFlags(0, -1);

9009
    if (!(vm = qemuDomObjFromDomain(dom)))
9010 9011
        goto cleanup;

9012 9013
    cfg = virQEMUDriverGetConfig(driver);

9014
    if (!path || path[0] == '\0') {
9015 9016
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("NULL or empty path"));
9017 9018 9019 9020
        goto cleanup;
    }

    /* Check the path belongs to this domain. */
9021
    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
9022 9023
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid path %s not assigned to domain"), path);
9024 9025
        goto cleanup;
    }
9026 9027
    disk = vm->def->disks[i];
    if (!disk->src) {
9028 9029 9030
        virReportError(VIR_ERR_INVALID_ARG,
                       _("disk %s does not currently have a source assigned"),
                       path);
9031 9032 9033
        goto cleanup;
    }
    path = disk->src;
9034 9035

    /* The path is correct, now try to open it and get its size. */
9036
    fd = open(path, O_RDONLY);
9037 9038 9039 9040 9041 9042 9043
    if (fd == -1) {
        virReportSystemError(errno,
                             _("failed to open path '%s'"), path);
        goto cleanup;
    }

    /* Probe for magic formats */
9044 9045
    if (disk->format) {
        format = disk->format;
9046
    } else {
9047 9048 9049 9050
        if (cfg->allowDiskFormatProbing) {
            if ((format = virStorageFileProbeFormat(disk->src,
                                                    cfg->user,
                                                    cfg->group)) < 0)
9051 9052
                goto cleanup;
        } else {
9053 9054 9055
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("no disk format for %s and probing is disabled"),
                           disk->src);
9056
            goto cleanup;
9057
        }
9058 9059
    }

9060
    if (!(meta = virStorageFileGetMetadataFromFD(path, fd, format)))
9061 9062 9063 9064 9065 9066 9067 9068 9069 9070
        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)) {
9071
#ifndef WIN32
9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084
        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.
         */
9085
        end = lseek(fd, 0, SEEK_END);
9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096
        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 */
9097 9098
    if (meta->capacity)
        info->capacity = meta->capacity;
9099

9100
    /* Set default value .. */
9101 9102
    info->allocation = info->physical;

9103 9104 9105
    /* ..but if guest is running & not using raw
       disk format and on a block device, then query
       highest allocated extent from QEMU */
9106
    if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
9107
        format != VIR_STORAGE_FILE_RAW &&
9108 9109
        S_ISBLK(sb.st_mode) &&
        virDomainObjIsActive(vm)) {
9110
        qemuDomainObjPrivatePtr priv = vm->privateData;
9111

9112 9113
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
            goto cleanup;
9114

9115
        if (virDomainObjIsActive(vm)) {
9116
            qemuDomainObjEnterMonitor(driver, vm);
9117 9118 9119 9120
            ret = qemuMonitorGetBlockExtent(priv->mon,
                                            disk->info.alias,
                                            &info->allocation);
            qemuDomainObjExitMonitor(driver, vm);
9121
        } else {
9122
            ret = 0;
9123
        }
9124 9125 9126

        if (qemuDomainObjEndJob(driver, vm) == 0)
            vm = NULL;
9127 9128 9129
    } else {
        ret = 0;
    }
9130 9131

cleanup:
9132
    virStorageFileFreeMetadata(meta);
9133
    VIR_FORCE_CLOSE(fd);
9134
    if (vm)
9135
        virObjectUnlock(vm);
9136
    virObjectUnref(cfg);
9137 9138 9139 9140
    return ret;
}


9141
static int
9142 9143 9144 9145
qemuDomainEventRegister(virConnectPtr conn,
                        virConnectDomainEventCallback callback,
                        void *opaque,
                        virFreeCallback freecb)
9146
{
9147
    virQEMUDriverPtr driver = conn->privateData;
9148 9149
    int ret;

9150 9151 9152
    ret = virDomainEventStateRegister(conn,
                                      driver->domainEventState,
                                      callback, opaque, freecb);
9153

9154
    return ret;
9155 9156
}

9157

9158
static int
9159 9160
qemuDomainEventDeregister(virConnectPtr conn,
                          virConnectDomainEventCallback callback)
9161
{
9162
    virQEMUDriverPtr driver = conn->privateData;
9163 9164
    int ret;

9165 9166 9167
    ret = virDomainEventStateDeregister(conn,
                                        driver->domainEventState,
                                        callback);
9168

9169
    return ret;
9170 9171
}

9172 9173 9174 9175 9176 9177 9178 9179 9180

static int
qemuDomainEventRegisterAny(virConnectPtr conn,
                           virDomainPtr dom,
                           int eventID,
                           virConnectDomainEventGenericCallback callback,
                           void *opaque,
                           virFreeCallback freecb)
{
9181
    virQEMUDriverPtr driver = conn->privateData;
9182 9183
    int ret;

9184 9185 9186 9187
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID,
                                      callback, opaque, freecb, &ret) < 0)
9188
        ret = -1;
9189 9190 9191 9192 9193 9194 9195 9196 9197

    return ret;
}


static int
qemuDomainEventDeregisterAny(virConnectPtr conn,
                             int callbackID)
{
9198
    virQEMUDriverPtr driver = conn->privateData;
9199 9200
    int ret;

9201 9202 9203
    ret = virDomainEventStateDeregisterID(conn,
                                          driver->domainEventState,
                                          callbackID);
9204 9205 9206 9207 9208

    return ret;
}


9209 9210 9211
/*******************************************************************
 * Migration Protocol Version 2
 *******************************************************************/
D
Daniel Veillard 已提交
9212

C
Chris Lalancette 已提交
9213 9214 9215 9216 9217 9218
/* 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
9219 9220 9221 9222 9223 9224
qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
                               virStreamPtr st,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource ATTRIBUTE_UNUSED,
                               const char *dom_xml)
C
Chris Lalancette 已提交
9225
{
9226
    virQEMUDriverPtr driver = dconn->privateData;
C
Chris Lalancette 已提交
9227
    int ret = -1;
9228

9229
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9230

C
Chris Lalancette 已提交
9231
    if (!dom_xml) {
9232 9233
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
C
Chris Lalancette 已提交
9234 9235 9236
        goto cleanup;
    }
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
9237 9238
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
C
Chris Lalancette 已提交
9239 9240 9241
        goto cleanup;
    }
    if (st == NULL) {
9242 9243
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("tunnelled migration requested but NULL stream passed"));
C
Chris Lalancette 已提交
9244 9245 9246
        goto cleanup;
    }

9247
    if (virLockManagerPluginUsesState(driver->lockManager)) {
9248 9249 9250
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Cannot use migrate v2 protocol with lock manager %s"),
                       virLockManagerPluginGetName(driver->lockManager));
9251 9252 9253
        goto cleanup;
    }

9254 9255
    ret = qemuMigrationPrepareTunnel(driver, dconn,
                                     NULL, 0, NULL, NULL, /* No cookies in v2 */
L
liguang 已提交
9256
                                     st, dname, dom_xml, flags);
9257

C
Chris Lalancette 已提交
9258 9259 9260 9261
cleanup:
    return ret;
}

D
Daniel Veillard 已提交
9262 9263 9264 9265
/* Prepare is the first step, and it runs on the destination host.
 *
 * This starts an empty VM listening on a TCP port.
 */
9266
static int ATTRIBUTE_NONNULL(5)
9267 9268 9269 9270 9271 9272 9273 9274 9275
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 已提交
9276
{
9277
    virQEMUDriverPtr driver = dconn->privateData;
9278
    int ret = -1;
9279

9280
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
C
Chris Lalancette 已提交
9281

9282
    *uri_out = NULL;
D
Daniel Veillard 已提交
9283

9284
    if (virLockManagerPluginUsesState(driver->lockManager)) {
9285 9286 9287
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Cannot use migrate v2 protocol with lock manager %s"),
                       virLockManagerPluginGetName(driver->lockManager));
9288 9289 9290
        goto cleanup;
    }

C
Chris Lalancette 已提交
9291 9292 9293 9294
    if (flags & VIR_MIGRATE_TUNNELLED) {
        /* this is a logical error; we never should have gotten here with
         * VIR_MIGRATE_TUNNELLED set
         */
9295 9296
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Tunnelled migration requested but invalid RPC method called"));
C
Chris Lalancette 已提交
9297 9298 9299
        goto cleanup;
    }

D
Daniel Veillard 已提交
9300
    if (!dom_xml) {
9301 9302
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
9303
        goto cleanup;
D
Daniel Veillard 已提交
9304 9305
    }

9306 9307 9308 9309
    /* Do not use cookies in v2 protocol, since the cookie
     * length was not sufficiently large, causing failures
     * migrating between old & new libvirtd
     */
9310
    ret = qemuMigrationPrepareDirect(driver, dconn,
9311
                                     NULL, 0, NULL, NULL, /* No cookies */
9312
                                     uri_in, uri_out,
L
liguang 已提交
9313
                                     dname, dom_xml, flags);
D
Daniel Veillard 已提交
9314

9315 9316 9317
cleanup:
    return ret;
}
C
Chris Lalancette 已提交
9318

D
Daniel Veillard 已提交
9319

9320 9321
/* Perform is the second step, and it runs on the source host. */
static int
9322 9323 9324 9325 9326 9327 9328
qemuDomainMigratePerform(virDomainPtr dom,
                         const char *cookie,
                         int cookielen,
                         const char *uri,
                         unsigned long flags,
                         const char *dname,
                         unsigned long resource)
9329
{
9330
    virQEMUDriverPtr driver = dom->conn->privateData;
9331 9332
    virDomainObjPtr vm;
    int ret = -1;
9333
    const char *dconnuri = NULL;
9334

9335
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
C
Chris Lalancette 已提交
9336

9337
    if (virLockManagerPluginUsesState(driver->lockManager)) {
9338 9339 9340
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Cannot use migrate v2 protocol with lock manager %s"),
                       virLockManagerPluginGetName(driver->lockManager));
9341 9342 9343
        goto cleanup;
    }

9344
    if (!(vm = qemuDomObjFromDomain(dom)))
9345
        goto cleanup;
D
Daniel Veillard 已提交
9346

9347 9348 9349 9350 9351
    if (flags & VIR_MIGRATE_PEER2PEER) {
        dconnuri = uri;
        uri = NULL;
    }

9352 9353 9354 9355 9356 9357
    /* 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
     */
9358
    ret = qemuMigrationPerform(driver, dom->conn, vm,
9359
                               NULL, dconnuri, uri, cookie, cookielen,
9360
                               NULL, NULL, /* No output cookies in v2 */
9361
                               flags, dname, resource, false);
9362

9363
cleanup:
9364
    return ret;
D
Daniel Veillard 已提交
9365 9366
}

9367

D
Daniel Veillard 已提交
9368 9369
/* Finish is the third and final step, and it runs on the destination host. */
static virDomainPtr
9370 9371 9372 9373 9374 9375 9376
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 已提交
9377
{
9378
    virQEMUDriverPtr driver = dconn->privateData;
9379 9380
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
D
Daniel Veillard 已提交
9381

9382
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
C
Chris Lalancette 已提交
9383

9384
    vm = virDomainObjListFindByName(driver->domains, dname);
D
Daniel Veillard 已提交
9385
    if (!vm) {
9386 9387
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching name '%s'"), dname);
9388
        goto cleanup;
D
Daniel Veillard 已提交
9389 9390
    }

9391 9392 9393 9394
    /* Do not use cookies in v2 protocol, since the cookie
     * length was not sufficiently large, causing failures
     * migrating between old & new libvirtd
     */
9395
    dom = qemuMigrationFinish(driver, dconn, vm,
9396
                              NULL, 0, NULL, NULL, /* No cookies */
9397
                              flags, retcode, false);
9398

9399 9400
cleanup:
    return dom;
D
Daniel Veillard 已提交
9401 9402
}

9403

9404 9405 9406 9407 9408 9409
/*******************************************************************
 * Migration Protocol Version 3
 *******************************************************************/

static char *
qemuDomainMigrateBegin3(virDomainPtr domain,
9410
                        const char *xmlin,
9411 9412 9413
                        char **cookieout,
                        int *cookieoutlen,
                        unsigned long flags,
9414
                        const char *dname,
9415 9416
                        unsigned long resource ATTRIBUTE_UNUSED)
{
9417
    virQEMUDriverPtr driver = domain->conn->privateData;
9418 9419
    virDomainObjPtr vm;
    char *xml = NULL;
9420
    enum qemuDomainAsyncJob asyncJob;
9421

9422
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
9423

9424 9425
    if (!(vm = qemuDomObjFromDomain(domain)))
        return NULL;
9426

9427 9428 9429
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
            goto cleanup;
9430
        asyncJob = QEMU_ASYNC_JOB_MIGRATION_OUT;
9431
    } else {
9432
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9433
            goto cleanup;
9434
        asyncJob = QEMU_ASYNC_JOB_NONE;
9435 9436
    }

L
liguang 已提交
9437
    if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
9438 9439
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
9440 9441 9442
        goto endjob;
    }

9443 9444 9445
    /* Check if there is any ejected media.
     * We don't want to require them on the destination.
     */
L
liguang 已提交
9446 9447
    if (!(flags & VIR_MIGRATE_OFFLINE) &&
        qemuDomainCheckEjectableMedia(driver, vm, asyncJob) < 0)
9448 9449
        goto endjob;

9450
    if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname,
9451 9452
                                   cookieout, cookieoutlen,
                                   flags)))
9453 9454 9455 9456 9457 9458 9459
        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.
         */
9460 9461
        if (virQEMUCloseCallbacksSet(driver->closeCallbacks, vm, domain->conn,
                                     qemuMigrationCleanup) < 0)
9462
            goto endjob;
9463 9464
        if (qemuMigrationJobContinue(vm) == 0) {
            vm = NULL;
9465 9466
            virReportError(VIR_ERR_OPERATION_FAILED,
                           "%s", _("domain disappeared"));
9467 9468 9469 9470 9471 9472 9473
            VIR_FREE(xml);
            if (cookieout)
                VIR_FREE(*cookieout);
        }
    } else {
        goto endjob;
    }
9474 9475

cleanup:
9476
    if (vm)
9477
        virObjectUnlock(vm);
9478
    return xml;
9479 9480 9481 9482 9483 9484 9485 9486 9487 9488

endjob:
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
        if (qemuMigrationJobFinish(driver, vm) == 0)
            vm = NULL;
    } else {
        if (qemuDomainObjEndJob(driver, vm) == 0)
            vm = NULL;
    }
    goto cleanup;
9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503
}

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)
{
9504
    virQEMUDriverPtr driver = dconn->privateData;
9505 9506
    int ret = -1;

9507
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9508 9509 9510 9511 9512 9513 9514

    *uri_out = NULL;

    if (flags & VIR_MIGRATE_TUNNELLED) {
        /* this is a logical error; we never should have gotten here with
         * VIR_MIGRATE_TUNNELLED set
         */
9515 9516
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Tunnelled migration requested but invalid RPC method called"));
9517 9518 9519 9520
        goto cleanup;
    }

    if (!dom_xml) {
9521 9522
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
9523 9524 9525 9526 9527 9528 9529
        goto cleanup;
    }

    ret = qemuMigrationPrepareDirect(driver, dconn,
                                     cookiein, cookieinlen,
                                     cookieout, cookieoutlen,
                                     uri_in, uri_out,
L
liguang 已提交
9530
                                     dname, dom_xml, flags);
9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548

cleanup:
    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)
{
9549
    virQEMUDriverPtr driver = dconn->privateData;
9550 9551
    int ret = -1;

9552
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9553 9554

    if (!dom_xml) {
9555 9556
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain XML passed"));
9557 9558 9559
        goto cleanup;
    }
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
9560 9561
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
9562 9563 9564
        goto cleanup;
    }
    if (st == NULL) {
9565 9566
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("tunnelled migration requested but NULL stream passed"));
9567 9568 9569 9570 9571 9572
        goto cleanup;
    }

    ret = qemuMigrationPrepareTunnel(driver, dconn,
                                     cookiein, cookieinlen,
                                     cookieout, cookieoutlen,
L
liguang 已提交
9573
                                     st, dname, dom_xml, flags);
9574 9575 9576 9577 9578 9579 9580 9581

cleanup:
    return ret;
}


static int
qemuDomainMigratePerform3(virDomainPtr dom,
9582
                          const char *xmlin,
9583 9584 9585 9586
                          const char *cookiein,
                          int cookieinlen,
                          char **cookieout,
                          int *cookieoutlen,
9587
                          const char *dconnuri,
9588 9589 9590 9591 9592
                          const char *uri,
                          unsigned long flags,
                          const char *dname,
                          unsigned long resource)
{
9593
    virQEMUDriverPtr driver = dom->conn->privateData;
9594 9595
    virDomainObjPtr vm;

9596
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9597

9598 9599
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
9600

9601 9602 9603 9604
    return qemuMigrationPerform(driver, dom->conn, vm, xmlin,
                                dconnuri, uri, cookiein, cookieinlen,
                                cookieout, cookieoutlen,
                                flags, dname, resource, true);
9605 9606 9607
}


9608
static virDomainPtr
9609 9610 9611 9612 9613 9614
qemuDomainMigrateFinish3(virConnectPtr dconn,
                         const char *dname,
                         const char *cookiein,
                         int cookieinlen,
                         char **cookieout,
                         int *cookieoutlen,
9615
                         const char *dconnuri ATTRIBUTE_UNUSED,
9616 9617
                         const char *uri ATTRIBUTE_UNUSED,
                         unsigned long flags,
9618
                         int cancelled)
9619
{
9620
    virQEMUDriverPtr driver = dconn->privateData;
9621
    virDomainObjPtr vm;
9622
    virDomainPtr dom = NULL;
9623

9624
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
9625

9626
    vm = virDomainObjListFindByName(driver->domains, dname);
9627
    if (!vm) {
9628 9629
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching name '%s'"), dname);
9630 9631 9632
        goto cleanup;
    }

9633 9634 9635 9636
    dom = qemuMigrationFinish(driver, dconn, vm,
                              cookiein, cookieinlen,
                              cookieout, cookieoutlen,
                              flags, cancelled, true);
9637 9638

cleanup:
9639
    return dom;
9640 9641 9642 9643 9644 9645 9646 9647 9648
}

static int
qemuDomainMigrateConfirm3(virDomainPtr domain,
                          const char *cookiein,
                          int cookieinlen,
                          unsigned long flags,
                          int cancelled)
{
9649
    virQEMUDriverPtr driver = domain->conn->privateData;
9650 9651
    virDomainObjPtr vm;
    int ret = -1;
9652
    enum qemuMigrationJobPhase phase;
9653
    virQEMUDriverConfigPtr cfg = NULL;
9654

9655
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
9656

9657 9658
    if (!(vm = qemuDomObjFromDomain(domain)))
        return -1;
9659

9660 9661
    cfg = virQEMUDriverGetConfig(driver);

9662
    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT))
9663 9664
        goto cleanup;

9665 9666 9667 9668 9669 9670
    if (cancelled)
        phase = QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED;
    else
        phase = QEMU_MIGRATION_PHASE_CONFIRM3;

    qemuMigrationJobStartPhase(driver, vm, phase);
9671 9672
    virQEMUCloseCallbacksUnset(driver->closeCallbacks, vm,
                               qemuMigrationCleanup);
9673

9674 9675
    ret = qemuMigrationConfirm(driver, domain->conn, vm,
                               cookiein, cookieinlen,
9676 9677
                               flags, cancelled);

9678
    if (qemuMigrationJobFinish(driver, vm) == 0) {
9679 9680 9681 9682
        vm = NULL;
    } else if (!virDomainObjIsActive(vm) &&
               (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) {
        if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
9683
            virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
9684
        qemuDomainRemoveInactive(driver, vm);
9685 9686 9687
        vm = NULL;
    }

9688
cleanup:
9689
    if (vm)
9690
        virObjectUnlock(vm);
9691
    virObjectUnref(cfg);
9692 9693 9694 9695
    return ret;
}


9696
static int
9697 9698 9699 9700 9701
qemuNodeDeviceGetPciInfo(virNodeDevicePtr dev,
                         unsigned *domain,
                         unsigned *bus,
                         unsigned *slot,
                         unsigned *function)
9702 9703 9704 9705 9706 9707 9708 9709 9710 9711
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

    xml = virNodeDeviceGetXMLDesc(dev, 0);
    if (!xml)
        goto out;

9712
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729
    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) {
9730 9731
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742
        goto out;
    }

    ret = 0;
out:
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
9743
qemuNodeDeviceDettach(virNodeDevicePtr dev)
9744
{
9745
    virQEMUDriverPtr driver = dev->conn->privateData;
9746
    virPCIDevicePtr pci;
9747 9748
    unsigned domain, bus, slot, function;
    int ret = -1;
9749
    bool in_inactive_list = false;
9750

9751
    if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
9752 9753
        return -1;

9754
    pci = virPCIDeviceNew(domain, bus, slot, function);
9755 9756 9757
    if (!pci)
        return -1;

9758 9759
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);
9760
    in_inactive_list = virPCIDeviceListFind(driver->inactivePciHostdevs, pci);
9761

9762 9763
    if (virPCIDeviceDetach(pci, driver->activePciHostdevs,
                           driver->inactivePciHostdevs, "pci-stub") < 0)
9764 9765 9766 9767
        goto out;

    ret = 0;
out:
9768 9769
    virObjectUnlock(driver->inactivePciHostdevs);
    virObjectUnlock(driver->activePciHostdevs);
9770
    if (in_inactive_list)
9771
        virPCIDeviceFree(pci);
9772 9773 9774 9775
    return ret;
}

static int
9776
qemuNodeDeviceReAttach(virNodeDevicePtr dev)
9777
{
9778
    virQEMUDriverPtr driver = dev->conn->privateData;
9779 9780
    virPCIDevicePtr pci;
    virPCIDevicePtr other;
9781 9782 9783
    unsigned domain, bus, slot, function;
    int ret = -1;

9784
    if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
9785 9786
        return -1;

9787
    pci = virPCIDeviceNew(domain, bus, slot, function);
9788 9789 9790
    if (!pci)
        return -1;

9791 9792
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);
9793
    other = virPCIDeviceListFind(driver->activePciHostdevs, pci);
9794
    if (other) {
9795
        const char *other_name = virPCIDeviceGetUsedBy(other);
9796 9797

        if (other_name)
9798 9799
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("PCI device %s is still in use by domain %s"),
9800
                           virPCIDeviceGetName(pci), other_name);
9801
        else
9802 9803
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("PCI device %s is still in use"),
9804
                           virPCIDeviceGetName(pci));
9805
        goto out;
9806 9807
    }

9808
    virPCIDeviceReattachInit(pci);
9809

9810 9811
    if (virPCIDeviceReattach(pci, driver->activePciHostdevs,
                             driver->inactivePciHostdevs, "pci-stub") < 0)
9812 9813 9814 9815
        goto out;

    ret = 0;
out:
9816 9817
    virObjectUnlock(driver->inactivePciHostdevs);
    virObjectUnlock(driver->activePciHostdevs);
9818
    virPCIDeviceFree(pci);
9819 9820 9821 9822
    return ret;
}

static int
9823
qemuNodeDeviceReset(virNodeDevicePtr dev)
9824
{
9825
    virQEMUDriverPtr driver = dev->conn->privateData;
9826
    virPCIDevicePtr pci;
9827 9828 9829
    unsigned domain, bus, slot, function;
    int ret = -1;

9830
    if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
9831 9832
        return -1;

9833
    pci = virPCIDeviceNew(domain, bus, slot, function);
9834 9835 9836
    if (!pci)
        return -1;

9837 9838
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);
9839

9840 9841
    if (virPCIDeviceReset(pci, driver->activePciHostdevs,
                          driver->inactivePciHostdevs) < 0)
9842 9843 9844 9845
        goto out;

    ret = 0;
out:
9846 9847
    virObjectUnlock(driver->inactivePciHostdevs);
    virObjectUnlock(driver->activePciHostdevs);
9848
    virPCIDeviceFree(pci);
9849 9850 9851
    return ret;
}

9852 9853 9854
static int
qemuCPUCompare(virConnectPtr conn,
               const char *xmlDesc,
E
Eric Blake 已提交
9855
               unsigned int flags)
9856
{
9857
    virQEMUDriverPtr driver = conn->privateData;
9858
    int ret = VIR_CPU_COMPARE_ERROR;
9859
    virCapsPtr caps = NULL;
9860

E
Eric Blake 已提交
9861 9862
    virCheckFlags(0, VIR_CPU_COMPARE_ERROR);

9863 9864 9865 9866 9867
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

    if (!caps->host.cpu ||
        !caps->host.cpu->model) {
9868 9869
        VIR_WARN("cannot get host CPU capabilities");
        ret = VIR_CPU_COMPARE_INCOMPATIBLE;
E
Eric Blake 已提交
9870
    } else {
9871
        ret = cpuCompareXML(caps->host.cpu, xmlDesc);
E
Eric Blake 已提交
9872
    }
9873

9874 9875
cleanup:
    virObjectUnref(caps);
9876 9877 9878
    return ret;
}

9879

9880 9881 9882 9883
static char *
qemuCPUBaseline(virConnectPtr conn ATTRIBUTE_UNUSED,
                const char **xmlCPUs,
                unsigned int ncpus,
E
Eric Blake 已提交
9884
                unsigned int flags)
9885 9886 9887
{
    char *cpu;

E
Eric Blake 已提交
9888 9889
    virCheckFlags(0, NULL);

9890 9891 9892 9893 9894
    cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0);

    return cpu;
}

9895 9896 9897 9898 9899 9900 9901

static int qemuDomainGetJobInfo(virDomainPtr dom,
                                virDomainJobInfoPtr info) {
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

9902
    if (!(vm = qemuDomObjFromDomain(dom)))
9903 9904 9905 9906 9907
        goto cleanup;

    priv = vm->privateData;

    if (virDomainObjIsActive(vm)) {
9908
        if (priv->job.asyncJob && !priv->job.dump_memory_only) {
9909
            memcpy(info, &priv->job.info, sizeof(*info));
9910 9911 9912 9913 9914 9915

            /* 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
             */
9916
            if (virTimeMillisNow(&info->timeElapsed) < 0)
9917
                goto cleanup;
9918
            info->timeElapsed -= priv->job.start;
9919 9920 9921 9922 9923
        } else {
            memset(info, 0, sizeof(*info));
            info->type = VIR_DOMAIN_JOB_NONE;
        }
    } else {
9924 9925
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
9926 9927 9928 9929 9930 9931 9932
        goto cleanup;
    }

    ret = 0;

cleanup:
    if (vm)
9933
        virObjectUnlock(vm);
9934 9935 9936 9937
    return ret;
}


9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 10075 10076 10077
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;
}


10078
static int qemuDomainAbortJob(virDomainPtr dom) {
10079
    virQEMUDriverPtr driver = dom->conn->privateData;
10080 10081 10082 10083
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

10084
    if (!(vm = qemuDomObjFromDomain(dom)))
10085 10086
        goto cleanup;

10087 10088
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_ABORT) < 0)
        goto cleanup;
10089

10090
    if (!virDomainObjIsActive(vm)) {
10091 10092
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
10093
        goto endjob;
10094 10095
    }

10096 10097
    priv = vm->privateData;

10098
    if (!priv->job.asyncJob || priv->job.dump_memory_only) {
10099 10100
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("no job is active on the domain"));
10101 10102
        goto endjob;
    } else if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
10103 10104 10105
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot abort incoming migration;"
                         " use virDomainDestroy instead"));
10106 10107 10108 10109
        goto endjob;
    }

    VIR_DEBUG("Cancelling job at client request");
10110
    qemuDomainObjAbortAsyncJob(vm);
10111
    qemuDomainObjEnterMonitor(driver, vm);
10112 10113 10114 10115 10116 10117
    ret = qemuMonitorMigrateCancel(priv->mon);
    qemuDomainObjExitMonitor(driver, vm);

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

cleanup:
    if (vm)
10121
        virObjectUnlock(vm);
10122 10123 10124 10125
    return ret;
}


10126 10127 10128 10129 10130
static int
qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
                                unsigned long long downtime,
                                unsigned int flags)
{
10131
    virQEMUDriverPtr driver = dom->conn->privateData;
10132 10133 10134 10135
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

10136
    virCheckFlags(0, -1);
10137

10138 10139
    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;
10140

10141 10142 10143
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
        goto cleanup;

10144
    if (!virDomainObjIsActive(vm)) {
10145 10146
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
10147
        goto endjob;
10148 10149 10150 10151
    }

    priv = vm->privateData;

10152
    if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) {
10153 10154
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not being migrated"));
10155
        goto endjob;
10156 10157
    }

10158
    VIR_DEBUG("Setting migration downtime to %llums", downtime);
10159
    qemuDomainObjEnterMonitor(driver, vm);
10160 10161 10162 10163 10164 10165
    ret = qemuMonitorSetMigrationDowntime(priv->mon, downtime);
    qemuDomainObjExitMonitor(driver, vm);

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

cleanup:
    if (vm)
10169
        virObjectUnlock(vm);
10170 10171 10172
    return ret;
}

10173 10174 10175 10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245 10246 10247 10248 10249 10250 10251 10252 10253 10254 10255 10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 10270 10271 10272 10273 10274 10275 10276 10277
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;
}

10278 10279 10280 10281 10282
static int
qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
                             unsigned long bandwidth,
                             unsigned int flags)
{
10283
    virQEMUDriverPtr driver = dom->conn->privateData;
10284 10285 10286 10287 10288 10289
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(0, -1);

10290 10291
    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;
10292 10293

    priv = vm->privateData;
10294 10295 10296
    if (virDomainObjIsActive(vm)) {
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
            goto cleanup;
10297

10298
        if (!virDomainObjIsActive(vm)) {
10299 10300
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is not running"));
10301 10302 10303
            goto endjob;
        }

10304 10305 10306 10307
        VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
        qemuDomainObjEnterMonitor(driver, vm);
        ret = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
        qemuDomainObjExitMonitor(driver, vm);
10308

10309 10310
        if (ret == 0)
            priv->migMaxBandwidth = bandwidth;
10311

10312
endjob:
10313 10314 10315 10316 10317 10318
        if (qemuDomainObjEndJob(driver, vm) == 0)
            vm = NULL;
    } else {
        priv->migMaxBandwidth = bandwidth;
        ret = 0;
    }
10319 10320 10321

cleanup:
    if (vm)
10322
        virObjectUnlock(vm);
10323 10324 10325
    return ret;
}

10326 10327 10328 10329 10330 10331
static int
qemuDomainMigrateGetMaxSpeed(virDomainPtr dom,
                             unsigned long *bandwidth,
                             unsigned int flags)
{
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
10332
    qemuDomainObjPrivatePtr priv;
10333 10334 10335 10336
    int ret = -1;

    virCheckFlags(0, -1);

10337
    if (!(vm = qemuDomObjFromDomain(dom)))
10338 10339
        goto cleanup;

J
Jim Fehlig 已提交
10340 10341
    priv = vm->privateData;
    *bandwidth = priv->migMaxBandwidth;
10342 10343 10344 10345
    ret = 0;

cleanup:
    if (vm)
10346
        virObjectUnlock(vm);
10347 10348 10349
    return ret;
}

10350 10351 10352 10353 10354 10355 10356 10357 10358 10359 10360 10361
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
10362
qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
10363 10364
                                  virDomainObjPtr vm,
                                  virDomainDiskDefPtr disk,
10365
                                  const char *file,
10366 10367 10368 10369 10370 10371 10372 10373 10374 10375
                                  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;
10376
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
10377

10378
    disk->src = (char *) file; /* casting away const is safe here */
10379 10380 10381 10382 10383 10384 10385 10386
    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);
10387
        if (qemuTeardownDiskCgroup(vm, disk) < 0)
10388 10389 10390
            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);
10391
    } else if (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
10392
                                       vm, disk) < 0 ||
10393
               qemuSetupDiskCgroup(vm, disk) < 0 ||
10394 10395 10396 10397 10398 10399 10400 10401 10402 10403 10404 10405
               virSecurityManagerSetImageLabel(driver->securityManager,
                                               vm->def, disk) < 0) {
        goto cleanup;
    }

    ret = 0;

cleanup:
    disk->src = origsrc;
    disk->format = origformat;
    disk->backingChain = origchain;
    disk->readonly = origreadonly;
10406
    virObjectUnref(cfg);
10407 10408 10409 10410
    return ret;
}


10411
static int
10412
qemuDomainSnapshotFSFreeze(virDomainObjPtr vm) {
10413 10414 10415 10416
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int freezed;

    if (priv->agentError) {
10417
        virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
10418 10419
                       _("QEMU guest agent is not "
                         "available due to an error"));
10420 10421 10422
        return -1;
    }
    if (!priv->agent) {
10423 10424
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("QEMU guest agent is not configured"));
10425 10426 10427
        return -1;
    }

10428
    qemuDomainObjEnterAgent(vm);
10429
    freezed = qemuAgentFSFreeze(priv->agent);
10430
    qemuDomainObjExitAgent(vm);
10431 10432 10433 10434 10435

    return freezed;
}

static int
10436
qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report)
E
Eric Blake 已提交
10437
{
10438 10439
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int thawed;
E
Eric Blake 已提交
10440
    virErrorPtr err = NULL;
10441 10442

    if (priv->agentError) {
E
Eric Blake 已提交
10443
        if (report)
10444
            virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
10445 10446
                           _("QEMU guest agent is not "
                             "available due to an error"));
10447 10448 10449
        return -1;
    }
    if (!priv->agent) {
E
Eric Blake 已提交
10450
        if (report)
10451 10452
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                           _("QEMU guest agent is not configured"));
10453 10454 10455
        return -1;
    }

10456
    qemuDomainObjEnterAgent(vm);
E
Eric Blake 已提交
10457
    if (!report)
10458
        err = virSaveLastError();
10459
    thawed = qemuAgentFSThaw(priv->agent);
10460 10461
    if (!report)
        virSetError(err);
10462
    qemuDomainObjExitAgent(vm);
10463

10464
    virFreeError(err);
10465 10466 10467
    return thawed;
}

10468 10469
/* The domain is expected to be locked and inactive. */
static int
10470
qemuDomainSnapshotCreateInactiveInternal(virQEMUDriverPtr driver,
10471 10472
                                         virDomainObjPtr vm,
                                         virDomainSnapshotObjPtr snap)
10473
{
E
Eric Blake 已提交
10474
    return qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-c", false);
10475 10476
}

10477 10478
/* The domain is expected to be locked and inactive. */
static int
10479
qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
10480 10481 10482 10483 10484 10485 10486 10487 10488
                                         virDomainObjPtr vm,
                                         virDomainSnapshotObjPtr snap,
                                         bool reuse)
{
    int i;
    virDomainSnapshotDiskDefPtr snapdisk;
    virDomainDiskDefPtr defdisk;
    virCommandPtr cmd = NULL;
    const char *qemuImgPath;
10489 10490
    virBitmapPtr created = NULL;
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
10491 10492 10493
    int ret = -1;

    if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
10494
        goto cleanup;
10495 10496 10497

    if (!(created = virBitmapNew(snap->def->ndisks))) {
        virReportOOMError();
10498
        goto cleanup;
10499 10500 10501 10502 10503 10504 10505 10506 10507 10508 10509 10510 10511 10512 10513 10514 10515 10516 10517 10518 10519 10520 10521 10522 10523 10524 10525 10526 10527
    }

    /* 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 {
10528
            if (!cfg->allowDiskFormatProbing) {
10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 10539 10540 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 10560 10561 10562 10563 10564 10565 10566 10567 10568 10569 10570 10571 10572 10573 10574 10575
                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 */
10576
    if (ret < 0 && created) {
10577 10578 10579 10580 10581 10582 10583 10584 10585
        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);
10586
    virObjectUnref(cfg);
10587 10588 10589 10590

    return ret;
}

10591

10592 10593
/* The domain is expected to be locked and active. */
static int
10594
qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
10595
                                       virQEMUDriverPtr driver,
10596 10597 10598
                                       virDomainObjPtr *vmptr,
                                       virDomainSnapshotObjPtr snap,
                                       unsigned int flags)
10599 10600 10601
{
    virDomainObjPtr vm = *vmptr;
    qemuDomainObjPrivatePtr priv = vm->privateData;
10602
    virDomainEventPtr event = NULL;
10603 10604
    bool resume = false;
    int ret = -1;
10605

10606
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10607 10608
        return -1;

10609
    if (!virDomainObjIsActive(vm)) {
10610 10611
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
10612 10613 10614
        goto endjob;
    }

J
Jiri Denemark 已提交
10615
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
10616 10617 10618 10619
        /* 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.
         */
10620 10621
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
                                QEMU_ASYNC_JOB_NONE) < 0)
10622 10623 10624 10625
            goto cleanup;

        resume = true;
        if (!virDomainObjIsActive(vm)) {
10626 10627
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("guest unexpectedly quit"));
10628 10629 10630 10631
            goto cleanup;
        }
    }

10632
    qemuDomainObjEnterMonitor(driver, vm);
10633
    ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
10634
    qemuDomainObjExitMonitor(driver, vm);
10635 10636 10637 10638 10639 10640
    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);
10641
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
10642 10643 10644 10645 10646 10647 10648
        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;
    }
10649

10650 10651
cleanup:
    if (resume && virDomainObjIsActive(vm) &&
J
Jiri Denemark 已提交
10652
        qemuProcessStartCPUs(driver, vm, conn,
10653
                             VIR_DOMAIN_RUNNING_UNPAUSED,
10654 10655 10656 10657 10658 10659 10660 10661
                             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"));
        }
10662 10663
    }

10664
endjob:
10665
    if (vm && qemuDomainObjEndJob(driver, vm) == 0) {
10666 10667
        /* Only possible if a transient vm quit while our locks were down,
         * in which case we don't want to save snapshot metadata.  */
10668
        *vmptr = NULL;
10669 10670
        ret = -1;
    }
10671

10672 10673 10674
    if (event)
        qemuDomainEventQueue(driver, event);

10675 10676 10677
    return ret;
}

10678
static int
E
Eric Blake 已提交
10679 10680
qemuDomainSnapshotPrepare(virDomainObjPtr vm, virDomainSnapshotDefPtr def,
                          unsigned int *flags)
10681 10682 10683 10684 10685
{
    int ret = -1;
    int i;
    bool active = virDomainObjIsActive(vm);
    struct stat st;
10686
    bool reuse = (*flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
10687
    bool atomic = (*flags & VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC) != 0;
10688
    bool found_internal = false;
10689 10690
    int external = 0;
    qemuDomainObjPrivatePtr priv = vm->privateData;
10691

E
Eric Blake 已提交
10692
    if (def->state == VIR_DOMAIN_DISK_SNAPSHOT &&
10693
        reuse && !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
10694 10695
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("reuse is not supported with this QEMU binary"));
10696 10697 10698
        goto cleanup;
    }

10699 10700
    for (i = 0; i < def->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk = &def->disks[i];
E
Eric Blake 已提交
10701
        virDomainDiskDefPtr dom_disk = vm->def->disks[i];
10702 10703

        switch (disk->snapshot) {
E
Eric Blake 已提交
10704
        case VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL:
E
Eric Blake 已提交
10705 10706 10707 10708 10709
            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;
10710
            }
10711 10712
            if (vm->def->disks[i]->format > 0 &&
                vm->def->disks[i]->format != VIR_STORAGE_FILE_QCOW2) {
10713 10714 10715 10716
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("internal snapshot for disk %s unsupported "
                                 "for storage type %s"),
                               disk->name,
10717 10718
                               virStorageFileFormatTypeToString(
                                   vm->def->disks[i]->format));
10719 10720
                goto cleanup;
            }
E
Eric Blake 已提交
10721 10722 10723 10724 10725 10726 10727
            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;
            }
10728
            found_internal = true;
10729 10730
            break;

E
Eric Blake 已提交
10731
        case VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL:
10732 10733 10734 10735
            if (!disk->format) {
                disk->format = VIR_STORAGE_FILE_QCOW2;
            } else if (disk->format != VIR_STORAGE_FILE_QCOW2 &&
                       disk->format != VIR_STORAGE_FILE_QED) {
10736 10737 10738
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("external snapshot format for disk %s "
                                 "is unsupported: %s"),
10739 10740
                               disk->name,
                               virStorageFileFormatTypeToString(disk->format));
10741 10742 10743 10744 10745 10746 10747 10748
                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;
10749 10750 10751 10752 10753
                } else if (reuse) {
                    virReportSystemError(errno,
                                         _("missing existing file for disk %s: %s"),
                                         disk->name, disk->file);
                    goto cleanup;
10754
                }
10755
            } else if (!S_ISBLK(st.st_mode) && st.st_size && !reuse) {
10756 10757 10758 10759
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("external snapshot file for disk %s already "
                                 "exists and is not a block device: %s"),
                               disk->name, disk->file);
10760 10761
                goto cleanup;
            }
10762
            external++;
10763 10764
            break;

E
Eric Blake 已提交
10765
        case VIR_DOMAIN_SNAPSHOT_LOCATION_NONE:
10766 10767
            break;

E
Eric Blake 已提交
10768
        case VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT:
10769
        default:
10770 10771
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unexpected code path"));
10772 10773 10774 10775
            goto cleanup;
        }
    }

10776 10777 10778
    /* internal snapshot requires a disk image to store the memory image to */
    if (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL &&
        !found_internal) {
10779
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10780
                       _("internal checkpoints require at least "
10781
                         "one disk to be selected for snapshot"));
10782 10783
        goto cleanup;
    }
10784

10785 10786 10787 10788 10789 10790 10791 10792 10793 10794 10795 10796 10797 10798 10799 10800 10801 10802 10803 10804 10805 10806
    /* 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 已提交
10807
    if (def->state != VIR_DOMAIN_DISK_SNAPSHOT && active) {
10808
        if (external == 1 ||
10809
            virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
10810 10811
            *flags |= VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC;
        } else if (atomic && external > 1) {
10812 10813 10814
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("atomic live snapshot of multiple disks "
                             "is unsupported"));
10815 10816 10817
            goto cleanup;
        }
    }
10818 10819 10820 10821 10822 10823 10824 10825 10826

    ret = 0;

cleanup:
    return ret;
}

/* The domain is expected to hold monitor lock.  */
static int
10827
qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
10828
                                         virDomainObjPtr vm,
10829
                                         virDomainSnapshotDiskDefPtr snap,
10830
                                         virDomainDiskDefPtr disk,
10831
                                         virDomainDiskDefPtr persistDisk,
10832 10833
                                         virJSONValuePtr actions,
                                         bool reuse)
10834 10835 10836 10837
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    char *device = NULL;
    char *source = NULL;
10838 10839
    int format = snap->format;
    const char *formatStr = NULL;
10840
    char *persistSource = NULL;
10841
    int ret = -1;
10842 10843
    int fd = -1;
    bool need_unlink = false;
10844

E
Eric Blake 已提交
10845
    if (snap->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
10846 10847
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected code path"));
10848 10849 10850 10851 10852
        return -1;
    }

    if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
        !(source = strdup(snap->file)) ||
10853
        (persistDisk &&
10854
         !(persistSource = strdup(source)))) {
10855 10856 10857 10858
        virReportOOMError();
        goto cleanup;
    }

10859 10860
    /* create the stub file and set selinux labels; manipulate disk in
     * place, in a way that can be reverted on failure. */
10861 10862 10863 10864 10865 10866 10867
    if (!reuse) {
        fd = qemuOpenFile(driver, source, O_WRONLY | O_TRUNC | O_CREAT,
                          &need_unlink, NULL);
        if (fd < 0)
            goto cleanup;
        VIR_FORCE_CLOSE(fd);
    }
10868

10869 10870 10871 10872 10873 10874 10875 10876
    /* 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;
10877

10878
    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
10879
                                          VIR_DISK_CHAIN_READ_WRITE) < 0) {
10880
        qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
10881
                                          VIR_DISK_CHAIN_NO_ACCESS);
10882 10883 10884 10885
        goto cleanup;
    }

    /* create the actual snapshot */
10886 10887
    if (snap->format)
        formatStr = virStorageFileFormatTypeToString(snap->format);
10888
    ret = qemuMonitorDiskSnapshot(priv->mon, actions, device, source,
10889
                                  formatStr, reuse);
10890 10891 10892 10893 10894
    virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0);
    if (ret < 0)
        goto cleanup;

    /* Update vm in place to match changes.  */
10895
    need_unlink = false;
10896 10897 10898
    VIR_FREE(disk->src);
    disk->src = source;
    source = NULL;
10899
    disk->format = format;
10900 10901 10902 10903
    if (persistDisk) {
        VIR_FREE(persistDisk->src);
        persistDisk->src = persistSource;
        persistSource = NULL;
10904
        persistDisk->format = format;
10905
    }
10906 10907

cleanup:
10908 10909
    if (need_unlink && unlink(source))
        VIR_WARN("unable to unlink just-created %s", source);
10910 10911
    VIR_FREE(device);
    VIR_FREE(source);
10912
    VIR_FREE(persistSource);
10913 10914 10915
    return ret;
}

10916 10917 10918 10919
/* The domain is expected to hold monitor lock.  This is the
 * counterpart to qemuDomainSnapshotCreateSingleDiskActive, called
 * only on a failed transaction. */
static void
10920
qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
10921 10922 10923 10924 10925 10926 10927 10928 10929 10930 10931 10932
                                       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 &&
10933
         !(persistSource = strdup(source)))) {
10934 10935 10936 10937
        virReportOOMError();
        goto cleanup;
    }

10938
    qemuDomainPrepareDiskChainElement(driver, vm, disk, origdisk->src,
10939
                                      VIR_DISK_CHAIN_NO_ACCESS);
10940
    if (need_unlink && stat(disk->src, &st) == 0 &&
10941
        S_ISREG(st.st_mode) && unlink(disk->src) < 0)
10942 10943 10944 10945 10946 10947
        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;
10948
    disk->format = origdisk->format;
10949 10950 10951 10952
    if (persistDisk) {
        VIR_FREE(persistDisk->src);
        persistDisk->src = persistSource;
        persistSource = NULL;
10953
        persistDisk->format = origdisk->format;
10954 10955 10956 10957 10958 10959 10960
    }

cleanup:
    VIR_FREE(source);
    VIR_FREE(persistSource);
}

10961 10962
/* The domain is expected to be locked and active. */
static int
10963
qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
10964
                                   virDomainObjPtr vm,
10965
                                   virDomainSnapshotObjPtr snap,
10966 10967
                                   unsigned int flags,
                                   enum qemuDomainAsyncJob asyncJob)
10968
{
10969 10970
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virJSONValuePtr actions = NULL;
10971 10972
    int ret = -1;
    int i;
10973
    bool persist = false;
10974
    bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
10975
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
10976

10977
    if (!virDomainObjIsActive(vm)) {
10978 10979
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
10980
        goto cleanup;
10981 10982
    }

10983
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
10984
        if (!(actions = virJSONValueNewArray())) {
10985 10986 10987
            virReportOOMError();
            goto cleanup;
        }
10988
    } else if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DISK_SNAPSHOT)) {
10989 10990 10991 10992
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
                       _("live disk snapshot not supported with this "
                         "QEMU binary"));
        goto cleanup;
10993
    }
10994 10995

    /* No way to roll back if first disk succeeds but later disks
10996
     * fail, unless we have transaction support.
E
Eric Blake 已提交
10997
     * Based on earlier qemuDomainSnapshotPrepare, all
10998 10999
     * disks in this list are now either SNAPSHOT_NO, or
     * SNAPSHOT_EXTERNAL with a valid file name and qcow2 format.  */
11000 11001 11002
    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
        goto cleanup;

11003
    for (i = 0; i < snap->def->ndisks; i++) {
11004 11005
        virDomainDiskDefPtr persistDisk = NULL;

E
Eric Blake 已提交
11006
        if (snap->def->disks[i].snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
11007
            continue;
11008 11009 11010 11011 11012 11013 11014 11015 11016
        if (vm->newDef) {
            int indx = virDomainDiskIndexByName(vm->newDef,
                                                vm->def->disks[i]->dst,
                                                false);
            if (indx >= 0) {
                persistDisk = vm->newDef->disks[indx];
                persist = true;
            }
        }
11017

11018
        ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
11019
                                                       &snap->def->disks[i],
11020
                                                       vm->def->disks[i],
11021 11022
                                                       persistDisk, actions,
                                                       reuse);
11023 11024 11025
        if (ret < 0)
            break;
    }
11026 11027 11028
    if (actions) {
        if (ret == 0)
            ret = qemuMonitorTransaction(priv->mon, actions);
E
Eric Blake 已提交
11029
        virJSONValueFree(actions);
11030 11031 11032 11033 11034 11035
        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 已提交
11036 11037
                if (snap->def->disks[i].snapshot ==
                    VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
11038 11039 11040 11041 11042 11043 11044 11045 11046
                    continue;
                if (vm->newDef) {
                    int indx = virDomainDiskIndexByName(vm->newDef,
                                                        vm->def->disks[i]->dst,
                                                        false);
                    if (indx >= 0)
                        persistDisk = vm->newDef->disks[indx];
                }

11047
                qemuDomainSnapshotUndoSingleDiskActive(driver, vm,
11048 11049 11050 11051 11052 11053 11054
                                                       snap->def->dom->disks[i],
                                                       vm->def->disks[i],
                                                       persistDisk,
                                                       need_unlink);
            }
        }
    }
11055
    qemuDomainObjExitMonitor(driver, vm);
11056 11057 11058

cleanup:

11059
    if (ret == 0 || !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
11060
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0 ||
11061
            (persist && virDomainSaveConfig(cfg->configDir, vm->newDef) < 0))
11062 11063
            ret = -1;
    }
11064
    virObjectUnref(cfg);
11065 11066 11067 11068 11069 11070 11071

    return ret;
}


static int
qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
11072
                                       virQEMUDriverPtr driver,
11073 11074 11075 11076 11077 11078 11079 11080 11081 11082
                                       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;
11083
    bool memory_unlink = false;
11084
    bool atomic = !!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC);
11085
    bool transaction = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION);
11086
    int thaw = 0; /* 1 if freeze succeeded, -1 if freeze failed */
11087
    bool pmsuspended = false;
11088

11089
    if (qemuDomainObjBeginAsyncJob(driver, vm,
11090
                                             QEMU_ASYNC_JOB_SNAPSHOT) < 0)
11091 11092
        goto cleanup;

11093 11094 11095 11096 11097
    /* 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) {
11098
        if (qemuDomainSnapshotFSFreeze(vm) < 0) {
11099 11100 11101 11102 11103 11104 11105 11106
            /* helper reported the error */
            thaw = -1;
            goto endjob;
        } else {
            thaw = 1;
        }
    }

11107 11108 11109 11110 11111
    /* 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) {
11112 11113 11114 11115 11116 11117 11118 11119 11120 11121 11122 11123 11124 11125 11126 11127 11128 11129 11130 11131 11132 11133 11134 11135 11136 11137 11138 11139 11140
        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) {
11141 11142 11143 11144
        /* check if migration is possible */
        if (!qemuMigrationIsAllowed(driver, vm, vm->def, false))
            goto endjob;

11145 11146 11147 11148 11149 11150 11151 11152 11153
        /* 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,
11154
                                        xml, QEMU_SAVE_FORMAT_RAW,
11155 11156 11157 11158
                                        resume, 0,
                                        QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
            goto endjob;

11159 11160 11161
        /* the memory image was created, remove it on errors */
        memory_unlink = true;

11162 11163 11164 11165 11166 11167 11168 11169 11170 11171 11172 11173 11174 11175 11176 11177
        /* 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 */
11178 11179 11180 11181 11182
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
        virDomainEventPtr event;

        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
11183
        qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
11184 11185 11186
        virDomainAuditStop(vm, "from-snapshot");
        /* We already filtered the _HALT flag for persistent domains
         * only, so this end job never drops the last reference.  */
11187
        ignore_value(qemuDomainObjEndAsyncJob(driver, vm));
11188
        resume = false;
E
Eric Blake 已提交
11189
        thaw = 0;
11190 11191 11192
        vm = NULL;
        if (event)
            qemuDomainEventQueue(driver, event);
11193 11194 11195 11196 11197 11198 11199 11200 11201 11202 11203 11204
    } 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);
11205 11206
    }

11207
    ret = 0;
11208 11209

endjob:
11210 11211 11212
    if (resume && vm && virDomainObjIsActive(vm) &&
        qemuProcessStartCPUs(driver, vm, conn,
                             VIR_DOMAIN_RUNNING_UNPAUSED,
11213
                             QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
11214 11215 11216 11217 11218 11219 11220 11221 11222 11223
        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"));
        }
11224

11225 11226
        ret = -1;
        goto cleanup;
11227
    }
E
Eric Blake 已提交
11228
    if (vm && thaw != 0 &&
11229
        qemuDomainSnapshotFSThaw(vm, thaw > 0) < 0) {
E
Eric Blake 已提交
11230 11231 11232 11233
        /* helper reported the error, if it was needed */
        if (thaw > 0)
            ret = -1;
    }
11234
    if (vm && !qemuDomainObjEndAsyncJob(driver, vm)) {
11235
        /* Only possible if a transient vm quit while our locks were down,
11236 11237
         * in which case we don't want to save snapshot metadata.
         */
11238 11239
        *vmptr = NULL;
        ret = -1;
11240 11241
    }

11242 11243
cleanup:
    VIR_FREE(xml);
11244 11245
    if (memory_unlink && ret < 0)
        unlink(snap->def->file);
11246

11247 11248 11249
    return ret;
}

11250

11251 11252 11253 11254
static virDomainSnapshotPtr
qemuDomainSnapshotCreateXML(virDomainPtr domain,
                            const char *xmlDesc,
                            unsigned int flags)
C
Chris Lalancette 已提交
11255
{
11256
    virQEMUDriverPtr driver = domain->conn->privateData;
C
Chris Lalancette 已提交
11257
    virDomainObjPtr vm = NULL;
11258
    char *xml = NULL;
C
Chris Lalancette 已提交
11259 11260 11261
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];
11262
    virDomainSnapshotDefPtr def = NULL;
11263
    bool update_current = true;
11264
    unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
11265
    virDomainSnapshotObjPtr other = NULL;
11266 11267
    int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
    int align_match = true;
11268
    virQEMUDriverConfigPtr cfg = NULL;
11269
    virCapsPtr caps = NULL;
C
Chris Lalancette 已提交
11270

11271 11272
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
                  VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
11273
                  VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
11274
                  VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
11275
                  VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY |
11276
                  VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT |
11277
                  VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
11278 11279
                  VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
                  VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);
11280 11281 11282

    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
        !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY)) {
11283 11284
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("quiesce requires disk-only"));
11285 11286
        return NULL;
    }
11287 11288 11289 11290 11291 11292 11293

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

C
Chris Lalancette 已提交
11295
    virUUIDFormat(domain->uuid, uuidstr);
11296 11297

    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
11298 11299
        goto cleanup;

11300 11301
    cfg = virQEMUDriverGetConfig(driver);

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

11305
    if (qemuProcessAutoDestroyActive(driver, vm)) {
11306 11307
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is marked for auto destroy"));
11308 11309
        goto cleanup;
    }
E
Eric Blake 已提交
11310 11311 11312 11313 11314 11315
    if (virDomainHasDiskMirror(vm)) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, "%s",
                       _("domain has active block copy job"));
        goto cleanup;
    }

11316
    if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
11317 11318
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot halt after transient domain snapshot"));
11319 11320
        goto cleanup;
    }
11321 11322 11323
    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) ||
        !virDomainObjIsActive(vm))
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE;
11324

11325
    if (!(def = virDomainSnapshotDefParseString(xmlDesc, caps, driver->xmlopt,
11326 11327
                                                QEMU_EXPECTED_VIRT_TYPES,
                                                parse_flags)))
C
Chris Lalancette 已提交
11328 11329
        goto cleanup;

11330 11331 11332 11333 11334 11335 11336 11337 11338 11339 11340 11341 11342 11343 11344 11345 11346 11347
    /* 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;
        }
11348 11349
    }

11350 11351 11352 11353 11354 11355 11356 11357 11358 11359 11360 11361 11362 11363 11364 11365 11366 11367 11368
    /* 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;
    }

11369 11370 11371 11372
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
        /* Prevent circular chains */
        if (def->parent) {
            if (STREQ(def->name, def->parent)) {
11373 11374 11375
                virReportError(VIR_ERR_INVALID_ARG,
                               _("cannot set snapshot %s as its own parent"),
                               def->name);
11376 11377
                goto cleanup;
            }
11378
            other = virDomainSnapshotFindByName(vm->snapshots, def->parent);
11379
            if (!other) {
11380 11381 11382
                virReportError(VIR_ERR_INVALID_ARG,
                               _("parent %s for snapshot %s not found"),
                               def->parent, def->name);
11383 11384 11385 11386
                goto cleanup;
            }
            while (other->def->parent) {
                if (STREQ(other->def->parent, def->name)) {
11387 11388 11389
                    virReportError(VIR_ERR_INVALID_ARG,
                                   _("parent %s would create cycle to %s"),
                                   other->def->name, def->name);
11390 11391
                    goto cleanup;
                }
11392
                other = virDomainSnapshotFindByName(vm->snapshots,
11393 11394 11395 11396 11397 11398 11399 11400 11401 11402
                                                    other->def->parent);
                if (!other) {
                    VIR_WARN("snapshots are inconsistent for %s",
                             vm->def->name);
                    break;
                }
            }
        }

        /* Check that any replacement is compatible */
11403 11404 11405 11406 11407 11408 11409 11410 11411
        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;

        }
11412

11413 11414
        if (def->dom &&
            memcmp(def->dom->uuid, domain->uuid, VIR_UUID_BUFLEN)) {
11415 11416 11417
            virReportError(VIR_ERR_INVALID_ARG,
                           _("definition for snapshot %s must use uuid %s"),
                           def->name, uuidstr);
11418 11419
            goto cleanup;
        }
11420

11421
        other = virDomainSnapshotFindByName(vm->snapshots, def->name);
11422 11423 11424 11425 11426
        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)) {
11427 11428 11429 11430
                virReportError(VIR_ERR_INVALID_ARG,
                               _("cannot change between online and offline "
                                 "snapshot state in snapshot %s"),
                               def->name);
11431 11432
                goto cleanup;
            }
11433

11434 11435
            if ((other->def->state == VIR_DOMAIN_DISK_SNAPSHOT) !=
                (def->state == VIR_DOMAIN_DISK_SNAPSHOT)) {
11436 11437 11438 11439
                virReportError(VIR_ERR_INVALID_ARG,
                               _("cannot change between disk snapshot and "
                                 "system checkpoint in snapshot %s"),
                               def->name);
11440 11441
                goto cleanup;
            }
11442

11443 11444 11445 11446 11447 11448 11449 11450 11451 11452 11453
            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;
                }
            }
11454

11455 11456
            if (def->dom) {
                if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
11457
                    virDomainSnapshotDefIsExternal(def)) {
11458 11459 11460 11461 11462 11463 11464 11465 11466 11467 11468 11469 11470 11471 11472
                    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;
                }
            }

11473 11474 11475 11476
            if (other == vm->current_snapshot) {
                update_current = true;
                vm->current_snapshot = NULL;
            }
11477

11478 11479
            /* Drop and rebuild the parent relationship, but keep all
             * child relations by reusing snap.  */
11480
            virDomainSnapshotDropParent(other);
11481
            virDomainSnapshotDefFree(other->def);
11482 11483
            other->def = def;
            def = NULL;
11484
            snap = other;
11485 11486 11487 11488 11489 11490 11491 11492 11493 11494
        } 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;
11495
            }
11496
        }
11497 11498 11499
    } else {
        /* Easiest way to clone inactive portion of vm->def is via
         * conversion in and back out of xml.  */
11500
        if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)) ||
11501
            !(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt,
11502 11503 11504 11505
                                                 QEMU_EXPECTED_VIRT_TYPES,
                                                 VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

11506
        if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
11507 11508
            align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
            align_match = false;
11509 11510 11511 11512
            if (virDomainObjIsActive(vm))
                def->state = VIR_DOMAIN_DISK_SNAPSHOT;
            else
                def->state = VIR_DOMAIN_SHUTOFF;
11513
            def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
11514 11515 11516 11517
        } else if (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            def->state = virDomainObjGetState(vm, NULL);
            align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
            align_match = false;
11518 11519
        } else {
            def->state = virDomainObjGetState(vm, NULL);
11520 11521 11522
            def->memory = (def->state == VIR_DOMAIN_SHUTOFF ?
                           VIR_DOMAIN_SNAPSHOT_LOCATION_NONE :
                           VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL);
11523
        }
E
Eric Blake 已提交
11524 11525 11526 11527
        if (virDomainSnapshotAlignDisks(def, align_location,
                                        align_match) < 0 ||
            qemuDomainSnapshotPrepare(vm, def, &flags) < 0)
            goto cleanup;
11528 11529
    }

11530 11531 11532 11533 11534 11535
    if (!snap) {
        if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
            goto cleanup;

        def = NULL;
    }
C
Chris Lalancette 已提交
11536

11537 11538
    if (update_current)
        snap->def->current = true;
11539
    if (vm->current_snapshot) {
11540 11541 11542 11543 11544 11545
        if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
            snap->def->parent = strdup(vm->current_snapshot->def->name);
            if (snap->def->parent == NULL) {
                virReportOOMError();
                goto cleanup;
            }
11546
        }
11547
        if (update_current) {
11548 11549
            vm->current_snapshot->def->current = false;
            if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
11550
                                                cfg->snapshotDir) < 0)
11551 11552 11553
                goto cleanup;
            vm->current_snapshot = NULL;
        }
11554
    }
11555

C
Chris Lalancette 已提交
11556
    /* actually do the snapshot */
11557 11558
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
        /* XXX Should we validate that the redefined snapshot even
11559 11560
         * makes sense, such as checking that qemu-img recognizes the
         * snapshot name in at least one of the domain's disks?  */
11561 11562 11563 11564 11565 11566 11567 11568 11569 11570 11571 11572 11573
    } 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 已提交
11574
    } else {
11575 11576 11577 11578 11579 11580 11581 11582 11583 11584 11585 11586 11587
        /* 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 已提交
11588 11589
    }

11590
    /* If we fail after this point, there's not a whole lot we can
C
Chris Lalancette 已提交
11591 11592 11593 11594 11595 11596
     * 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:
11597
    if (vm) {
11598
        if (snapshot && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
11599
            if (qemuDomainSnapshotWriteMetadata(vm, snap,
11600
                                                cfg->snapshotDir) < 0) {
11601 11602 11603 11604 11605 11606 11607 11608
                /* 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);
11609 11610 11611
            } else {
                if (update_current)
                    vm->current_snapshot = snap;
11612
                other = virDomainSnapshotFindByName(vm->snapshots,
11613 11614 11615 11616 11617
                                                    snap->def->parent);
                snap->parent = other;
                other->nchildren++;
                snap->sibling = other->first_child;
                other->first_child = snap;
11618
            }
11619
        } else if (snap) {
11620
            virDomainSnapshotObjListRemove(vm->snapshots, snap);
11621
        }
11622
        virObjectUnlock(vm);
11623 11624
    }
    virDomainSnapshotDefFree(def);
11625
    VIR_FREE(xml);
11626
    virObjectUnref(caps);
11627
    virObjectUnref(cfg);
C
Chris Lalancette 已提交
11628 11629 11630 11631 11632
    return snapshot;
}

static int qemuDomainSnapshotListNames(virDomainPtr domain, char **names,
                                       int nameslen,
11633
                                       unsigned int flags)
C
Chris Lalancette 已提交
11634 11635 11636 11637
{
    virDomainObjPtr vm = NULL;
    int n = -1;

11638
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
11639
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
11640

11641
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
11642 11643
        goto cleanup;

11644
    n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
11645
                                         flags);
C
Chris Lalancette 已提交
11646 11647 11648

cleanup:
    if (vm)
11649
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
11650 11651 11652 11653
    return n;
}

static int qemuDomainSnapshotNum(virDomainPtr domain,
11654
                                 unsigned int flags)
C
Chris Lalancette 已提交
11655 11656 11657 11658
{
    virDomainObjPtr vm = NULL;
    int n = -1;

11659
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
11660
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
11661

11662
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
11663 11664
        goto cleanup;

11665
    n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);
C
Chris Lalancette 已提交
11666 11667 11668

cleanup:
    if (vm)
11669
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
11670 11671 11672
    return n;
}

11673 11674 11675 11676 11677 11678 11679 11680 11681 11682
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);

11683
    if (!(vm = qemuDomObjFromDomain(domain)))
11684 11685
        goto cleanup;

11686
    n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);
11687 11688 11689

cleanup:
    if (vm)
11690
        virObjectUnlock(vm);
11691 11692 11693
    return n;
}

11694 11695 11696 11697 11698 11699 11700 11701 11702 11703 11704
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 |
11705
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
11706

11707
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
11708 11709
        goto cleanup;

11710
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
11711 11712
        goto cleanup;

11713
    n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
11714
                                         flags);
11715 11716 11717

cleanup:
    if (vm)
11718
        virObjectUnlock(vm);
11719 11720 11721 11722 11723 11724 11725 11726 11727 11728 11729 11730
    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 |
11731
                  VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
11732

11733
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
11734 11735
        goto cleanup;

11736
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
11737 11738
        goto cleanup;

11739
    n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);
11740 11741 11742

cleanup:
    if (vm)
11743
        virObjectUnlock(vm);
11744 11745 11746
    return n;
}

11747 11748 11749 11750 11751 11752 11753 11754 11755 11756 11757 11758
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);

11759
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
11760 11761
        goto cleanup;

11762
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
11763 11764
        goto cleanup;

11765
    n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
11766 11767 11768 11769
                               flags);

cleanup:
    if (vm)
11770
        virObjectUnlock(vm);
11771 11772 11773
    return n;
}

C
Chris Lalancette 已提交
11774 11775
static virDomainSnapshotPtr qemuDomainSnapshotLookupByName(virDomainPtr domain,
                                                           const char *name,
11776
                                                           unsigned int flags)
C
Chris Lalancette 已提交
11777 11778 11779 11780 11781
{
    virDomainObjPtr vm;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr snapshot = NULL;

11782 11783
    virCheckFlags(0, NULL);

11784
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
11785 11786
        goto cleanup;

11787
    if (!(snap = qemuSnapObjFromName(vm, name)))
C
Chris Lalancette 已提交
11788 11789 11790 11791 11792 11793
        goto cleanup;

    snapshot = virGetDomainSnapshot(domain, snap->def->name);

cleanup:
    if (vm)
11794
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
11795 11796 11797 11798
    return snapshot;
}

static int qemuDomainHasCurrentSnapshot(virDomainPtr domain,
11799
                                        unsigned int flags)
C
Chris Lalancette 已提交
11800 11801 11802 11803
{
    virDomainObjPtr vm;
    int ret = -1;

11804 11805
    virCheckFlags(0, -1);

11806
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
11807 11808 11809 11810 11811 11812
        goto cleanup;

    ret = (vm->current_snapshot != NULL);

cleanup:
    if (vm)
11813
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
11814 11815 11816
    return ret;
}

11817 11818 11819 11820 11821 11822 11823 11824 11825 11826
static virDomainSnapshotPtr
qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainSnapshotPtr parent = NULL;

    virCheckFlags(0, NULL);

11827
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
11828 11829
        goto cleanup;

11830
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
11831 11832 11833
        goto cleanup;

    if (!snap->def->parent) {
11834 11835 11836
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
                       _("snapshot '%s' does not have a parent"),
                       snap->def->name);
11837 11838 11839 11840 11841 11842 11843
        goto cleanup;
    }

    parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent);

cleanup:
    if (vm)
11844
        virObjectUnlock(vm);
11845 11846 11847
    return parent;
}

C
Chris Lalancette 已提交
11848
static virDomainSnapshotPtr qemuDomainSnapshotCurrent(virDomainPtr domain,
11849
                                                      unsigned int flags)
C
Chris Lalancette 已提交
11850 11851 11852 11853
{
    virDomainObjPtr vm;
    virDomainSnapshotPtr snapshot = NULL;

11854 11855
    virCheckFlags(0, NULL);

11856
    if (!(vm = qemuDomObjFromDomain(domain)))
C
Chris Lalancette 已提交
11857 11858 11859
        goto cleanup;

    if (!vm->current_snapshot) {
11860 11861
        virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
                       _("the domain does not have a current snapshot"));
C
Chris Lalancette 已提交
11862 11863 11864 11865 11866 11867 11868
        goto cleanup;
    }

    snapshot = virGetDomainSnapshot(domain, vm->current_snapshot->def->name);

cleanup:
    if (vm)
11869
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
11870 11871 11872
    return snapshot;
}

11873 11874
static char *qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
                                          unsigned int flags)
C
Chris Lalancette 已提交
11875 11876 11877 11878 11879 11880
{
    virDomainObjPtr vm = NULL;
    char *xml = NULL;
    virDomainSnapshotObjPtr snap = NULL;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

11881
    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);
11882

11883
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
C
Chris Lalancette 已提交
11884 11885
        goto cleanup;

11886
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
C
Chris Lalancette 已提交
11887
        goto cleanup;
11888 11889

    virUUIDFormat(snapshot->domain->uuid, uuidstr);
C
Chris Lalancette 已提交
11890

11891
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, flags, 0);
C
Chris Lalancette 已提交
11892 11893 11894

cleanup:
    if (vm)
11895
        virObjectUnlock(vm);
C
Chris Lalancette 已提交
11896 11897 11898
    return xml;
}

11899 11900 11901 11902 11903 11904 11905 11906 11907 11908
static int
qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;

    virCheckFlags(0, -1);

11909
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
11910 11911
        goto cleanup;

11912
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
11913 11914 11915 11916 11917 11918 11919
        goto cleanup;

    ret = (vm->current_snapshot &&
           STREQ(snapshot->name, vm->current_snapshot->def->name));

cleanup:
    if (vm)
11920
        virObjectUnlock(vm);
11921 11922 11923 11924 11925 11926 11927 11928 11929 11930 11931 11932 11933 11934
    return ret;
}


static int
qemuDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;

    virCheckFlags(0, -1);

11935
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
11936 11937
        goto cleanup;

11938
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
11939 11940 11941 11942 11943 11944 11945 11946 11947
        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)
11948
        virObjectUnlock(vm);
11949 11950 11951
    return ret;
}

11952 11953
/* The domain is expected to be locked and inactive. */
static int
11954
qemuDomainSnapshotRevertInactive(virQEMUDriverPtr driver,
E
Eric Blake 已提交
11955
                                 virDomainObjPtr vm,
11956 11957 11958
                                 virDomainSnapshotObjPtr snap)
{
    /* Try all disks, but report failure if we skipped any.  */
E
Eric Blake 已提交
11959
    int ret = qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-a", true);
11960 11961 11962
    return ret > 0 ? -1 : ret;
}

C
Chris Lalancette 已提交
11963
static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
11964
                                      unsigned int flags)
C
Chris Lalancette 已提交
11965
{
11966
    virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
C
Chris Lalancette 已提交
11967 11968 11969 11970
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;
    virDomainEventPtr event = NULL;
11971
    virDomainEventPtr event2 = NULL;
11972
    int detail;
C
Chris Lalancette 已提交
11973 11974
    qemuDomainObjPrivatePtr priv;
    int rc;
11975
    virDomainDefPtr config = NULL;
11976
    virQEMUDriverConfigPtr cfg = NULL;
11977
    virCapsPtr caps = NULL;
C
Chris Lalancette 已提交
11978

11979
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
11980 11981
                  VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
                  VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, -1);
11982

11983 11984 11985 11986 11987 11988 11989 11990 11991 11992
    /* 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
11993 11994
     * Also, several transitions occur even if we fail partway through,
     * and use of FORCE can cause multiple transitions.
11995 11996
     */

11997 11998
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
        return -1;
11999 12000 12001

    cfg = virQEMUDriverGetConfig(driver);

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

E
Eric Blake 已提交
12005 12006 12007 12008 12009
    if (virDomainHasDiskMirror(vm)) {
        virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, "%s",
                       _("domain has active block copy job"));
        goto cleanup;
    }
C
Chris Lalancette 已提交
12010

12011
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
C
Chris Lalancette 已提交
12012 12013
        goto cleanup;

12014 12015 12016 12017 12018
    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) {
12019 12020 12021
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("transient domain needs to request run or pause "
                         "to revert to inactive snapshot"));
12022 12023
        goto cleanup;
    }
12024
    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) {
12025 12026 12027
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("revert to external disk snapshot not supported "
                         "yet"));
12028 12029
        goto cleanup;
    }
12030 12031
    if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
        if (!snap->def->dom) {
12032 12033 12034
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
                           _("snapshot '%s' lacks domain '%s' rollback info"),
                           snap->def->name, vm->def->name);
12035 12036 12037 12038 12039 12040 12041
            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))) {
12042 12043
            virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                           _("must respawn qemu to start inactive snapshot"));
12044 12045 12046 12047
            goto cleanup;
        }
    }

12048

12049 12050 12051
    if (vm->current_snapshot) {
        vm->current_snapshot->def->current = false;
        if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
12052
                                            cfg->snapshotDir) < 0)
12053 12054 12055 12056 12057 12058
            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?  */
    }

12059
    /* Prepare to copy the snapshot inactive xml as the config of this
12060
     * domain.
12061 12062 12063
     *
     * XXX Should domain snapshots track live xml rather
     * than inactive xml?  */
12064
    snap->def->current = true;
12065
    if (snap->def->dom) {
12066
        config = virDomainDefCopy(snap->def->dom, caps, driver->xmlopt, true);
12067 12068 12069
        if (!config)
            goto cleanup;
    }
C
Chris Lalancette 已提交
12070

12071
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
C
Chris Lalancette 已提交
12072 12073 12074 12075
        goto cleanup;

    if (snap->def->state == VIR_DOMAIN_RUNNING
        || snap->def->state == VIR_DOMAIN_PAUSED) {
12076 12077 12078 12079 12080 12081 12082 12083 12084
        /* 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 已提交
12085
        if (virDomainObjIsActive(vm)) {
12086
            /* Transitions 5, 6, 8, 9 */
12087 12088
            /* Check for ABI compatibility.  */
            if (config && !virDomainDefCheckABIStability(vm->def, config)) {
12089 12090 12091 12092 12093
                virErrorPtr err = virGetLastError();

                if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
                    /* Re-spawn error using correct category. */
                    if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
12094 12095
                        virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
                                       err->str2);
12096 12097 12098
                    goto endjob;
                }
                virResetError(err);
12099 12100
                qemuProcessStop(driver, vm,
                                VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
12101 12102 12103 12104 12105 12106 12107 12108
                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;
12109 12110
            }

C
Chris Lalancette 已提交
12111
            priv = vm->privateData;
12112 12113 12114 12115 12116 12117 12118 12119 12120 12121 12122 12123 12124 12125 12126
            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)) {
12127 12128
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("guest unexpectedly quit"));
12129 12130 12131
                    goto endjob;
                }
            }
12132
            qemuDomainObjEnterMonitor(driver, vm);
C
Chris Lalancette 已提交
12133
            rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name);
12134
            qemuDomainObjExitMonitor(driver, vm);
12135 12136 12137
            if (rc < 0) {
                /* XXX resume domain if it was running before the
                 * failed loadvm attempt? */
12138
                goto endjob;
12139
            }
12140
            if (config)
12141
                virDomainObjAssignDef(vm, config, false, NULL);
E
Eric Blake 已提交
12142
        } else {
12143
            /* Transitions 2, 3 */
12144
        load:
12145
            was_stopped = true;
12146
            if (config)
12147
                virDomainObjAssignDef(vm, config, false, NULL);
12148

12149 12150 12151 12152
            rc = qemuProcessStart(snapshot->domain->conn,
                                  driver, vm, NULL, -1, NULL, snap,
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                                  VIR_QEMU_PROCESS_START_PAUSED);
12153
            virDomainAuditStart(vm, "from-snapshot", rc >= 0);
12154 12155 12156 12157
            detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STARTED,
                                             detail);
C
Chris Lalancette 已提交
12158
            if (rc < 0)
12159
                goto endjob;
C
Chris Lalancette 已提交
12160 12161
        }

12162
        /* Touch up domain state.  */
12163 12164 12165
        if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
            (snap->def->state == VIR_DOMAIN_PAUSED ||
             (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
12166 12167 12168 12169 12170 12171 12172 12173 12174 12175 12176 12177 12178
            /* 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)) {
12179 12180
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("guest unexpectedly quit"));
12181 12182 12183 12184 12185
                goto endjob;
            }
            rc = qemuProcessStartCPUs(driver, vm, snapshot->domain->conn,
                                      VIR_DOMAIN_RUNNING_FROM_SNAPSHOT,
                                      QEMU_ASYNC_JOB_NONE);
H
Hu Tao 已提交
12186
            if (rc < 0)
12187
                goto endjob;
12188 12189 12190 12191 12192 12193 12194 12195 12196 12197 12198 12199 12200 12201 12202
            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 已提交
12203
        }
E
Eric Blake 已提交
12204
    } else {
12205
        /* Transitions 1, 4, 7 */
12206 12207 12208
        /* 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 已提交
12209 12210 12211
         */

        if (virDomainObjIsActive(vm)) {
12212
            /* Transitions 4, 7 */
12213
            qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
12214
            virDomainAuditStop(vm, "from-snapshot");
12215
            detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
C
Chris Lalancette 已提交
12216 12217
            event = virDomainEventNewFromObj(vm,
                                             VIR_DOMAIN_EVENT_STOPPED,
12218
                                             detail);
12219 12220
        }

E
Eric Blake 已提交
12221
        if (qemuDomainSnapshotRevertInactive(driver, vm, snap) < 0) {
12222
            if (!vm->persistent) {
12223
                if (qemuDomainObjEndJob(driver, vm) > 0)
12224
                    qemuDomainRemoveInactive(driver, vm);
12225
                vm = NULL;
12226
                goto cleanup;
12227
            }
12228
            goto endjob;
C
Chris Lalancette 已提交
12229
        }
12230
        if (config)
12231
            virDomainObjAssignDef(vm, config, false, NULL);
12232

12233 12234 12235 12236
        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;
12237 12238 12239
            unsigned int start_flags = 0;

            start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
12240 12241 12242

            if (event)
                qemuDomainEventQueue(driver, event);
12243 12244 12245 12246
            rc = qemuProcessStart(snapshot->domain->conn,
                                  driver, vm, NULL, -1, NULL, NULL,
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                                  start_flags);
12247 12248 12249 12250
            virDomainAuditStart(vm, "from-snapshot", rc >= 0);
            if (rc < 0) {
                if (!vm->persistent) {
                    if (qemuDomainObjEndJob(driver, vm) > 0)
12251
                        qemuDomainRemoveInactive(driver, vm);
12252 12253 12254 12255 12256 12257 12258 12259 12260 12261 12262 12263 12264 12265 12266 12267
                    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 已提交
12268 12269 12270 12271
    }

    ret = 0;

12272
endjob:
12273
    if (vm && qemuDomainObjEndJob(driver, vm) == 0)
C
Chris Lalancette 已提交
12274 12275
        vm = NULL;

12276
cleanup:
12277 12278
    if (vm && ret == 0) {
        if (qemuDomainSnapshotWriteMetadata(vm, snap,
12279
                                            cfg->snapshotDir) < 0)
12280 12281 12282 12283 12284 12285
            ret = -1;
        else
            vm->current_snapshot = snap;
    } else if (snap) {
        snap->def->current = false;
    }
12286
    if (event) {
C
Chris Lalancette 已提交
12287
        qemuDomainEventQueue(driver, event);
12288 12289 12290
        if (event2)
            qemuDomainEventQueue(driver, event2);
    }
C
Chris Lalancette 已提交
12291
    if (vm)
12292
        virObjectUnlock(vm);
12293
    virObjectUnref(caps);
12294
    virObjectUnref(cfg);
C
Chris Lalancette 已提交
12295 12296 12297 12298

    return ret;
}

12299 12300 12301 12302

typedef struct _virQEMUSnapReparent virQEMUSnapReparent;
typedef virQEMUSnapReparent *virQEMUSnapReparentPtr;
struct _virQEMUSnapReparent {
12303
    virQEMUDriverConfigPtr cfg;
12304
    virDomainSnapshotObjPtr parent;
12305 12306
    virDomainObjPtr vm;
    int err;
12307
    virDomainSnapshotObjPtr last;
12308 12309 12310 12311
};

static void
qemuDomainSnapshotReparentChildren(void *payload,
12312
                                   const void *name ATTRIBUTE_UNUSED,
12313 12314 12315
                                   void *data)
{
    virDomainSnapshotObjPtr snap = payload;
12316
    virQEMUSnapReparentPtr rep = data;
12317 12318 12319 12320 12321

    if (rep->err < 0) {
        return;
    }

12322
    VIR_FREE(snap->def->parent);
12323
    snap->parent = rep->parent;
12324

12325
    if (rep->parent->def) {
12326
        snap->def->parent = strdup(rep->parent->def->name);
12327

12328 12329 12330 12331
        if (snap->def->parent == NULL) {
            virReportOOMError();
            rep->err = -1;
            return;
12332 12333
        }
    }
12334

12335 12336 12337
    if (!snap->sibling)
        rep->last = snap;

12338
    rep->err = qemuDomainSnapshotWriteMetadata(rep->vm, snap,
12339
                                               rep->cfg->snapshotDir);
12340 12341
}

12342

C
Chris Lalancette 已提交
12343 12344 12345
static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                                    unsigned int flags)
{
12346
    virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
C
Chris Lalancette 已提交
12347 12348 12349
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainSnapshotObjPtr snap = NULL;
12350 12351
    virQEMUSnapRemove rem;
    virQEMUSnapReparent rep;
12352
    bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);
12353
    int external = 0;
12354
    virQEMUDriverConfigPtr cfg = NULL;
C
Chris Lalancette 已提交
12355

12356
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
12357 12358
                  VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY |
                  VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);
12359

12360 12361
    if (!(vm = qemuDomObjFromSnapshot(snapshot)))
        return -1;
C
Chris Lalancette 已提交
12362

12363
    cfg = virQEMUDriverGetConfig(driver);
12364
    if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
C
Chris Lalancette 已提交
12365 12366
        goto cleanup;

12367
    if (!metadata_only) {
12368
        if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
12369
            virDomainSnapshotIsExternal(snap))
12370 12371
            external++;
        if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN)
E
Eric Blake 已提交
12372
            virDomainSnapshotForEachDescendant(snap,
12373 12374 12375
                                               qemuDomainSnapshotCountExternal,
                                               &external);
        if (external) {
12376 12377 12378
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("deletion of %d external disk snapshots not "
                             "supported yet"), external);
12379 12380 12381 12382
            goto cleanup;
        }
    }

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

12386 12387
    if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
C
Chris Lalancette 已提交
12388 12389
        rem.driver = driver;
        rem.vm = vm;
12390
        rem.metadata_only = metadata_only;
C
Chris Lalancette 已提交
12391
        rem.err = 0;
12392
        rem.current = false;
E
Eric Blake 已提交
12393
        virDomainSnapshotForEachDescendant(snap,
E
Eric Blake 已提交
12394
                                           qemuDomainSnapshotDiscardAll,
12395
                                           &rem);
C
Chris Lalancette 已提交
12396
        if (rem.err < 0)
12397
            goto endjob;
12398 12399 12400 12401
        if (rem.current) {
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
                snap->def->current = true;
                if (qemuDomainSnapshotWriteMetadata(vm, snap,
12402
                                                    cfg->snapshotDir) < 0) {
12403 12404 12405
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("failed to set snapshot '%s' as current"),
                                   snap->def->name);
12406 12407 12408 12409
                    snap->def->current = false;
                    goto endjob;
                }
            }
12410
            vm->current_snapshot = snap;
12411
        }
12412
    } else if (snap->nchildren) {
12413
        rep.cfg = cfg;
12414
        rep.parent = snap->parent;
12415 12416
        rep.vm = vm;
        rep.err = 0;
12417
        rep.last = NULL;
E
Eric Blake 已提交
12418
        virDomainSnapshotForEachChild(snap,
12419 12420
                                      qemuDomainSnapshotReparentChildren,
                                      &rep);
12421 12422
        if (rep.err < 0)
            goto endjob;
12423
        /* Can't modify siblings during ForEachChild, so do it now.  */
12424 12425 12426
        snap->parent->nchildren += snap->nchildren;
        rep.last->sibling = snap->parent->first_child;
        snap->parent->first_child = snap->first_child;
C
Chris Lalancette 已提交
12427 12428
    }

12429 12430 12431
    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
        snap->nchildren = 0;
        snap->first_child = NULL;
12432
        ret = 0;
12433
    } else {
12434
        virDomainSnapshotDropParent(snap);
12435
        ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
12436
    }
C
Chris Lalancette 已提交
12437

12438
endjob:
12439
    if (qemuDomainObjEndJob(driver, vm) == 0)
12440 12441
        vm = NULL;

C
Chris Lalancette 已提交
12442 12443
cleanup:
    if (vm)
12444
        virObjectUnlock(vm);
12445
    virObjectUnref(cfg);
C
Chris Lalancette 已提交
12446 12447
    return ret;
}
12448

12449 12450 12451
static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd,
                                    char **result, unsigned int flags)
{
12452
    virQEMUDriverPtr driver = domain->conn->privateData;
12453 12454 12455
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
12456
    bool hmp;
12457

12458
    virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
12459

12460
    if (!(vm = qemuDomObjFromDomain(domain)))
12461 12462 12463
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
12464 12465
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
12466
        goto cleanup;
12467
    }
12468

12469
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
12470 12471 12472
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
12473 12474
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
12475 12476 12477
        goto endjob;
    }

12478 12479
    priv = vm->privateData;

12480
    qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_MONITOR, -1);
12481

12482 12483
    hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);

12484
    qemuDomainObjEnterMonitor(driver, vm);
12485
    ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
12486
    qemuDomainObjExitMonitor(driver, vm);
12487 12488

endjob:
12489
    if (qemuDomainObjEndJob(driver, vm) == 0) {
12490 12491 12492 12493 12494
        vm = NULL;
    }

cleanup:
    if (vm)
12495
        virObjectUnlock(vm);
12496 12497 12498
    return ret;
}

12499

12500
static virDomainPtr qemuDomainAttach(virConnectPtr conn,
12501
                                     unsigned int pid_value,
12502 12503
                                     unsigned int flags)
{
12504
    virQEMUDriverPtr driver = conn->privateData;
12505 12506 12507 12508 12509
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    virDomainPtr dom = NULL;
    virDomainChrSourceDefPtr monConfig = NULL;
    bool monJSON = false;
12510
    pid_t pid = pid_value;
12511
    char *pidfile = NULL;
12512
    virQEMUCapsPtr qemuCaps = NULL;
12513
    virCapsPtr caps = NULL;
12514 12515 12516

    virCheckFlags(0, NULL);

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

12520
    if (!(def = qemuParseCommandLinePid(caps, driver->xmlopt, pid,
12521 12522 12523 12524
                                        &pidfile, &monConfig, &monJSON)))
        goto cleanup;

    if (!monConfig) {
12525 12526
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("No monitor connection for pid %u"), pid_value);
12527 12528 12529
        goto cleanup;
    }
    if (monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
12530 12531 12532 12533 12534
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Cannot connect to monitor connection of type '%s' "
                         "for pid %u"),
                       virDomainChrTypeToString(monConfig->type),
                       pid_value);
12535 12536 12537 12538
        goto cleanup;
    }

    if (!(def->name) &&
12539
        virAsprintf(&def->name, "attach-pid-%u", pid_value) < 0) {
12540 12541 12542 12543
        virReportOOMError();
        goto cleanup;
    }

12544
    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
12545 12546
        goto cleanup;

12547
    if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
12548 12549
        goto cleanup;

12550
    if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0)
12551 12552
        goto cleanup;

12553
    if (!(vm = virDomainObjListAdd(driver->domains, def,
12554
                                   driver->xmlopt,
12555 12556 12557
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
12558 12559 12560 12561
        goto cleanup;

    def = NULL;

12562
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
12563 12564 12565 12566 12567 12568 12569 12570 12571 12572 12573 12574 12575 12576
        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:
12577
    if (qemuDomainObjEndJob(driver, vm) == 0) {
12578 12579 12580 12581 12582 12583
        vm = NULL;
        goto cleanup;
    }

cleanup:
    virDomainDefFree(def);
12584
    virObjectUnref(qemuCaps);
12585 12586
    virDomainChrSourceDefFree(monConfig);
    if (vm)
12587
        virObjectUnlock(vm);
12588
    VIR_FREE(pidfile);
12589
    virObjectUnref(caps);
12590 12591 12592 12593
    return dom;
}


12594 12595
static int
qemuDomainOpenConsole(virDomainPtr dom,
12596
                      const char *dev_name,
12597 12598 12599 12600 12601 12602 12603
                      virStreamPtr st,
                      unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    int i;
    virDomainChrDefPtr chr = NULL;
12604
    qemuDomainObjPrivatePtr priv;
12605

12606 12607
    virCheckFlags(VIR_DOMAIN_CONSOLE_SAFE |
                  VIR_DOMAIN_CONSOLE_FORCE, -1);
12608

12609
    if (!(vm = qemuDomObjFromDomain(dom)))
12610 12611 12612
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
12613 12614
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
12615 12616 12617
        goto cleanup;
    }

12618 12619
    priv = vm->privateData;

12620
    if (dev_name) {
12621 12622 12623 12624 12625
        for (i = 0 ; !chr && i < vm->def->nconsoles ; i++) {
            if (vm->def->consoles[i]->info.alias &&
                STREQ(dev_name, vm->def->consoles[i]->info.alias))
                chr = vm->def->consoles[i];
        }
12626
        for (i = 0 ; !chr && i < vm->def->nserials ; i++) {
12627
            if (STREQ(dev_name, vm->def->serials[i]->info.alias))
12628 12629 12630
                chr = vm->def->serials[i];
        }
        for (i = 0 ; !chr && i < vm->def->nparallels ; i++) {
12631
            if (STREQ(dev_name, vm->def->parallels[i]->info.alias))
12632 12633 12634
                chr = vm->def->parallels[i];
        }
    } else {
12635 12636
        if (vm->def->nconsoles)
            chr = vm->def->consoles[0];
12637 12638 12639 12640 12641
        else if (vm->def->nserials)
            chr = vm->def->serials[0];
    }

    if (!chr) {
12642 12643 12644
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find character device %s"),
                       NULLSTR(dev_name));
12645 12646 12647
        goto cleanup;
    }

12648
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
12649 12650 12651
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"),
                       NULLSTR(dev_name));
12652 12653 12654
        goto cleanup;
    }

12655
    /* handle mutually exclusive access to console devices */
12656
    ret = virChrdevOpen(priv->devs,
12657
                        &chr->source,
12658 12659
                        st,
                        (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
12660 12661

    if (ret == 1) {
12662 12663
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Active console session exists for this domain"));
12664 12665
        ret = -1;
    }
12666 12667 12668

cleanup:
    if (vm)
12669
        virObjectUnlock(vm);
12670 12671 12672
    return ret;
}

12673 12674 12675 12676 12677 12678 12679 12680 12681 12682 12683 12684 12685 12686 12687 12688 12689 12690 12691 12692 12693 12694 12695 12696 12697 12698 12699 12700 12701 12702 12703 12704 12705 12706 12707 12708 12709 12710 12711 12712 12713 12714 12715 12716 12717 12718 12719 12720 12721 12722 12723 12724 12725 12726 12727 12728 12729 12730 12731 12732 12733 12734 12735 12736 12737 12738 12739 12740
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) {
        for (i = 0 ; !chr && i < vm->def->nchannels ; i++) {
            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)
12741
        virObjectUnlock(vm);
12742 12743 12744
    return ret;
}

E
Eric Blake 已提交
12745
static char *
E
Eric Blake 已提交
12746
qemuDiskPathToAlias(virDomainObjPtr vm, const char *path, int *idx)
E
Eric Blake 已提交
12747
{
12748 12749
    int i;
    char *ret = NULL;
12750
    virDomainDiskDefPtr disk;
12751

12752 12753 12754
    i = virDomainDiskIndexByName(vm->def, path, true);
    if (i < 0)
        goto cleanup;
12755

12756
    disk = vm->def->disks[i];
E
Eric Blake 已提交
12757 12758
    if (idx)
        *idx = i;
12759

12760 12761 12762 12763 12764 12765 12766 12767
    if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
        disk->type != VIR_DOMAIN_DISK_TYPE_FILE)
        goto cleanup;

    if (disk->src) {
        if (virAsprintf(&ret, "drive-%s", disk->info.alias) < 0) {
            virReportOOMError();
            return NULL;
12768 12769 12770
        }
    }

12771
cleanup:
12772
    if (!ret) {
12773 12774
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("No device found for specified path"));
12775 12776 12777 12778
    }
    return ret;
}

12779 12780 12781 12782
/* 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 已提交
12783
qemuDomainBlockPivot(virConnectPtr conn,
12784
                     virQEMUDriverPtr driver, virDomainObjPtr vm,
12785 12786 12787 12788 12789 12790
                     const char *device, virDomainDiskDefPtr disk)
{
    int ret = -1;
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virDomainBlockJobInfo info;
    const char *format = virStorageFileFormatTypeToString(disk->mirrorFormat);
E
Eric Blake 已提交
12791
    bool resume = false;
12792 12793 12794
    char *oldsrc = NULL;
    int oldformat;
    virStorageFileMetadataPtr oldchain = NULL;
12795
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
12796 12797 12798

    /* Probe the status, if needed.  */
    if (!disk->mirroring) {
12799
        qemuDomainObjEnterMonitor(driver, vm);
12800 12801
        ret = qemuMonitorBlockJob(priv->mon, device, NULL, 0, &info,
                                  BLOCK_JOB_INFO, true);
12802
        qemuDomainObjExitMonitor(driver, vm);
12803 12804 12805 12806 12807 12808 12809 12810 12811 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821
        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 已提交
12822 12823 12824 12825 12826 12827 12828 12829 12830 12831 12832 12833 12834 12835 12836 12837 12838 12839 12840 12841 12842 12843 12844
    /* 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;
        }
    }

12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 12855 12856 12857 12858 12859 12860 12861 12862 12863
    /* 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 &&
12864
        (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
12865
                                 vm, disk) < 0 ||
12866
         qemuSetupDiskCgroup(vm, disk) < 0 ||
12867 12868 12869 12870 12871 12872 12873 12874
         virSecurityManagerSetImageLabel(driver->securityManager, vm->def,
                                         disk) < 0)) {
        disk->src = oldsrc;
        disk->format = oldformat;
        disk->backingChain = oldchain;
        goto cleanup;
    }

12875
    /* Attempt the pivot.  */
12876
    qemuDomainObjEnterMonitor(driver, vm);
12877
    ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror, format);
12878
    qemuDomainObjExitMonitor(driver, vm);
12879 12880 12881 12882 12883 12884 12885 12886 12887

    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.  */
12888 12889
        VIR_FREE(oldsrc);
        virStorageFileFreeMetadata(oldchain);
12890 12891 12892 12893 12894 12895 12896 12897 12898 12899
        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.  */
12900 12901 12902 12903
        disk->src = oldsrc;
        disk->format = oldformat;
        virStorageFileFreeMetadata(disk->backingChain);
        disk->backingChain = oldchain;
12904 12905
        VIR_FREE(disk->mirror);
    }
12906 12907
    disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
    disk->mirroring = false;
12908 12909

cleanup:
E
Eric Blake 已提交
12910 12911 12912
    if (resume && virDomainObjIsActive(vm) &&
        qemuProcessStartCPUs(driver, vm, conn,
                             VIR_DOMAIN_RUNNING_UNPAUSED,
12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923
                             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 已提交
12924
    }
12925
    virObjectUnref(cfg);
12926 12927 12928
    return ret;
}

12929
static int
12930
qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base,
12931
                       unsigned long bandwidth, virDomainBlockJobInfoPtr info,
12932
                       int mode, unsigned int flags)
12933
{
12934
    virQEMUDriverPtr driver = dom->conn->privateData;
12935 12936
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
E
Eric Blake 已提交
12937
    char *device = NULL;
12938
    int ret = -1;
12939
    bool async = false;
12940 12941 12942
    virDomainEventPtr event = NULL;
    int idx;
    virDomainDiskDefPtr disk;
12943

12944 12945 12946
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

12947
    if (!virDomainObjIsActive(vm)) {
12948 12949
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
12950 12951 12952
        goto cleanup;
    }

12953
    priv = vm->privateData;
12954
    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC)) {
12955
        async = true;
12956
    } else if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_SYNC)) {
12957 12958
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("block jobs not supported with this QEMU binary"));
12959 12960
        goto cleanup;
    } else if (base) {
12961 12962 12963
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("partial block pull not supported with this "
                         "QEMU binary"));
12964
        goto cleanup;
12965
    } else if (mode == BLOCK_JOB_PULL && bandwidth) {
12966 12967 12968
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("setting bandwidth at start of block pull not "
                         "supported with this QEMU binary"));
12969
        goto cleanup;
12970
    }
12971

12972 12973
    device = qemuDiskPathToAlias(vm, path, &idx);
    if (!device)
12974
        goto cleanup;
12975
    disk = vm->def->disks[idx];
12976

E
Eric Blake 已提交
12977 12978 12979 12980 12981 12982
    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;
    }
12983 12984 12985 12986 12987 12988 12989 12990
    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 已提交
12991

12992
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
12993
        goto cleanup;
12994 12995

    if (!virDomainObjIsActive(vm)) {
12996 12997
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
12998 12999 13000
        goto endjob;
    }

13001 13002
    if (disk->mirror && mode == BLOCK_JOB_ABORT &&
        (flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT)) {
E
Eric Blake 已提交
13003
        ret = qemuDomainBlockPivot(dom->conn, driver, vm, device, disk);
13004 13005 13006
        goto endjob;
    }

13007
    qemuDomainObjEnterMonitor(driver, vm);
13008
    /* XXX - libvirt should really be tracking the backing file chain
13009 13010
     * itself, and validating that base is on the chain, rather than
     * relying on qemu to do this.  */
13011 13012
    ret = qemuMonitorBlockJob(priv->mon, device, base, bandwidth, info, mode,
                              async);
13013
    qemuDomainObjExitMonitor(driver, vm);
13014 13015 13016
    if (ret < 0)
        goto endjob;

13017 13018 13019 13020 13021 13022
    /* 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;

13023 13024 13025 13026 13027 13028 13029 13030 13031
    /* 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;
    }

13032 13033 13034 13035 13036 13037 13038 13039 13040 13041 13042 13043 13044 13045 13046 13047 13048 13049 13050
    /* 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;

13051
                qemuDomainObjEnterMonitor(driver, vm);
13052 13053
                ret = qemuMonitorBlockJob(priv->mon, device, NULL, 0, &dummy,
                                          BLOCK_JOB_INFO, async);
13054
                qemuDomainObjExitMonitor(driver, vm);
13055 13056 13057 13058

                if (ret <= 0)
                    break;

13059
                virObjectUnlock(vm);
13060 13061 13062

                nanosleep(&ts, NULL);

13063
                virObjectLock(vm);
13064 13065

                if (!virDomainObjIsActive(vm)) {
13066 13067
                    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                                   _("domain is not running"));
13068 13069 13070 13071 13072 13073
                    ret = -1;
                    break;
                }
            }
        }
    }
13074 13075

endjob:
13076 13077 13078 13079 13080 13081 13082 13083
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    VIR_FREE(device);
    if (vm)
13084
        virObjectUnlock(vm);
13085 13086
    if (event)
        qemuDomainEventQueue(driver, event);
13087 13088 13089 13090 13091 13092
    return ret;
}

static int
qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags)
{
13093 13094
    virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC |
                  VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, -1);
13095 13096
    return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT,
                                  flags);
13097 13098 13099 13100 13101 13102 13103
}

static int
qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
                           virDomainBlockJobInfoPtr info, unsigned int flags)
{
    virCheckFlags(0, -1);
13104 13105
    return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO,
                                  flags);
13106 13107 13108 13109 13110 13111 13112
}

static int
qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
                           unsigned long bandwidth, unsigned int flags)
{
    virCheckFlags(0, -1);
13113
    return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
13114
                                  BLOCK_JOB_SPEED, flags);
13115 13116
}

13117 13118 13119 13120 13121
static int
qemuDomainBlockCopy(virDomainPtr dom, const char *path,
                    const char *dest, const char *format,
                    unsigned long bandwidth, unsigned int flags)
{
13122
    virQEMUDriverPtr driver = dom->conn->privateData;
13123 13124 13125 13126 13127 13128
    virDomainObjPtr vm;
    qemuDomainObjPrivatePtr priv;
    char *device = NULL;
    virDomainDiskDefPtr disk;
    int ret = -1;
    int idx;
13129
    struct stat st;
13130 13131
    bool need_unlink = false;
    char *mirror = NULL;
13132
    virQEMUDriverConfigPtr cfg = NULL;
13133 13134

    /* Preliminaries: find the disk we are editing, sanity checks */
13135 13136
    virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
                  VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1);
13137 13138 13139 13140

    if (!(vm = qemuDomObjFromDomain(dom)))
        goto cleanup;
    priv = vm->privateData;
13141
    cfg = virQEMUDriverGetConfig(driver);
13142 13143 13144 13145 13146 13147 13148 13149 13150 13151 13152 13153 13154 13155 13156 13157 13158 13159
    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;
    }

13160 13161
    if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
          virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
13162 13163 13164 13165 13166 13167 13168 13169 13170 13171 13172 13173 13174 13175 13176 13177 13178 13179 13180 13181 13182 13183 13184 13185 13186 13187 13188 13189 13190 13191 13192 13193 13194 13195 13196 13197
        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.  */
13198 13199 13200 13201 13202 13203 13204 13205 13206 13207 13208 13209 13210 13211 13212 13213 13214 13215 13216 13217
    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;
    }

13218 13219 13220 13221 13222 13223 13224
    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)
13225
            disk->mirrorFormat = disk->format;
13226
    } else if (format) {
13227 13228 13229 13230 13231 13232
        disk->mirrorFormat = virStorageFileFormatTypeFromString(format);
        if (disk->mirrorFormat <= 0) {
            virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"),
                           format);
            goto endjob;
        }
13233 13234 13235 13236 13237
    } 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.  */
13238 13239
        disk->mirrorFormat = virStorageFileProbeFormat(dest, cfg->user,
                                                       cfg->group);
13240 13241 13242
    }
    if (!format && disk->mirrorFormat > 0)
        format = virStorageFileFormatTypeToString(disk->mirrorFormat);
13243
    if (!(mirror = strdup(dest))) {
13244 13245 13246 13247
        virReportOOMError();
        goto endjob;
    }

13248
    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
13249
                                          VIR_DISK_CHAIN_READ_WRITE) < 0) {
13250
        qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
13251 13252 13253 13254
                                          VIR_DISK_CHAIN_NO_ACCESS);
        goto endjob;
    }

13255 13256 13257 13258
    /* Actually start the mirroring */
    qemuDomainObjEnterMonitor(driver, vm);
    ret = qemuMonitorDriveMirror(priv->mon, device, dest, format, bandwidth,
                                 flags);
13259
    virDomainAuditDisk(vm, NULL, dest, "mirror", ret >= 0);
13260
    qemuDomainObjExitMonitor(driver, vm);
13261
    if (ret < 0) {
13262
        qemuDomainPrepareDiskChainElement(driver, vm, disk, dest,
13263 13264 13265 13266 13267 13268 13269 13270
                                          VIR_DISK_CHAIN_NO_ACCESS);
        goto endjob;
    }

    /* Update vm in place to match changes.  */
    need_unlink = false;
    disk->mirror = mirror;
    mirror = NULL;
13271 13272

endjob:
13273 13274 13275
    if (need_unlink && unlink(dest))
        VIR_WARN("unable to unlink just-created %s", dest);
    if (ret < 0)
13276
        disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
13277
    VIR_FREE(mirror);
13278 13279 13280 13281 13282 13283 13284 13285
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    VIR_FREE(device);
    if (vm)
13286
        virObjectUnlock(vm);
13287
    virObjectUnref(cfg);
13288 13289 13290
    return ret;
}

13291
static int
13292 13293
qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
                      unsigned long bandwidth, unsigned int flags)
13294
{
13295
    virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
13296
                  VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
13297 13298 13299 13300 13301 13302 13303 13304 13305 13306 13307 13308
                  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);
    }

13309 13310
    return qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL,
                                  BLOCK_JOB_PULL, flags);
13311
}
13312

13313 13314 13315 13316
static int
qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
                    unsigned int flags)
{
13317 13318 13319
    virCheckFlags(0, -1);
    return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
                                  BLOCK_JOB_PULL, flags);
13320 13321
}

13322 13323 13324 13325 13326 13327

static int
qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base,
                      const char *top, unsigned long bandwidth,
                      unsigned int flags)
{
13328
    virQEMUDriverPtr driver = dom->conn->privateData;
13329 13330 13331 13332 13333
    qemuDomainObjPrivatePtr priv;
    virDomainObjPtr vm = NULL;
    char *device = NULL;
    int ret = -1;
    int idx;
E
Eric Blake 已提交
13334
    virDomainDiskDefPtr disk = NULL;
13335 13336 13337 13338
    const char *top_canon = NULL;
    virStorageFileMetadataPtr top_meta = NULL;
    const char *top_parent = NULL;
    const char *base_canon = NULL;
E
Eric Blake 已提交
13339
    bool clean_access = false;
13340

13341
    virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW, -1);
13342 13343 13344 13345 13346 13347 13348 13349 13350 13351 13352 13353 13354

    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;
    }
13355
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_COMMIT)) {
13356 13357 13358 13359 13360 13361 13362 13363 13364 13365 13366 13367 13368 13369 13370 13371
        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;
    }
13372 13373
    if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
        goto endjob;
13374

13375 13376 13377 13378 13379 13380 13381 13382 13383 13384 13385 13386 13387 13388 13389 13390 13391 13392 13393 13394 13395 13396 13397 13398 13399 13400 13401 13402 13403 13404 13405 13406 13407 13408 13409 13410 13411 13412 13413
    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;
    }
13414

13415 13416 13417 13418 13419 13420 13421
    /* 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 已提交
13422
    clean_access = true;
13423
    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, base_canon,
13424 13425
                                          VIR_DISK_CHAIN_READ_WRITE) < 0 ||
        (top_parent && top_parent != disk->src &&
13426
         qemuDomainPrepareDiskChainElement(driver, vm, disk,
13427 13428 13429 13430 13431
                                           top_parent,
                                           VIR_DISK_CHAIN_READ_WRITE) < 0))
        goto endjob;

    /* Start the commit operation.  */
13432
    qemuDomainObjEnterMonitor(driver, vm);
13433 13434
    ret = qemuMonitorBlockCommit(priv->mon, device, top_canon, base_canon,
                                 bandwidth);
13435 13436 13437
    qemuDomainObjExitMonitor(driver, vm);

endjob:
E
Eric Blake 已提交
13438
    if (ret < 0 && clean_access) {
13439
        /* Revert access to read-only, if possible.  */
13440
        qemuDomainPrepareDiskChainElement(driver, vm, disk, base_canon,
13441 13442
                                          VIR_DISK_CHAIN_READ_ONLY);
        if (top_parent && top_parent != disk->src)
13443
            qemuDomainPrepareDiskChainElement(driver, vm, disk,
13444 13445 13446
                                              top_parent,
                                              VIR_DISK_CHAIN_READ_ONLY);
    }
13447 13448 13449 13450 13451 13452 13453 13454
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    VIR_FREE(device);
    if (vm)
13455
        virObjectUnlock(vm);
13456 13457 13458
    return ret;
}

13459 13460 13461 13462 13463 13464
static int
qemuDomainOpenGraphics(virDomainPtr dom,
                       unsigned int idx,
                       int fd,
                       unsigned int flags)
{
13465
    virQEMUDriverPtr driver = dom->conn->privateData;
13466 13467 13468 13469 13470 13471 13472
    virDomainObjPtr vm = NULL;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;
    const char *protocol;

    virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);

13473 13474
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
13475 13476

    if (!virDomainObjIsActive(vm)) {
13477 13478
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
13479 13480 13481 13482 13483 13484
        goto cleanup;
    }

    priv = vm->privateData;

    if (idx >= vm->def->ngraphics) {
13485 13486
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No graphics backend with index %d"), idx);
13487 13488 13489 13490 13491 13492 13493 13494 13495 13496
        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:
13497 13498 13499
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Can only open VNC or SPICE graphics backends, not %s"),
                       virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
13500 13501 13502
        goto cleanup;
    }

13503
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
13504
        goto cleanup;
13505
    qemuDomainObjEnterMonitor(driver, vm);
13506 13507
    ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
                                  (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
13508
    qemuDomainObjExitMonitor(driver, vm);
13509 13510 13511 13512 13513 13514 13515
    if (qemuDomainObjEndJob(driver, vm) == 0) {
        vm = NULL;
        goto cleanup;
    }

cleanup:
    if (vm)
13516
        virObjectUnlock(vm);
13517 13518 13519
    return ret;
}

13520 13521 13522 13523 13524 13525 13526
static int
qemuDomainSetBlockIoTune(virDomainPtr dom,
                         const char *disk,
                         virTypedParameterPtr params,
                         int nparams,
                         unsigned int flags)
{
13527
    virQEMUDriverPtr driver = dom->conn->privateData;
13528 13529 13530 13531
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
    virDomainDefPtr persistentDef = NULL;
    virDomainBlockIoTuneInfo info;
E
Eric Blake 已提交
13532
    virDomainBlockIoTuneInfo *oldinfo;
13533 13534 13535 13536
    const char *device = NULL;
    int ret = -1;
    int i;
    int idx = -1;
E
Eric Blake 已提交
13537 13538
    bool set_bytes = false;
    bool set_iops = false;
13539
    virQEMUDriverConfigPtr cfg = NULL;
13540
    virCapsPtr caps = NULL;
13541 13542 13543

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
13544 13545 13546 13547 13548 13549 13550 13551 13552 13553 13554 13555 13556 13557 13558
    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;
13559 13560 13561

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

13562 13563 13564
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;

13565
    priv = vm->privateData;
13566 13567
    cfg = virQEMUDriverGetConfig(driver);

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

13571
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE)) {
13572 13573 13574
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("block I/O throttling not supported with this "
                         "QEMU binary"));
13575 13576
        goto cleanup;
    }
13577

E
Eric Blake 已提交
13578
    device = qemuDiskPathToAlias(vm, disk, &idx);
13579 13580 13581 13582
    if (!device) {
        goto cleanup;
    }

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

13586
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
13587
                                        &persistentDef) < 0)
13588 13589 13590 13591 13592 13593 13594
        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 已提交
13595
            set_bytes = true;
13596 13597 13598
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC)) {
            info.read_bytes_sec = param->value.ul;
E
Eric Blake 已提交
13599
            set_bytes = true;
13600 13601 13602
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC)) {
            info.write_bytes_sec = param->value.ul;
E
Eric Blake 已提交
13603
            set_bytes = true;
13604 13605 13606
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC)) {
            info.total_iops_sec = param->value.ul;
E
Eric Blake 已提交
13607
            set_iops = true;
13608 13609 13610
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC)) {
            info.read_iops_sec = param->value.ul;
E
Eric Blake 已提交
13611
            set_iops = true;
13612 13613 13614
        } else if (STREQ(param->field,
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) {
            info.write_iops_sec = param->value.ul;
E
Eric Blake 已提交
13615
            set_iops = true;
13616 13617 13618 13619 13620
        }
    }

    if ((info.total_bytes_sec && info.read_bytes_sec) ||
        (info.total_bytes_sec && info.write_bytes_sec)) {
13621 13622
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of bytes_sec cannot be set at the same time"));
13623 13624 13625 13626 13627
        goto endjob;
    }

    if ((info.total_iops_sec && info.read_iops_sec) ||
        (info.total_iops_sec && info.write_iops_sec)) {
13628 13629
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("total and read/write of iops_sec cannot be set at the same time"));
13630 13631 13632 13633
        goto endjob;
    }

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
E
Eric Blake 已提交
13634 13635 13636 13637 13638 13639 13640 13641 13642 13643 13644 13645 13646 13647
        /* 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;
        }
13648
        qemuDomainObjEnterMonitor(driver, vm);
13649
        ret = qemuMonitorSetBlockIoThrottle(priv->mon, device, &info);
13650
        qemuDomainObjExitMonitor(driver, vm);
L
Lei Li 已提交
13651 13652
        if (ret < 0)
            goto endjob;
13653
        vm->def->disks[idx]->blkdeviotune = info;
13654 13655 13656
    }

    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
13657 13658 13659 13660
        sa_assert(persistentDef);
        idx = virDomainDiskIndexByName(persistentDef, disk, true);
        if (idx < 0)
            goto endjob;
E
Eric Blake 已提交
13661 13662 13663 13664 13665 13666 13667 13668 13669 13670 13671
        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;
        }
13672
        persistentDef->disks[idx]->blkdeviotune = info;
13673
        ret = virDomainSaveConfig(cfg->configDir, persistentDef);
13674
        if (ret < 0) {
13675
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
13676 13677 13678 13679 13680 13681 13682 13683 13684 13685 13686 13687
                           _("Write to config file failed"));
            goto endjob;
        }
    }

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

cleanup:
    VIR_FREE(device);
    if (vm)
13688
        virObjectUnlock(vm);
13689
    virObjectUnref(caps);
13690
    virObjectUnref(cfg);
13691 13692 13693 13694 13695 13696 13697 13698 13699 13700
    return ret;
}

static int
qemuDomainGetBlockIoTune(virDomainPtr dom,
                         const char *disk,
                         virTypedParameterPtr params,
                         int *nparams,
                         unsigned int flags)
{
13701
    virQEMUDriverPtr driver = dom->conn->privateData;
13702 13703 13704 13705 13706 13707 13708
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
    virDomainDefPtr persistentDef = NULL;
    virDomainBlockIoTuneInfo reply;
    const char *device = NULL;
    int ret = -1;
    int i;
13709
    virCapsPtr caps = NULL;
13710 13711 13712 13713 13714 13715 13716 13717

    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;

13718 13719
    if (!(vm = qemuDomObjFromDomain(dom)))
        return -1;
13720

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

13724 13725 13726 13727 13728 13729 13730
    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 已提交
13731
    device = qemuDiskPathToAlias(vm, disk, NULL);
13732 13733 13734 13735 13736

    if (!device) {
        goto cleanup;
    }

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

13740
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
13741
                                        &persistentDef) < 0)
13742 13743 13744 13745
        goto endjob;

    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        priv = vm->privateData;
13746
        qemuDomainObjEnterMonitor(driver, vm);
13747
        ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, &reply);
13748
        qemuDomainObjExitMonitor(driver, vm);
13749 13750 13751 13752 13753 13754 13755 13756 13757 13758 13759 13760 13761 13762
        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];

13763
        switch (i) {
13764
        case 0:
13765 13766 13767 13768
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.total_bytes_sec) < 0)
13769 13770 13771
                goto endjob;
            break;
        case 1:
13772 13773 13774 13775
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.read_bytes_sec) < 0)
13776 13777 13778
                goto endjob;
            break;
        case 2:
13779 13780 13781 13782
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.write_bytes_sec) < 0)
13783 13784 13785
                goto endjob;
            break;
        case 3:
13786 13787 13788 13789
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.total_iops_sec) < 0)
13790 13791 13792
                goto endjob;
            break;
        case 4:
13793 13794 13795 13796
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.read_iops_sec) < 0)
13797 13798 13799
                goto endjob;
            break;
        case 5:
13800 13801 13802 13803
            if (virTypedParameterAssign(param,
                                        VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
                                        VIR_TYPED_PARAM_ULLONG,
                                        reply.write_iops_sec) < 0)
13804 13805 13806 13807 13808 13809 13810 13811 13812 13813 13814 13815 13816 13817 13818 13819 13820 13821
                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)
13822
        virObjectUnlock(vm);
13823
    virObjectUnref(caps);
13824 13825
    return ret;
}
13826

13827 13828 13829 13830 13831 13832
static int
qemuDomainGetDiskErrors(virDomainPtr dom,
                        virDomainDiskErrorPtr errors,
                        unsigned int nerrors,
                        unsigned int flags)
{
13833
    virQEMUDriverPtr driver = dom->conn->privateData;
13834 13835 13836 13837 13838 13839 13840 13841 13842
    virDomainObjPtr vm = NULL;
    qemuDomainObjPrivatePtr priv;
    virHashTablePtr table = NULL;
    int ret = -1;
    int i;
    int n = 0;

    virCheckFlags(0, -1);

13843
    if (!(vm = qemuDomObjFromDomain(dom)))
13844 13845 13846 13847 13848 13849 13850 13851
        goto cleanup;

    priv = vm->privateData;

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

    if (!virDomainObjIsActive(vm)) {
13852 13853
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
13854 13855 13856 13857 13858 13859 13860 13861 13862 13863 13864 13865 13866 13867 13868 13869 13870 13871 13872 13873 13874 13875 13876 13877 13878 13879 13880 13881 13882 13883 13884 13885 13886 13887 13888 13889 13890 13891 13892 13893
        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)
13894
        virObjectUnlock(vm);
13895 13896 13897 13898 13899 13900 13901 13902
    virHashFree(table);
    if (ret < 0) {
        for (i = 0; i < n; i++)
            VIR_FREE(errors[i].disk);
    }
    return ret;
}

13903 13904 13905 13906 13907 13908 13909 13910
static int
qemuDomainSetMetadata(virDomainPtr dom,
                      int type,
                      const char *metadata,
                      const char *key ATTRIBUTE_UNUSED,
                      const char *uri ATTRIBUTE_UNUSED,
                      unsigned int flags)
{
13911
    virQEMUDriverPtr driver = dom->conn->privateData;
13912 13913 13914
    virDomainObjPtr vm;
    virDomainDefPtr persistentDef;
    int ret = -1;
13915
    virQEMUDriverConfigPtr cfg = NULL;
13916
    virCapsPtr caps = NULL;
13917 13918 13919 13920

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

13921
    if (!(vm = qemuDomObjFromDomain(dom)))
13922 13923
        goto cleanup;

13924 13925
    cfg = virQEMUDriverGetConfig(driver);

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

13929
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
13930 13931 13932 13933 13934 13935 13936 13937 13938 13939 13940 13941 13942 13943 13944 13945 13946 13947
                                        &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:
13948
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
13949
                           _("QEmu driver does not support modifying "
13950
                             "<metadata> element"));
13951 13952 13953
            goto cleanup;
            break;
        default:
13954 13955
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("unknown metadata type"));
13956 13957 13958 13959 13960 13961 13962 13963 13964 13965 13966 13967 13968 13969 13970 13971 13972 13973 13974 13975
            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:
13976
            virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
13977
                           _("QEMU driver does not support "
13978
                             "<metadata> element"));
13979 13980
            goto cleanup;
         default:
13981 13982
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("unknown metadata type"));
13983 13984 13985 13986
            goto cleanup;
            break;
        }

13987
        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
13988 13989 13990 13991 13992 13993 13994
            goto cleanup;
    }

    ret = 0;

cleanup:
    if (vm)
13995
        virObjectUnlock(vm);
13996
    virObjectUnref(caps);
13997
    virObjectUnref(cfg);
13998 13999 14000 14001 14002 14003 14004 14005 14006 14007 14008 14009
    return ret;
no_memory:
    virReportOOMError();
    goto cleanup;
}

static char *
qemuDomainGetMetadata(virDomainPtr dom,
                      int type,
                      const char *uri ATTRIBUTE_UNUSED,
                      unsigned int flags)
{
14010
    virQEMUDriverPtr driver = dom->conn->privateData;
14011 14012 14013 14014
    virDomainObjPtr vm;
    virDomainDefPtr def;
    char *ret = NULL;
    char *field = NULL;
14015
    virCapsPtr caps = NULL;
14016 14017 14018 14019

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, NULL);

14020
    if (!(vm = qemuDomObjFromDomain(dom)))
14021 14022
        goto cleanup;

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

14026
    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags, &def) < 0)
14027 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040
        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:
14041
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
14042
                       _("QEMU driver does not support "
14043
                         "<metadata> element"));
14044 14045 14046
        goto cleanup;
        break;
    default:
14047 14048
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("unknown metadata type"));
14049 14050 14051 14052 14053
        goto cleanup;
        break;
    }

    if (!field) {
14054 14055
        virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s",
                       _("Requested metadata element is not present"));
14056 14057 14058 14059 14060 14061 14062 14063 14064 14065
        goto cleanup;
    }

    if (!(ret = strdup(field))) {
        virReportOOMError();
        goto cleanup;
    }

cleanup:
    if (vm)
14066
        virObjectUnlock(vm);
14067
    virObjectUnref(caps);
14068 14069 14070
    return ret;
}

14071 14072
/* qemuDomainGetCPUStats() with start_cpu == -1 */
static int
14073
qemuDomainGetTotalcpuStats(virDomainObjPtr vm,
14074 14075 14076 14077 14078
                           virTypedParameterPtr params,
                           int nparams)
{
    unsigned long long cpu_time;
    int ret;
14079
    qemuDomainObjPrivatePtr priv = vm->privateData;
14080 14081

    if (nparams == 0) /* return supported number of params */
E
Eric Blake 已提交
14082
        return QEMU_NB_TOTAL_CPU_STAT_PARAM;
14083
    /* entry 0 is cputime */
14084
    ret = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time);
14085 14086 14087 14088 14089
    if (ret < 0) {
        virReportSystemError(-ret, "%s", _("unable to get cpu account"));
        return -1;
    }

E
Eric Blake 已提交
14090 14091 14092 14093 14094 14095 14096 14097
    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;

14098
        ret = virCgroupGetCpuacctStat(priv->cgroup, &user, &sys);
E
Eric Blake 已提交
14099 14100 14101 14102 14103 14104 14105 14106 14107 14108 14109 14110 14111 14112 14113 14114 14115 14116 14117 14118
        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;
14119 14120
}

14121 14122 14123 14124 14125 14126 14127 14128 14129 14130 14131 14132 14133 14134 14135
/* 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
14136
getSumVcpuPercpuStats(virDomainObjPtr vm,
14137 14138 14139 14140 14141 14142
                      unsigned long long *sum_cpu_time,
                      unsigned int num)
{
    int ret = -1;
    int i;
    char *buf = NULL;
14143
    qemuDomainObjPrivatePtr priv = vm->privateData;
14144 14145
    virCgroupPtr group_vcpu = NULL;

14146
    for (i = 0; i < priv->nvcpupids; i++) {
14147 14148 14149 14150
        char *pos;
        unsigned long long tmp;
        int j;

14151
        if (virCgroupNewVcpu(priv->cgroup, i, false, &group_vcpu) < 0) {
14152 14153
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("error accessing cgroup cpuacct for vcpu"));
14154 14155 14156
            goto cleanup;
        }

14157
        if (virCgroupGetCpuacctPercpuUsage(group_vcpu, &buf) < 0)
14158 14159 14160 14161 14162
            goto cleanup;

        pos = buf;
        for (j = 0; j < num; j++) {
            if (virStrToLong_ull(pos, &pos, 10, &tmp) < 0) {
14163 14164
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("cpuacct parse error"));
14165 14166 14167 14168 14169 14170 14171 14172 14173 14174 14175 14176 14177 14178 14179 14180
                goto cleanup;
            }
            sum_cpu_time[j] += tmp;
        }

        virCgroupFree(&group_vcpu);
        VIR_FREE(buf);
    }

    ret = 0;
cleanup:
    virCgroupFree(&group_vcpu);
    VIR_FREE(buf);
    return ret;
}

14181
static int
14182
qemuDomainGetPercpuStats(virDomainObjPtr vm,
14183 14184 14185 14186 14187 14188
                         virTypedParameterPtr params,
                         unsigned int nparams,
                         int start_cpu,
                         unsigned int ncpus)
{
    int rv = -1;
14189
    int i, id, max_id;
14190 14191
    char *pos;
    char *buf = NULL;
14192 14193 14194 14195
    unsigned long long *sum_cpu_time = NULL;
    unsigned long long *sum_cpu_pos;
    unsigned int n = 0;
    qemuDomainObjPrivatePtr priv = vm->privateData;
14196 14197
    virTypedParameterPtr ent;
    int param_idx;
14198
    unsigned long long cpu_time;
14199 14200 14201

    /* return the number of supported params */
    if (nparams == 0 && ncpus != 0)
14202
        return QEMU_NB_PER_CPU_STAT_PARAM;
14203

14204 14205 14206
    /* To parse account file, we need to know how many cpus are present.  */
    max_id = nodeGetCPUCount();
    if (max_id < 0)
14207 14208 14209
        return rv;

    if (ncpus == 0) { /* returns max cpu ID */
14210
        rv = max_id;
14211 14212 14213 14214
        goto cleanup;
    }

    if (start_cpu > max_id) {
14215 14216 14217
        virReportError(VIR_ERR_INVALID_ARG,
                       _("start_cpu %d larger than maximum of %d"),
                       start_cpu, max_id);
14218 14219 14220 14221
        goto cleanup;
    }

    /* we get percpu cputime accounting info. */
14222
    if (virCgroupGetCpuacctPercpuUsage(priv->cgroup, &buf))
14223 14224
        goto cleanup;
    pos = buf;
14225
    memset(params, 0, nparams * ncpus);
14226

14227 14228 14229
    /* return percpu cputime in index 0 */
    param_idx = 0;

14230
    /* number of cpus to compute */
14231 14232 14233
    if (start_cpu >= max_id - ncpus)
        id = max_id - 1;
    else
14234
        id = start_cpu + ncpus - 1;
14235

14236
    for (i = 0; i <= id; i++) {
14237
        if (virStrToLong_ull(pos, &pos, 10, &cpu_time) < 0) {
14238
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
14239
                           _("cpuacct parse error"));
14240
            goto cleanup;
14241 14242
        } else {
            n++;
14243 14244 14245
        }
        if (i < start_cpu)
            continue;
14246
        ent = &params[(i - start_cpu) * nparams + param_idx];
E
Eric Blake 已提交
14247 14248 14249
        if (virTypedParameterAssign(ent, VIR_DOMAIN_CPU_STATS_CPUTIME,
                                    VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
            goto cleanup;
14250
    }
14251 14252 14253 14254 14255 14256 14257 14258 14259 14260 14261

    /* 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;
    }
14262
    if (getSumVcpuPercpuStats(vm, sum_cpu_time, n) < 0)
14263 14264 14265
        goto cleanup;

    sum_cpu_pos = sum_cpu_time;
14266
    for (i = 0; i <= id; i++) {
14267
        cpu_time = *(sum_cpu_pos++);
14268 14269 14270 14271 14272 14273 14274 14275 14276 14277
        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;
    }

14278 14279
    rv = param_idx + 1;
cleanup:
14280
    VIR_FREE(sum_cpu_time);
14281 14282 14283 14284 14285 14286 14287
    VIR_FREE(buf);
    return rv;
}


static int
qemuDomainGetCPUStats(virDomainPtr domain,
14288 14289 14290 14291 14292
                      virTypedParameterPtr params,
                      unsigned int nparams,
                      int start_cpu,
                      unsigned int ncpus,
                      unsigned int flags)
14293 14294 14295 14296
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    bool isActive;
14297
    qemuDomainObjPrivatePtr priv;
14298 14299 14300

    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

14301 14302
    if (!(vm = qemuDomObjFromDomain(domain)))
        return -1;
14303

14304 14305
    priv = vm->privateData;

14306 14307
    isActive = virDomainObjIsActive(vm);
    if (!isActive) {
14308 14309
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("domain is not running"));
14310 14311 14312
        goto cleanup;
    }

14313
    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) {
14314 14315
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cgroup CPUACCT controller is not mounted"));
14316 14317 14318 14319
        goto cleanup;
    }

    if (start_cpu == -1)
14320
        ret = qemuDomainGetTotalcpuStats(vm, params, nparams);
14321
    else
14322
        ret = qemuDomainGetPercpuStats(vm, params, nparams,
14323 14324 14325
                                       start_cpu, ncpus);
cleanup:
    if (vm)
14326
        virObjectUnlock(vm);
14327 14328 14329
    return ret;
}

14330 14331 14332 14333 14334 14335
static int
qemuDomainPMSuspendForDuration(virDomainPtr dom,
                               unsigned int target,
                               unsigned long long duration,
                               unsigned int flags)
{
14336
    virQEMUDriverPtr driver = dom->conn->privateData;
14337 14338 14339 14340 14341 14342 14343
    qemuDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

    if (duration) {
14344 14345
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Duration not supported. Use 0 for now"));
14346 14347 14348 14349 14350 14351
        return -1;
    }

    if (!(target == VIR_NODE_SUSPEND_TARGET_MEM ||
          target == VIR_NODE_SUSPEND_TARGET_DISK ||
          target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
14352 14353 14354
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Unknown suspend target: %u"),
                       target);
14355 14356 14357
        return -1;
    }

14358
    if (!(vm = qemuDomObjFromDomain(dom)))
14359 14360 14361 14362
        goto cleanup;

    priv = vm->privateData;

14363
    if (!virDomainObjIsActive(vm)) {
14364 14365
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
14366 14367 14368
        goto cleanup;
    }

14369
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_WAKEUP) &&
14370 14371
        (target == VIR_NODE_SUSPEND_TARGET_MEM ||
         target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
14372 14373 14374
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("Unable to suspend domain due to "
                         "missing system_wakeup monitor command"));
O
Osier Yang 已提交
14375
        goto cleanup;
14376 14377
    }

14378 14379 14380 14381 14382 14383 14384 14385 14386 14387 14388 14389 14390 14391 14392 14393 14394
    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;
        }
    }

14395
    if (priv->agentError) {
14396 14397 14398
        virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                       _("QEMU guest agent is not "
                         "available due to an error"));
14399 14400 14401 14402
        goto cleanup;
    }

    if (!priv->agent) {
14403 14404
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("QEMU guest agent is not configured"));
14405 14406 14407 14408 14409 14410 14411
        goto cleanup;
    }

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

    if (!virDomainObjIsActive(vm)) {
14412 14413
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
14414 14415 14416
        goto endjob;
    }

14417
    qemuDomainObjEnterAgent(vm);
14418
    ret = qemuAgentSuspend(priv->agent, target);
14419
    qemuDomainObjExitAgent(vm);
14420 14421 14422 14423 14424 14425 14426

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

cleanup:
    if (vm)
14427
        virObjectUnlock(vm);
14428 14429 14430
    return ret;
}

14431 14432 14433 14434
static int
qemuDomainPMWakeup(virDomainPtr dom,
                   unsigned int flags)
{
14435
    virQEMUDriverPtr driver = dom->conn->privateData;
14436 14437 14438 14439 14440 14441
    virDomainObjPtr vm;
    int ret = -1;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, -1);

14442
    if (!(vm = qemuDomObjFromDomain(dom)))
14443 14444 14445 14446 14447 14448
        goto cleanup;

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

    if (!virDomainObjIsActive(vm)) {
14449 14450
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
14451 14452 14453 14454 14455
        goto endjob;
    }

    priv = vm->privateData;

14456
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_WAKEUP)) {
14457 14458 14459
       virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                      _("Unable to wake up domain due to "
                        "missing system_wakeup monitor command"));
14460 14461 14462 14463 14464 14465 14466 14467 14468 14469 14470 14471 14472
       goto endjob;
    }

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

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

cleanup:
    if (vm)
14473
        virObjectUnlock(vm);
14474 14475 14476
    return ret;
}

14477 14478 14479 14480 14481
static int
qemuListAllDomains(virConnectPtr conn,
                   virDomainPtr **domains,
                   unsigned int flags)
{
14482
    virQEMUDriverPtr driver = conn->privateData;
14483 14484
    int ret = -1;

O
Osier Yang 已提交
14485
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
14486

14487
    ret = virDomainObjListExport(driver->domains, conn, domains, flags);
14488 14489 14490 14491

    return ret;
}

M
MATSUDA Daiki 已提交
14492
static char *
14493
qemuDomainAgentCommand(virDomainPtr domain,
M
MATSUDA Daiki 已提交
14494 14495 14496 14497
                       const char *cmd,
                       int timeout,
                       unsigned int flags)
{
14498
    virQEMUDriverPtr driver = domain->conn->privateData;
M
MATSUDA Daiki 已提交
14499 14500 14501 14502 14503 14504 14505
    virDomainObjPtr vm;
    int ret = -1;
    char *result = NULL;
    qemuDomainObjPrivatePtr priv;

    virCheckFlags(0, NULL);

14506
    if (!(vm = qemuDomObjFromDomain(domain)))
M
MATSUDA Daiki 已提交
14507 14508 14509 14510 14511 14512 14513 14514 14515 14516 14517
        goto cleanup;

    priv = vm->privateData;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    if (priv->agentError) {
14518 14519 14520
        virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s",
                       _("QEMU guest agent is not "
                         "available due to an error"));
M
MATSUDA Daiki 已提交
14521 14522 14523 14524 14525 14526 14527 14528 14529 14530 14531 14532 14533 14534 14535 14536 14537 14538
        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;
    }

14539
    qemuDomainObjEnterAgent(vm);
M
MATSUDA Daiki 已提交
14540
    ret = qemuAgentArbitraryCommand(priv->agent, cmd, &result, timeout);
14541
    qemuDomainObjExitAgent(vm);
M
MATSUDA Daiki 已提交
14542 14543 14544 14545 14546 14547 14548 14549 14550 14551 14552 14553 14554
    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)
14555
        virObjectUnlock(vm);
M
MATSUDA Daiki 已提交
14556 14557 14558
    return result;
}

M
Michal Privoznik 已提交
14559 14560 14561 14562 14563 14564
static int
qemuDomainFSTrim(virDomainPtr dom,
                 const char *mountPoint,
                 unsigned long long minimum,
                 unsigned int flags)
{
14565
    virQEMUDriverPtr driver = dom->conn->privateData;
M
Michal Privoznik 已提交
14566 14567 14568 14569 14570 14571 14572 14573 14574 14575 14576 14577 14578 14579 14580 14581 14582 14583 14584 14585 14586 14587 14588 14589 14590 14591 14592 14593 14594 14595 14596 14597 14598 14599 14600 14601 14602 14603 14604 14605 14606 14607 14608 14609 14610 14611
    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;
    }

14612
    qemuDomainObjEnterAgent(vm);
M
Michal Privoznik 已提交
14613
    ret = qemuAgentFSTrim(priv->agent, minimum);
14614
    qemuDomainObjExitAgent(vm);
M
Michal Privoznik 已提交
14615 14616 14617 14618 14619 14620 14621

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

cleanup:
    if (vm)
14622
        virObjectUnlock(vm);
M
Michal Privoznik 已提交
14623 14624 14625
    return ret;
}

14626
static virDriver qemuDriver = {
14627
    .no = VIR_DRV_QEMU,
14628
    .name = QEMU_DRIVER_NAME,
14629 14630 14631 14632 14633 14634 14635 14636
    .connectOpen = qemuOpen, /* 0.2.0 */
    .connectClose = qemuClose, /* 0.2.0 */
    .connectSupportsFeature = qemuSupportsFeature, /* 0.5.0 */
    .connectGetType = qemuGetType, /* 0.2.0 */
    .connectGetVersion = qemuGetVersion, /* 0.2.0 */
    .connectGetHostname = virGetHostname, /* 0.3.3 */
    .connectGetSysinfo = qemuGetSysinfo, /* 0.8.8 */
    .connectGetMaxVcpus = qemuGetMaxVCPUs, /* 0.2.1 */
14637
    .nodeGetInfo = nodeGetInfo, /* 0.2.0 */
14638 14639 14640 14641
    .connectGetCapabilities = qemuGetCapabilities, /* 0.2.1 */
    .connectListDomains = qemuListDomains, /* 0.2.0 */
    .connectNumOfDomains = qemuNumDomains, /* 0.2.0 */
    .connectListAllDomains = qemuListAllDomains, /* 0.9.13 */
14642 14643 14644 14645 14646 14647
    .domainCreateXML = qemuDomainCreate, /* 0.2.0 */
    .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 */
14648
    .domainShutdown = qemuDomainShutdown, /* 0.2.0 */
14649
    .domainShutdownFlags = qemuDomainShutdownFlags, /* 0.9.10 */
14650
    .domainReboot = qemuDomainReboot, /* 0.9.3 */
14651
    .domainReset = qemuDomainReset, /* 0.9.7 */
14652 14653
    .domainDestroy = qemuDomainDestroy, /* 0.2.0 */
    .domainDestroyFlags = qemuDomainDestroyFlags, /* 0.9.4 */
14654
    .domainGetOSType = qemuDomainGetOSType, /* 0.2.2 */
14655
    .domainGetMaxMemory = qemuDomainGetMaxMemory, /* 0.4.2 */
14656 14657 14658
    .domainSetMaxMemory = qemuDomainSetMaxMemory, /* 0.4.2 */
    .domainSetMemory = qemuDomainSetMemory, /* 0.4.2 */
    .domainSetMemoryFlags = qemuDomainSetMemoryFlags, /* 0.9.0 */
14659 14660 14661 14662
    .domainSetMemoryParameters = qemuDomainSetMemoryParameters, /* 0.8.5 */
    .domainGetMemoryParameters = qemuDomainGetMemoryParameters, /* 0.8.5 */
    .domainSetBlkioParameters = qemuDomainSetBlkioParameters, /* 0.9.0 */
    .domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */
14663
    .domainGetInfo = qemuDomainGetInfo, /* 0.2.0 */
14664
    .domainGetState = qemuDomainGetState, /* 0.9.2 */
14665
    .domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */
14666 14667
    .domainSave = qemuDomainSave, /* 0.2.0 */
    .domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */
14668
    .domainRestore = qemuDomainRestore, /* 0.2.0 */
14669
    .domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */
14670 14671
    .domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */
    .domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */
14672
    .domainCoreDump = qemuDomainCoreDump, /* 0.7.0 */
14673
    .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */
14674 14675
    .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */
    .domainSetVcpusFlags = qemuDomainSetVcpusFlags, /* 0.8.5 */
14676 14677 14678 14679 14680 14681 14682 14683 14684
    .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 已提交
14685
    .domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
14686
    .nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
14687
    .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */
14688 14689 14690 14691
    .connectDomainXMLFromNative = qemuDomainXMLFromNative, /* 0.6.4 */
    .connectDomainXMLToNative = qemuDomainXMLToNative, /* 0.6.4 */
    .connectListDefinedDomains = qemuListDefinedDomains, /* 0.2.0 */
    .connectNumOfDefinedDomains = qemuNumDefinedDomains, /* 0.2.0 */
14692 14693
    .domainCreate = qemuDomainStart, /* 0.2.0 */
    .domainCreateWithFlags = qemuDomainStartWithFlags, /* 0.8.2 */
14694 14695
    .domainDefineXML = qemuDomainDefine, /* 0.2.0 */
    .domainUndefine = qemuDomainUndefine, /* 0.2.0 */
14696
    .domainUndefineFlags = qemuDomainUndefineFlags, /* 0.9.4 */
14697 14698 14699 14700 14701
    .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 */
14702 14703
    .domainGetAutostart = qemuDomainGetAutostart, /* 0.2.1 */
    .domainSetAutostart = qemuDomainSetAutostart, /* 0.2.1 */
14704 14705
    .domainGetSchedulerType = qemuGetSchedulerType, /* 0.7.0 */
    .domainGetSchedulerParameters = qemuGetSchedulerParameters, /* 0.7.0 */
14706
    .domainGetSchedulerParametersFlags = qemuGetSchedulerParametersFlags, /* 0.9.2 */
14707
    .domainSetSchedulerParameters = qemuSetSchedulerParameters, /* 0.7.0 */
14708
    .domainSetSchedulerParametersFlags = qemuSetSchedulerParametersFlags, /* 0.9.2 */
14709
    .domainMigratePerform = qemuDomainMigratePerform, /* 0.5.0 */
14710
    .domainBlockResize = qemuDomainBlockResize, /* 0.9.8 */
14711 14712
    .domainBlockStats = qemuDomainBlockStats, /* 0.4.1 */
    .domainBlockStatsFlags = qemuDomainBlockStatsFlags, /* 0.9.5 */
14713 14714 14715 14716
    .domainInterfaceStats = qemuDomainInterfaceStats, /* 0.4.1 */
    .domainMemoryStats = qemuDomainMemoryStats, /* 0.7.5 */
    .domainBlockPeek = qemuDomainBlockPeek, /* 0.4.4 */
    .domainMemoryPeek = qemuDomainMemoryPeek, /* 0.4.4 */
14717
    .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
14718
    .nodeGetCPUStats = nodeGetCPUStats, /* 0.9.3 */
14719
    .nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.3 */
14720 14721
    .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.4.4 */
    .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.4.4 */
14722 14723
    .connectDomainEventRegister = qemuDomainEventRegister, /* 0.5.0 */
    .connectDomainEventDeregister = qemuDomainEventDeregister, /* 0.5.0 */
14724 14725 14726 14727 14728 14729
    .domainMigratePrepare2 = qemuDomainMigratePrepare2, /* 0.5.0 */
    .domainMigrateFinish2 = qemuDomainMigrateFinish2, /* 0.5.0 */
    .nodeDeviceDettach = qemuNodeDeviceDettach, /* 0.6.1 */
    .nodeDeviceReAttach = qemuNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = qemuNodeDeviceReset, /* 0.6.1 */
    .domainMigratePrepareTunnel = qemuDomainMigratePrepareTunnel, /* 0.7.2 */
14730 14731
    .connectIsEncrypted = qemuIsEncrypted, /* 0.7.3 */
    .connectIsSecure = qemuIsSecure, /* 0.7.3 */
14732 14733 14734
    .domainIsActive = qemuDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = qemuDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = qemuDomainIsUpdated, /* 0.8.6 */
14735 14736
    .connectCompareCPU = qemuCPUCompare, /* 0.7.5 */
    .connectBaselineCPU = qemuCPUBaseline, /* 0.7.7 */
14737
    .domainGetJobInfo = qemuDomainGetJobInfo, /* 0.7.7 */
14738
    .domainGetJobStats = qemuDomainGetJobStats, /* 1.0.3 */
14739 14740
    .domainAbortJob = qemuDomainAbortJob, /* 0.7.7 */
    .domainMigrateSetMaxDowntime = qemuDomainMigrateSetMaxDowntime, /* 0.8.0 */
14741 14742
    .domainMigrateGetCompressionCache = qemuDomainMigrateGetCompressionCache, /* 1.0.3 */
    .domainMigrateSetCompressionCache = qemuDomainMigrateSetCompressionCache, /* 1.0.3 */
14743
    .domainMigrateSetMaxSpeed = qemuDomainMigrateSetMaxSpeed, /* 0.9.0 */
14744
    .domainMigrateGetMaxSpeed = qemuDomainMigrateGetMaxSpeed, /* 0.9.5 */
14745 14746
    .connectDomainEventRegisterAny = qemuDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = qemuDomainEventDeregisterAny, /* 0.8.0 */
14747 14748 14749 14750 14751 14752 14753
    .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 */
14754
    .domainListAllSnapshots = qemuDomainListAllSnapshots, /* 0.9.13 */
14755 14756
    .domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */
    .domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */
14757
    .domainSnapshotListAllChildren = qemuDomainSnapshotListAllChildren, /* 0.9.13 */
14758 14759
    .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */
    .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */
14760
    .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */
14761
    .domainSnapshotCurrent = qemuDomainSnapshotCurrent, /* 0.8.0 */
14762 14763
    .domainSnapshotIsCurrent = qemuDomainSnapshotIsCurrent, /* 0.9.13 */
    .domainSnapshotHasMetadata = qemuDomainSnapshotHasMetadata, /* 0.9.13 */
14764 14765
    .domainRevertToSnapshot = qemuDomainRevertToSnapshot, /* 0.8.0 */
    .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
14766 14767 14768
    .domainQemuMonitorCommand = qemuDomainMonitorCommand, /* 0.8.3 */
    .domainQemuAttach = qemuDomainAttach, /* 0.9.4 */
    .domainQemuAgentCommand = qemuDomainAgentCommand, /* 0.10.0 */
14769
    .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
14770
    .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
14771
    .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
14772 14773 14774 14775 14776 14777
    .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 */
14778
    .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
14779 14780 14781 14782
    .domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
    .domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
    .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
    .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
14783
    .domainBlockRebase = qemuDomainBlockRebase, /* 0.9.10 */
14784
    .domainBlockCommit = qemuDomainBlockCommit, /* 1.0.0 */
14785
    .connectIsAlive = qemuIsAlive, /* 0.9.8 */
14786
    .nodeSuspendForDuration = nodeSuspendForDuration, /* 0.9.8 */
14787 14788
    .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
    .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
14789 14790
    .domainSetNumaParameters = qemuDomainSetNumaParameters, /* 0.9.9 */
    .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
14791 14792
    .domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
    .domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
14793
    .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
14794 14795
    .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */
    .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */
14796
    .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
14797
    .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
14798
    .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
14799 14800
    .nodeGetMemoryParameters = nodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = nodeSetMemoryParameters, /* 0.10.2 */
14801
    .nodeGetCPUMap = nodeGetCPUMap, /* 1.0.0 */
M
Michal Privoznik 已提交
14802
    .domainFSTrim = qemuDomainFSTrim, /* 1.0.1 */
14803
    .domainOpenChannel = qemuDomainOpenChannel, /* 1.0.2 */
14804 14805 14806
};


14807
static virStateDriver qemuStateDriver = {
14808
    .name = "QEMU",
14809 14810 14811 14812
    .stateInitialize = qemuStartup,
    .stateCleanup = qemuShutdown,
    .stateReload = qemuReload,
    .stateStop = qemuStop,
14813
};
14814

14815
int qemuRegister(void) {
14816 14817 14818 14819
    virRegisterDriver(&qemuDriver);
    virRegisterStateDriver(&qemuStateDriver);
    return 0;
}