~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages

« back to all changes in this revision

Viewing changes to .pc/ubuntu/9024-qemu-allow-snapshotting-of-sheepdog-and-rbd-disks.patch/src/qemu/qemu_driver.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-13 15:44:12 UTC
  • mfrom: (1.2.13)
  • Revision ID: package-import@ubuntu.com-20120513154412-fgmn5sxqdzgnzlx3
Tags: 0.9.12-0ubuntu1
* New upstream version:
  * Synchronize with debian packaging:
    - debian/control: Update build depends.
    - debian/libvirt-bin.postrm: Cleanup /var/log/libvirt
      on purge.
    - Bump standards verson (no changes).
    - debian/patches/Don-t-fail-if-we-can-t-setup-avahi.patch: Added
  * Dropped patches:
    - debian/patches/Debianize-libvirt-guests.patch
    - debian/patches/rewrite-lxc-controller-eof-handling-yet-again
    - debian/patches/ubuntu/libnl13.patch
    - debian/patches/ubuntu/fix-lxc-startup-error.patch
    - debian/patches/ubuntu/fix-bridge-fd.patch
    - debian/patches/ubuntu/skip-labelling-network-disks.patch
    - debian/patches/ubuntu/xen-xend-shutdown-detection.patch
    - debian/patches/ubuntu/xen-config-no-vfb-for-hvm.patch
    - debian/patches/debian/Disable-daemon-start-test.patch
    - debian/patches/debian/Disable-gnulib-s-test-nonplocking-pipe.sh.patch
    - debian/patches/ubuntu/9006-default-config-test-case.patch
    - debian/patches/fix-block-migration.patch
    - debian/patches/ubuntu/9022-qemu-unescape-HMP-commands-before-converting-them-to.patch
    - debian/patches/ubuntu/9023-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/9024-qemu-allow-snapshotting-of-sheepdog-and-rbd-disks.patch
    - debian/patches/9025-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/arm-gcc-workaround.patch
  * Rediffed:
    - debian/patches/Allow-libvirt-group-to-access-the-socket.patch
    - debian/patches/Disable-failing-virnetsockettest.patch
    - debian/patches/dnsmasq-as-priv-user
    - debian/patches/9002-better_default_uri_virsh.patch
  * debian/control: Add libnl-route-3-dev ass a build depends.
  * debian/patches/libnl3-build-fix.patch: Fix build with libnl3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * qemu_driver.c: core driver methods for managing qemu guests
3
 
 *
4
 
 * Copyright (C) 2006-2011 Red Hat, Inc.
5
 
 * Copyright (C) 2006 Daniel P. Berrange
6
 
 *
7
 
 * This library is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU Lesser General Public
9
 
 * License as published by the Free Software Foundation; either
10
 
 * version 2.1 of the License, or (at your option) any later version.
11
 
 *
12
 
 * This library is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * Lesser General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this library; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
20
 
 *
21
 
 * Author: Daniel P. Berrange <berrange@redhat.com>
22
 
 */
23
 
 
24
 
#include <config.h>
25
 
 
26
 
#include <sys/types.h>
27
 
#include <sys/poll.h>
28
 
#include <sys/time.h>
29
 
#include <dirent.h>
30
 
#include <limits.h>
31
 
#include <string.h>
32
 
#include <stdio.h>
33
 
#include <stdarg.h>
34
 
#include <stdlib.h>
35
 
#include <unistd.h>
36
 
#include <errno.h>
37
 
#include <sys/utsname.h>
38
 
#include <sys/stat.h>
39
 
#include <fcntl.h>
40
 
#include <signal.h>
41
 
#include <paths.h>
42
 
#include <stdio.h>
43
 
#include <sys/wait.h>
44
 
#include <sys/ioctl.h>
45
 
#include <sys/un.h>
46
 
#include <byteswap.h>
47
 
 
48
 
 
49
 
#include "qemu_driver.h"
50
 
#include "qemu_conf.h"
51
 
#include "qemu_capabilities.h"
52
 
#include "qemu_command.h"
53
 
#include "qemu_cgroup.h"
54
 
#include "qemu_hostdev.h"
55
 
#include "qemu_hotplug.h"
56
 
#include "qemu_monitor.h"
57
 
#include "qemu_bridge_filter.h"
58
 
#include "qemu_process.h"
59
 
#include "qemu_migration.h"
60
 
 
61
 
#include "virterror_internal.h"
62
 
#include "logging.h"
63
 
#include "datatypes.h"
64
 
#include "buf.h"
65
 
#include "util.h"
66
 
#include "nodeinfo.h"
67
 
#include "stats_linux.h"
68
 
#include "capabilities.h"
69
 
#include "memory.h"
70
 
#include "uuid.h"
71
 
#include "domain_conf.h"
72
 
#include "domain_audit.h"
73
 
#include "node_device_conf.h"
74
 
#include "pci.h"
75
 
#include "hostusb.h"
76
 
#include "processinfo.h"
77
 
#include "libvirt_internal.h"
78
 
#include "xml.h"
79
 
#include "cpu/cpu.h"
80
 
#include "sysinfo.h"
81
 
#include "domain_nwfilter.h"
82
 
#include "hooks.h"
83
 
#include "storage_file.h"
84
 
#include "virfile.h"
85
 
#include "fdstream.h"
86
 
#include "configmake.h"
87
 
#include "threadpool.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
 
 
94
 
#define VIR_FROM_THIS VIR_FROM_QEMU
95
 
 
96
 
#define QEMU_NB_MEM_PARAM  3
97
 
 
98
 
#define QEMU_NB_BLOCK_IO_TUNE_PARAM  6
99
 
 
100
 
#if HAVE_LINUX_KVM_H
101
 
# include <linux/kvm.h>
102
 
#endif
103
 
 
104
 
/* device for kvm ioctls */
105
 
#define KVM_DEVICE "/dev/kvm"
106
 
 
107
 
/* add definitions missing in older linux/kvm.h */
108
 
#ifndef KVMIO
109
 
# define KVMIO 0xAE
110
 
#endif
111
 
#ifndef KVM_CHECK_EXTENSION
112
 
# define KVM_CHECK_EXTENSION       _IO(KVMIO,   0x03)
113
 
#endif
114
 
#ifndef KVM_CAP_NR_VCPUS
115
 
# define KVM_CAP_NR_VCPUS 9       /* returns max vcpus per vm */
116
 
#endif
117
 
 
118
 
#define QEMU_NB_BLKIO_PARAM  2
119
 
 
120
 
static void processWatchdogEvent(void *data, void *opaque);
121
 
 
122
 
static int qemudShutdown(void);
123
 
 
124
 
static int qemuDomainObjStart(virConnectPtr conn,
125
 
                              struct qemud_driver *driver,
126
 
                              virDomainObjPtr vm,
127
 
                              unsigned int flags);
128
 
 
129
 
static int qemudDomainGetMaxVcpus(virDomainPtr dom);
130
 
 
131
 
struct qemud_driver *qemu_driver = NULL;
132
 
 
133
 
 
134
 
struct qemuAutostartData {
135
 
    struct qemud_driver *driver;
136
 
    virConnectPtr conn;
137
 
};
138
 
 
139
 
static void
140
 
qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
141
 
                    void *opaque)
142
 
{
143
 
    virDomainObjPtr vm = payload;
144
 
    struct qemuAutostartData *data = opaque;
145
 
    virErrorPtr err;
146
 
    int flags = 0;
147
 
 
148
 
    if (data->driver->autoStartBypassCache)
149
 
        flags |= VIR_DOMAIN_START_BYPASS_CACHE;
150
 
 
151
 
    virDomainObjLock(vm);
152
 
    virResetLastError();
153
 
    if (vm->autostart &&
154
 
        !virDomainObjIsActive(vm)) {
155
 
        if (qemuDomainObjBeginJobWithDriver(data->driver, vm,
156
 
                                            QEMU_JOB_MODIFY) < 0) {
157
 
            err = virGetLastError();
158
 
            VIR_ERROR(_("Failed to start job on VM '%s': %s"),
159
 
                      vm->def->name,
160
 
                      err ? err->message : _("unknown error"));
161
 
            goto cleanup;
162
 
        }
163
 
 
164
 
        if (qemuDomainObjStart(data->conn, data->driver, vm, flags) < 0) {
165
 
            err = virGetLastError();
166
 
            VIR_ERROR(_("Failed to autostart VM '%s': %s"),
167
 
                      vm->def->name,
168
 
                      err ? err->message : _("unknown error"));
169
 
        }
170
 
 
171
 
        if (qemuDomainObjEndJob(data->driver, vm) == 0)
172
 
            vm = NULL;
173
 
    }
174
 
 
175
 
cleanup:
176
 
    if (vm)
177
 
        virDomainObjUnlock(vm);
178
 
}
179
 
 
180
 
 
181
 
static void
182
 
qemuAutostartDomains(struct qemud_driver *driver)
183
 
{
184
 
    /* XXX: Figure out a better way todo this. The domain
185
 
     * startup code needs a connection handle in order
186
 
     * to lookup the bridge associated with a virtual
187
 
     * network
188
 
     */
189
 
    virConnectPtr conn = virConnectOpen(driver->privileged ?
190
 
                                        "qemu:///system" :
191
 
                                        "qemu:///session");
192
 
    /* Ignoring NULL conn which is mostly harmless here */
193
 
    struct qemuAutostartData data = { driver, conn };
194
 
 
195
 
    qemuDriverLock(driver);
196
 
    virHashForEach(driver->domains.objs, qemuAutostartDomain, &data);
197
 
    qemuDriverUnlock(driver);
198
 
 
199
 
    if (conn)
200
 
        virConnectClose(conn);
201
 
}
202
 
 
203
 
static int
204
 
qemuSecurityInit(struct qemud_driver *driver)
205
 
{
206
 
    virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName,
207
 
                                                      driver->allowDiskFormatProbing);
208
 
    if (!mgr)
209
 
        goto error;
210
 
 
211
 
    if (driver->privileged) {
212
 
        virSecurityManagerPtr dac = virSecurityManagerNewDAC(driver->user,
213
 
                                                             driver->group,
214
 
                                                             driver->allowDiskFormatProbing,
215
 
                                                             driver->dynamicOwnership);
216
 
        if (!dac)
217
 
            goto error;
218
 
 
219
 
        if (!(driver->securityManager = virSecurityManagerNewStack(mgr,
220
 
                                                                   dac))) {
221
 
 
222
 
            virSecurityManagerFree(dac);
223
 
            goto error;
224
 
        }
225
 
    } else {
226
 
        driver->securityManager = mgr;
227
 
    }
228
 
 
229
 
    return 0;
230
 
 
231
 
error:
232
 
    VIR_ERROR(_("Failed to initialize security drivers"));
233
 
    virSecurityManagerFree(mgr);
234
 
    return -1;
235
 
}
236
 
 
237
 
 
238
 
static virCapsPtr
239
 
qemuCreateCapabilities(virCapsPtr oldcaps,
240
 
                       struct qemud_driver *driver)
241
 
{
242
 
    virCapsPtr caps;
243
 
 
244
 
    /* Basic host arch / guest machine capabilities */
245
 
    if (!(caps = qemuCapsInit(oldcaps))) {
246
 
        virReportOOMError();
247
 
        return NULL;
248
 
    }
249
 
 
250
 
    if (driver->allowDiskFormatProbing) {
251
 
        caps->defaultDiskDriverName = NULL;
252
 
        caps->defaultDiskDriverType = NULL;
253
 
    } else {
254
 
        caps->defaultDiskDriverName = "qemu";
255
 
        caps->defaultDiskDriverType = "raw";
256
 
    }
257
 
 
258
 
    qemuDomainSetPrivateDataHooks(caps);
259
 
    qemuDomainSetNamespaceHooks(caps);
260
 
 
261
 
    if (virGetHostUUID(caps->host.host_uuid)) {
262
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
263
 
                         "%s", _("cannot get the host uuid"));
264
 
        goto err_exit;
265
 
    }
266
 
 
267
 
    /* Security driver data */
268
 
    const char *doi, *model;
269
 
 
270
 
    doi = virSecurityManagerGetDOI(driver->securityManager);
271
 
    model = virSecurityManagerGetModel(driver->securityManager);
272
 
    if (STRNEQ(model, "none")) {
273
 
        if (!(caps->host.secModel.model = strdup(model)))
274
 
            goto no_memory;
275
 
        if (!(caps->host.secModel.doi = strdup(doi)))
276
 
            goto no_memory;
277
 
    }
278
 
 
279
 
    VIR_DEBUG("Initialized caps for security driver \"%s\" with "
280
 
              "DOI \"%s\"", model, doi);
281
 
 
282
 
    return caps;
283
 
 
284
 
no_memory:
285
 
    virReportOOMError();
286
 
err_exit:
287
 
    virCapabilitiesFree(caps);
288
 
    return NULL;
289
 
}
290
 
 
291
 
static void qemuDomainSnapshotLoad(void *payload,
292
 
                                   const void *name ATTRIBUTE_UNUSED,
293
 
                                   void *data)
294
 
{
295
 
    virDomainObjPtr vm = (virDomainObjPtr)payload;
296
 
    char *baseDir = (char *)data;
297
 
    char *snapDir = NULL;
298
 
    DIR *dir = NULL;
299
 
    struct dirent *entry;
300
 
    char *xmlStr;
301
 
    int ret;
302
 
    char *fullpath;
303
 
    virDomainSnapshotDefPtr def = NULL;
304
 
    virDomainSnapshotObjPtr snap = NULL;
305
 
    virDomainSnapshotObjPtr current = NULL;
306
 
    char ebuf[1024];
307
 
    unsigned int flags = (VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE |
308
 
                          VIR_DOMAIN_SNAPSHOT_PARSE_DISKS |
309
 
                          VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL);
310
 
 
311
 
    virDomainObjLock(vm);
312
 
    if (virAsprintf(&snapDir, "%s/%s", baseDir, vm->def->name) < 0) {
313
 
        VIR_ERROR(_("Failed to allocate memory for snapshot directory for domain %s"),
314
 
                   vm->def->name);
315
 
        goto cleanup;
316
 
    }
317
 
 
318
 
    VIR_INFO("Scanning for snapshots for domain %s in %s", vm->def->name,
319
 
             snapDir);
320
 
 
321
 
    if (!(dir = opendir(snapDir))) {
322
 
        if (errno != ENOENT)
323
 
            VIR_ERROR(_("Failed to open snapshot directory %s for domain %s: %s"),
324
 
                      snapDir, vm->def->name,
325
 
                      virStrerror(errno, ebuf, sizeof(ebuf)));
326
 
        goto cleanup;
327
 
    }
328
 
 
329
 
    while ((entry = readdir(dir))) {
330
 
        if (entry->d_name[0] == '.')
331
 
            continue;
332
 
 
333
 
        /* NB: ignoring errors, so one malformed config doesn't
334
 
           kill the whole process */
335
 
        VIR_INFO("Loading snapshot file '%s'", entry->d_name);
336
 
 
337
 
        if (virAsprintf(&fullpath, "%s/%s", snapDir, entry->d_name) < 0) {
338
 
            VIR_ERROR(_("Failed to allocate memory for path"));
339
 
            continue;
340
 
        }
341
 
 
342
 
        ret = virFileReadAll(fullpath, 1024*1024*1, &xmlStr);
343
 
        if (ret < 0) {
344
 
            /* Nothing we can do here, skip this one */
345
 
            VIR_ERROR(_("Failed to read snapshot file %s: %s"), fullpath,
346
 
                      virStrerror(errno, ebuf, sizeof(ebuf)));
347
 
            VIR_FREE(fullpath);
348
 
            continue;
349
 
        }
350
 
 
351
 
        def = virDomainSnapshotDefParseString(xmlStr, qemu_driver->caps,
352
 
                                              QEMU_EXPECTED_VIRT_TYPES,
353
 
                                              flags);
354
 
        if (def == NULL) {
355
 
            /* Nothing we can do here, skip this one */
356
 
            VIR_ERROR(_("Failed to parse snapshot XML from file '%s'"),
357
 
                      fullpath);
358
 
            VIR_FREE(fullpath);
359
 
            VIR_FREE(xmlStr);
360
 
            continue;
361
 
        }
362
 
 
363
 
        snap = virDomainSnapshotAssignDef(&vm->snapshots, def);
364
 
        if (snap == NULL) {
365
 
            virDomainSnapshotDefFree(def);
366
 
        } else if (snap->def->current) {
367
 
            current = snap;
368
 
            if (!vm->current_snapshot)
369
 
                vm->current_snapshot = snap;
370
 
        }
371
 
 
372
 
        VIR_FREE(fullpath);
373
 
        VIR_FREE(xmlStr);
374
 
    }
375
 
 
376
 
    if (vm->current_snapshot != current) {
377
 
        VIR_ERROR(_("Too many snapshots claiming to be current for domain %s"),
378
 
                  vm->def->name);
379
 
        vm->current_snapshot = NULL;
380
 
    }
381
 
 
382
 
    if (virDomainSnapshotUpdateRelations(&vm->snapshots) < 0)
383
 
        VIR_ERROR(_("Snapshots have inconsistent relations for domain %s"),
384
 
                  vm->def->name);
385
 
 
386
 
    /* FIXME: qemu keeps internal track of snapshots.  We can get access
387
 
     * to this info via the "info snapshots" monitor command for running
388
 
     * domains, or via "qemu-img snapshot -l" for shutoff domains.  It would
389
 
     * be nice to update our internal state based on that, but there is a
390
 
     * a problem.  qemu doesn't track all of the same metadata that we do.
391
 
     * In particular we wouldn't be able to fill in the <parent>, which is
392
 
     * pretty important in our metadata.
393
 
     */
394
 
 
395
 
    virResetLastError();
396
 
 
397
 
cleanup:
398
 
    if (dir)
399
 
        closedir(dir);
400
 
    VIR_FREE(snapDir);
401
 
    virDomainObjUnlock(vm);
402
 
}
403
 
 
404
 
/**
405
 
 * qemudStartup:
406
 
 *
407
 
 * Initialization function for the QEmu daemon
408
 
 */
409
 
static int
410
 
qemudStartup(int privileged) {
411
 
    char *base = NULL;
412
 
    char *driverConf = NULL;
413
 
    int rc;
414
 
    virConnectPtr conn = NULL;
415
 
 
416
 
    if (VIR_ALLOC(qemu_driver) < 0)
417
 
        return -1;
418
 
 
419
 
    if (virMutexInit(&qemu_driver->lock) < 0) {
420
 
        VIR_ERROR(_("cannot initialize mutex"));
421
 
        VIR_FREE(qemu_driver);
422
 
        return -1;
423
 
    }
424
 
    qemuDriverLock(qemu_driver);
425
 
    qemu_driver->privileged = privileged;
426
 
 
427
 
    /* Don't have a dom0 so start from 1 */
428
 
    qemu_driver->nextvmid = 1;
429
 
 
430
 
    if (virDomainObjListInit(&qemu_driver->domains) < 0)
431
 
        goto out_of_memory;
432
 
 
433
 
    /* Init domain events */
434
 
    qemu_driver->domainEventState = virDomainEventStateNew(qemuDomainEventFlush,
435
 
                                                           qemu_driver,
436
 
                                                           NULL,
437
 
                                                           true);
438
 
    if (!qemu_driver->domainEventState)
439
 
        goto error;
440
 
 
441
 
    /* Allocate bitmap for vnc port reservation */
442
 
    if ((qemu_driver->reservedVNCPorts =
443
 
         virBitmapAlloc(QEMU_VNC_PORT_MAX - QEMU_VNC_PORT_MIN)) == NULL)
444
 
        goto out_of_memory;
445
 
 
446
 
    /* read the host sysinfo */
447
 
    if (privileged)
448
 
        qemu_driver->hostsysinfo = virSysinfoRead();
449
 
 
450
 
    if (privileged) {
451
 
        if (virAsprintf(&qemu_driver->logDir,
452
 
                        "%s/log/libvirt/qemu", LOCALSTATEDIR) == -1)
453
 
            goto out_of_memory;
454
 
 
455
 
        if ((base = strdup (SYSCONFDIR "/libvirt")) == NULL)
456
 
            goto out_of_memory;
457
 
 
458
 
        if (virAsprintf(&qemu_driver->stateDir,
459
 
                      "%s/run/libvirt/qemu", LOCALSTATEDIR) == -1)
460
 
            goto out_of_memory;
461
 
 
462
 
        if (virAsprintf(&qemu_driver->libDir,
463
 
                      "%s/lib/libvirt/qemu", LOCALSTATEDIR) == -1)
464
 
            goto out_of_memory;
465
 
 
466
 
        if (virAsprintf(&qemu_driver->cacheDir,
467
 
                      "%s/cache/libvirt/qemu", LOCALSTATEDIR) == -1)
468
 
            goto out_of_memory;
469
 
        if (virAsprintf(&qemu_driver->saveDir,
470
 
                      "%s/lib/libvirt/qemu/save", LOCALSTATEDIR) == -1)
471
 
            goto out_of_memory;
472
 
        if (virAsprintf(&qemu_driver->snapshotDir,
473
 
                        "%s/lib/libvirt/qemu/snapshot", LOCALSTATEDIR) == -1)
474
 
            goto out_of_memory;
475
 
        if (virAsprintf(&qemu_driver->autoDumpPath,
476
 
                        "%s/lib/libvirt/qemu/dump", LOCALSTATEDIR) == -1)
477
 
            goto out_of_memory;
478
 
    } else {
479
 
        uid_t uid = geteuid();
480
 
        char *userdir = virGetUserDirectory(uid);
481
 
        if (!userdir)
482
 
            goto error;
483
 
 
484
 
        if (virAsprintf(&qemu_driver->logDir,
485
 
                        "%s/.libvirt/qemu/log", userdir) == -1) {
486
 
            VIR_FREE(userdir);
487
 
            goto out_of_memory;
488
 
        }
489
 
 
490
 
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
491
 
            VIR_FREE(userdir);
492
 
            goto out_of_memory;
493
 
        }
494
 
        VIR_FREE(userdir);
495
 
 
496
 
        if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", base) == -1)
497
 
            goto out_of_memory;
498
 
        if (virAsprintf(&qemu_driver->libDir, "%s/qemu/lib", base) == -1)
499
 
            goto out_of_memory;
500
 
        if (virAsprintf(&qemu_driver->cacheDir, "%s/qemu/cache", base) == -1)
501
 
            goto out_of_memory;
502
 
        if (virAsprintf(&qemu_driver->saveDir, "%s/qemu/save", base) == -1)
503
 
            goto out_of_memory;
504
 
        if (virAsprintf(&qemu_driver->snapshotDir, "%s/qemu/snapshot", base) == -1)
505
 
            goto out_of_memory;
506
 
        if (virAsprintf(&qemu_driver->autoDumpPath, "%s/qemu/dump", base) == -1)
507
 
            goto out_of_memory;
508
 
    }
509
 
 
510
 
    if (virFileMakePath(qemu_driver->stateDir) < 0) {
511
 
        char ebuf[1024];
512
 
        VIR_ERROR(_("Failed to create state dir '%s': %s"),
513
 
                  qemu_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
514
 
        goto error;
515
 
    }
516
 
    if (virFileMakePath(qemu_driver->libDir) < 0) {
517
 
        char ebuf[1024];
518
 
        VIR_ERROR(_("Failed to create lib dir '%s': %s"),
519
 
                  qemu_driver->libDir, virStrerror(errno, ebuf, sizeof ebuf));
520
 
        goto error;
521
 
    }
522
 
    if (virFileMakePath(qemu_driver->cacheDir) < 0) {
523
 
        char ebuf[1024];
524
 
        VIR_ERROR(_("Failed to create cache dir '%s': %s"),
525
 
                  qemu_driver->cacheDir, virStrerror(errno, ebuf, sizeof ebuf));
526
 
        goto error;
527
 
    }
528
 
    if (virFileMakePath(qemu_driver->saveDir) < 0) {
529
 
        char ebuf[1024];
530
 
        VIR_ERROR(_("Failed to create save dir '%s': %s"),
531
 
                  qemu_driver->saveDir, virStrerror(errno, ebuf, sizeof ebuf));
532
 
        goto error;
533
 
    }
534
 
    if (virFileMakePath(qemu_driver->snapshotDir) < 0) {
535
 
        char ebuf[1024];
536
 
        VIR_ERROR(_("Failed to create save dir '%s': %s"),
537
 
                  qemu_driver->snapshotDir, virStrerror(errno, ebuf, sizeof ebuf));
538
 
        goto error;
539
 
    }
540
 
    if (virFileMakePath(qemu_driver->autoDumpPath) < 0) {
541
 
        char ebuf[1024];
542
 
        VIR_ERROR(_("Failed to create dump dir '%s': %s"),
543
 
                  qemu_driver->autoDumpPath, virStrerror(errno, ebuf, sizeof ebuf));
544
 
        goto error;
545
 
    }
546
 
 
547
 
    /* Configuration paths are either ~/.libvirt/qemu/... (session) or
548
 
     * /etc/libvirt/qemu/... (system).
549
 
     */
550
 
    if (virAsprintf(&driverConf, "%s/qemu.conf", base) < 0 ||
551
 
        virAsprintf(&qemu_driver->configDir, "%s/qemu", base) < 0 ||
552
 
        virAsprintf(&qemu_driver->autostartDir, "%s/qemu/autostart", base) < 0)
553
 
        goto out_of_memory;
554
 
 
555
 
    VIR_FREE(base);
556
 
 
557
 
    rc = virCgroupForDriver("qemu", &qemu_driver->cgroup, privileged, 1);
558
 
    if (rc < 0) {
559
 
        char buf[1024];
560
 
        VIR_INFO("Unable to create cgroup for driver: %s",
561
 
                 virStrerror(-rc, buf, sizeof(buf)));
562
 
    }
563
 
 
564
 
    if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
565
 
        goto error;
566
 
    }
567
 
    VIR_FREE(driverConf);
568
 
 
569
 
    /* We should always at least have the 'nop' manager, so
570
 
     * NULLs here are a fatal error
571
 
     */
572
 
    if (!qemu_driver->lockManager) {
573
 
        VIR_ERROR(_("Missing lock manager implementation"));
574
 
        goto error;
575
 
    }
576
 
 
577
 
    if (qemuSecurityInit(qemu_driver) < 0)
578
 
        goto error;
579
 
 
580
 
    if ((qemu_driver->caps = qemuCreateCapabilities(NULL,
581
 
                                                    qemu_driver)) == NULL)
582
 
        goto error;
583
 
 
584
 
    if ((qemu_driver->activePciHostdevs = pciDeviceListNew()) == NULL)
585
 
        goto error;
586
 
 
587
 
    if (privileged) {
588
 
        if (chown(qemu_driver->libDir, qemu_driver->user, qemu_driver->group) < 0) {
589
 
            virReportSystemError(errno,
590
 
                                 _("unable to set ownership of '%s' to user %d:%d"),
591
 
                                 qemu_driver->libDir, qemu_driver->user, qemu_driver->group);
592
 
            goto error;
593
 
        }
594
 
        if (chown(qemu_driver->cacheDir, qemu_driver->user, qemu_driver->group) < 0) {
595
 
            virReportSystemError(errno,
596
 
                                 _("unable to set ownership of '%s' to %d:%d"),
597
 
                                 qemu_driver->cacheDir, qemu_driver->user, qemu_driver->group);
598
 
            goto error;
599
 
        }
600
 
        if (chown(qemu_driver->saveDir, qemu_driver->user, qemu_driver->group) < 0) {
601
 
            virReportSystemError(errno,
602
 
                                 _("unable to set ownership of '%s' to %d:%d"),
603
 
                                 qemu_driver->saveDir, qemu_driver->user, qemu_driver->group);
604
 
            goto error;
605
 
        }
606
 
        if (chown(qemu_driver->snapshotDir, qemu_driver->user, qemu_driver->group) < 0) {
607
 
            virReportSystemError(errno,
608
 
                                 _("unable to set ownership of '%s' to %d:%d"),
609
 
                                 qemu_driver->snapshotDir, qemu_driver->user, qemu_driver->group);
610
 
            goto error;
611
 
        }
612
 
    }
613
 
 
614
 
    /* If hugetlbfs is present, then we need to create a sub-directory within
615
 
     * it, since we can't assume the root mount point has permissions that
616
 
     * will let our spawned QEMU instances use it.
617
 
     *
618
 
     * NB the check for '/', since user may config "" to disable hugepages
619
 
     * even when mounted
620
 
     */
621
 
    if (qemu_driver->hugetlbfs_mount &&
622
 
        qemu_driver->hugetlbfs_mount[0] == '/') {
623
 
        char *mempath = NULL;
624
 
        if (virAsprintf(&mempath, "%s/libvirt/qemu", qemu_driver->hugetlbfs_mount) < 0)
625
 
            goto out_of_memory;
626
 
 
627
 
        if (virFileMakePath(mempath) < 0) {
628
 
            virReportSystemError(errno,
629
 
                                 _("unable to create hugepage path %s"), mempath);
630
 
            VIR_FREE(mempath);
631
 
            goto error;
632
 
        }
633
 
        if (qemu_driver->privileged &&
634
 
            chown(mempath, qemu_driver->user, qemu_driver->group) < 0) {
635
 
            virReportSystemError(errno,
636
 
                                 _("unable to set ownership on %s to %d:%d"),
637
 
                                 mempath, qemu_driver->user, qemu_driver->group);
638
 
            VIR_FREE(mempath);
639
 
            goto error;
640
 
        }
641
 
 
642
 
        qemu_driver->hugepage_path = mempath;
643
 
    }
644
 
 
645
 
    if (qemuProcessAutoDestroyInit(qemu_driver) < 0)
646
 
        goto error;
647
 
 
648
 
    /* Get all the running persistent or transient configs first */
649
 
    if (virDomainLoadAllConfigs(qemu_driver->caps,
650
 
                                &qemu_driver->domains,
651
 
                                qemu_driver->stateDir,
652
 
                                NULL,
653
 
                                1, QEMU_EXPECTED_VIRT_TYPES,
654
 
                                NULL, NULL) < 0)
655
 
        goto error;
656
 
 
657
 
    conn = virConnectOpen(qemu_driver->privileged ?
658
 
                          "qemu:///system" :
659
 
                          "qemu:///session");
660
 
 
661
 
    qemuProcessReconnectAll(conn, qemu_driver);
662
 
 
663
 
    /* Then inactive persistent configs */
664
 
    if (virDomainLoadAllConfigs(qemu_driver->caps,
665
 
                                &qemu_driver->domains,
666
 
                                qemu_driver->configDir,
667
 
                                qemu_driver->autostartDir,
668
 
                                0, QEMU_EXPECTED_VIRT_TYPES,
669
 
                                NULL, NULL) < 0)
670
 
        goto error;
671
 
 
672
 
 
673
 
    virHashForEach(qemu_driver->domains.objs, qemuDomainSnapshotLoad,
674
 
                   qemu_driver->snapshotDir);
675
 
 
676
 
    qemu_driver->workerPool = virThreadPoolNew(0, 1, 0, processWatchdogEvent, qemu_driver);
677
 
    if (!qemu_driver->workerPool)
678
 
        goto error;
679
 
 
680
 
    qemuDriverUnlock(qemu_driver);
681
 
 
682
 
    qemuAutostartDomains(qemu_driver);
683
 
 
684
 
    if (conn)
685
 
        virConnectClose(conn);
686
 
 
687
 
    return 0;
688
 
 
689
 
out_of_memory:
690
 
    virReportOOMError();
691
 
error:
692
 
    if (qemu_driver)
693
 
        qemuDriverUnlock(qemu_driver);
694
 
    if (conn)
695
 
        virConnectClose(conn);
696
 
    VIR_FREE(base);
697
 
    VIR_FREE(driverConf);
698
 
    qemudShutdown();
699
 
    return -1;
700
 
}
701
 
 
702
 
static void qemudNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
703
 
{
704
 
    struct qemud_driver *driver = opaque;
705
 
 
706
 
    if (newVM) {
707
 
        virDomainEventPtr event =
708
 
            virDomainEventNewFromObj(vm,
709
 
                                     VIR_DOMAIN_EVENT_DEFINED,
710
 
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED);
711
 
        if (event)
712
 
            qemuDomainEventQueue(driver, event);
713
 
    }
714
 
}
715
 
 
716
 
/**
717
 
 * qemudReload:
718
 
 *
719
 
 * Function to restart the QEmu daemon, it will recheck the configuration
720
 
 * files and update its state and the networking
721
 
 */
722
 
static int
723
 
qemudReload(void) {
724
 
    if (!qemu_driver)
725
 
        return 0;
726
 
 
727
 
    qemuDriverLock(qemu_driver);
728
 
    virDomainLoadAllConfigs(qemu_driver->caps,
729
 
                            &qemu_driver->domains,
730
 
                            qemu_driver->configDir,
731
 
                            qemu_driver->autostartDir,
732
 
                            0, QEMU_EXPECTED_VIRT_TYPES,
733
 
                            qemudNotifyLoadDomain, qemu_driver);
734
 
    qemuDriverUnlock(qemu_driver);
735
 
 
736
 
    qemuAutostartDomains(qemu_driver);
737
 
 
738
 
    return 0;
739
 
}
740
 
 
741
 
/**
742
 
 * qemudActive:
743
 
 *
744
 
 * Checks if the QEmu daemon is active, i.e. has an active domain or
745
 
 * an active network
746
 
 *
747
 
 * Returns 1 if active, 0 otherwise
748
 
 */
749
 
static int
750
 
qemudActive(void) {
751
 
    int active = 0;
752
 
 
753
 
    if (!qemu_driver)
754
 
        return 0;
755
 
 
756
 
    /* XXX having to iterate here is not great because it requires many locks */
757
 
    qemuDriverLock(qemu_driver);
758
 
    active = virDomainObjListNumOfDomains(&qemu_driver->domains, 1);
759
 
    qemuDriverUnlock(qemu_driver);
760
 
    return active;
761
 
}
762
 
 
763
 
/**
764
 
 * qemudShutdown:
765
 
 *
766
 
 * Shutdown the QEmu daemon, it will stop all active domains and networks
767
 
 */
768
 
static int
769
 
qemudShutdown(void) {
770
 
    int i;
771
 
 
772
 
    if (!qemu_driver)
773
 
        return -1;
774
 
 
775
 
    qemuDriverLock(qemu_driver);
776
 
    pciDeviceListFree(qemu_driver->activePciHostdevs);
777
 
    virCapabilitiesFree(qemu_driver->caps);
778
 
 
779
 
    virDomainObjListDeinit(&qemu_driver->domains);
780
 
    virBitmapFree(qemu_driver->reservedVNCPorts);
781
 
 
782
 
    virSysinfoDefFree(qemu_driver->hostsysinfo);
783
 
 
784
 
    qemuProcessAutoDestroyShutdown(qemu_driver);
785
 
 
786
 
    VIR_FREE(qemu_driver->configDir);
787
 
    VIR_FREE(qemu_driver->autostartDir);
788
 
    VIR_FREE(qemu_driver->logDir);
789
 
    VIR_FREE(qemu_driver->stateDir);
790
 
    VIR_FREE(qemu_driver->libDir);
791
 
    VIR_FREE(qemu_driver->cacheDir);
792
 
    VIR_FREE(qemu_driver->saveDir);
793
 
    VIR_FREE(qemu_driver->snapshotDir);
794
 
    VIR_FREE(qemu_driver->qemuImgBinary);
795
 
    VIR_FREE(qemu_driver->autoDumpPath);
796
 
    VIR_FREE(qemu_driver->vncTLSx509certdir);
797
 
    VIR_FREE(qemu_driver->vncListen);
798
 
    VIR_FREE(qemu_driver->vncPassword);
799
 
    VIR_FREE(qemu_driver->vncSASLdir);
800
 
    VIR_FREE(qemu_driver->spiceTLSx509certdir);
801
 
    VIR_FREE(qemu_driver->spiceListen);
802
 
    VIR_FREE(qemu_driver->spicePassword);
803
 
    VIR_FREE(qemu_driver->hugetlbfs_mount);
804
 
    VIR_FREE(qemu_driver->hugepage_path);
805
 
    VIR_FREE(qemu_driver->saveImageFormat);
806
 
    VIR_FREE(qemu_driver->dumpImageFormat);
807
 
 
808
 
    virSecurityManagerFree(qemu_driver->securityManager);
809
 
 
810
 
    ebtablesContextFree(qemu_driver->ebtables);
811
 
 
812
 
    if (qemu_driver->cgroupDeviceACL) {
813
 
        for (i = 0 ; qemu_driver->cgroupDeviceACL[i] != NULL ; i++)
814
 
            VIR_FREE(qemu_driver->cgroupDeviceACL[i]);
815
 
        VIR_FREE(qemu_driver->cgroupDeviceACL);
816
 
    }
817
 
 
818
 
    /* Free domain callback list */
819
 
    virDomainEventStateFree(qemu_driver->domainEventState);
820
 
 
821
 
    virCgroupFree(&qemu_driver->cgroup);
822
 
 
823
 
    virLockManagerPluginUnref(qemu_driver->lockManager);
824
 
 
825
 
    qemuDriverUnlock(qemu_driver);
826
 
    virMutexDestroy(&qemu_driver->lock);
827
 
    virThreadPoolFree(qemu_driver->workerPool);
828
 
    VIR_FREE(qemu_driver);
829
 
 
830
 
    return 0;
831
 
}
832
 
 
833
 
 
834
 
static virDrvOpenStatus qemudOpen(virConnectPtr conn,
835
 
                                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
836
 
                                  unsigned int flags)
837
 
{
838
 
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
839
 
 
840
 
    if (conn->uri == NULL) {
841
 
        if (qemu_driver == NULL)
842
 
            return VIR_DRV_OPEN_DECLINED;
843
 
 
844
 
        conn->uri = xmlParseURI(qemu_driver->privileged ?
845
 
                                "qemu:///system" :
846
 
                                "qemu:///session");
847
 
        if (!conn->uri) {
848
 
            virReportOOMError();
849
 
            return VIR_DRV_OPEN_ERROR;
850
 
        }
851
 
    } else {
852
 
        /* If URI isn't 'qemu' its definitely not for us */
853
 
        if (conn->uri->scheme == NULL ||
854
 
            STRNEQ(conn->uri->scheme, "qemu"))
855
 
            return VIR_DRV_OPEN_DECLINED;
856
 
 
857
 
        /* Allow remote driver to deal with URIs with hostname server */
858
 
        if (conn->uri->server != NULL)
859
 
            return VIR_DRV_OPEN_DECLINED;
860
 
 
861
 
        if (qemu_driver == NULL) {
862
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
863
 
                            _("qemu state driver is not active"));
864
 
            return VIR_DRV_OPEN_ERROR;
865
 
        }
866
 
 
867
 
        if (conn->uri->path == NULL) {
868
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
869
 
                            _("no QEMU URI path given, try %s"),
870
 
                            qemu_driver->privileged
871
 
                            ? "qemu:///system"
872
 
                            : "qemu:///session");
873
 
                return VIR_DRV_OPEN_ERROR;
874
 
        }
875
 
 
876
 
        if (qemu_driver->privileged) {
877
 
            if (STRNEQ (conn->uri->path, "/system") &&
878
 
                STRNEQ (conn->uri->path, "/session")) {
879
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
880
 
                                _("unexpected QEMU URI path '%s', try qemu:///system"),
881
 
                                conn->uri->path);
882
 
                return VIR_DRV_OPEN_ERROR;
883
 
            }
884
 
        } else {
885
 
            if (STRNEQ (conn->uri->path, "/session")) {
886
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
887
 
                                _("unexpected QEMU URI path '%s', try qemu:///session"),
888
 
                                conn->uri->path);
889
 
                return VIR_DRV_OPEN_ERROR;
890
 
            }
891
 
        }
892
 
    }
893
 
    conn->privateData = qemu_driver;
894
 
 
895
 
    return VIR_DRV_OPEN_SUCCESS;
896
 
}
897
 
 
898
 
static int qemudClose(virConnectPtr conn) {
899
 
    struct qemud_driver *driver = conn->privateData;
900
 
 
901
 
    /* Get rid of callbacks registered for this conn */
902
 
    qemuDriverLock(driver);
903
 
    virDomainEventCallbackListRemoveConn(conn,
904
 
                                         driver->domainEventState->callbacks);
905
 
    qemuProcessAutoDestroyRun(driver, conn);
906
 
    qemuDriverUnlock(driver);
907
 
 
908
 
    conn->privateData = NULL;
909
 
 
910
 
    return 0;
911
 
}
912
 
 
913
 
/* Which features are supported by this driver? */
914
 
static int
915
 
qemudSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
916
 
{
917
 
    switch (feature) {
918
 
    case VIR_DRV_FEATURE_MIGRATION_V2:
919
 
    case VIR_DRV_FEATURE_MIGRATION_V3:
920
 
    case VIR_DRV_FEATURE_MIGRATION_P2P:
921
 
    case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
922
 
    case VIR_DRV_FEATURE_FD_PASSING:
923
 
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
924
 
        return 1;
925
 
    default:
926
 
        return 0;
927
 
    }
928
 
}
929
 
 
930
 
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
931
 
    return "QEMU";
932
 
}
933
 
 
934
 
 
935
 
static int qemuIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
936
 
{
937
 
    /* Trivially secure, since always inside the daemon */
938
 
    return 1;
939
 
}
940
 
 
941
 
static int qemuIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
942
 
{
943
 
    /* Not encrypted, but remote driver takes care of that */
944
 
    return 0;
945
 
}
946
 
 
947
 
static int qemuIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
948
 
{
949
 
    return 1;
950
 
}
951
 
 
952
 
 
953
 
static int kvmGetMaxVCPUs(void) {
954
 
    int maxvcpus = 1;
955
 
 
956
 
    int r, fd;
957
 
 
958
 
    fd = open(KVM_DEVICE, O_RDONLY);
959
 
    if (fd < 0) {
960
 
        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
961
 
        return -1;
962
 
    }
963
 
 
964
 
    r = ioctl(fd, KVM_CHECK_EXTENSION, KVM_CAP_NR_VCPUS);
965
 
    if (r > 0)
966
 
        maxvcpus = r;
967
 
 
968
 
    VIR_FORCE_CLOSE(fd);
969
 
    return maxvcpus;
970
 
}
971
 
 
972
 
 
973
 
static char *
974
 
qemuGetSysinfo(virConnectPtr conn, unsigned int flags)
975
 
{
976
 
    struct qemud_driver *driver = conn->privateData;
977
 
    virBuffer buf = VIR_BUFFER_INITIALIZER;
978
 
 
979
 
    virCheckFlags(0, NULL);
980
 
 
981
 
    if (!driver->hostsysinfo) {
982
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
983
 
                        _("Host SMBIOS information is not available"));
984
 
        return NULL;
985
 
    }
986
 
 
987
 
    if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
988
 
        return NULL;
989
 
    if (virBufferError(&buf)) {
990
 
        virReportOOMError();
991
 
        return NULL;
992
 
    }
993
 
    return virBufferContentAndReset(&buf);
994
 
}
995
 
 
996
 
static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type) {
997
 
    if (!type)
998
 
        return 16;
999
 
 
1000
 
    if (STRCASEEQ(type, "qemu"))
1001
 
        return 16;
1002
 
 
1003
 
    if (STRCASEEQ(type, "kvm"))
1004
 
        return kvmGetMaxVCPUs();
1005
 
 
1006
 
    if (STRCASEEQ(type, "kqemu"))
1007
 
        return 1;
1008
 
 
1009
 
    qemuReportError(VIR_ERR_INVALID_ARG,
1010
 
                    _("unknown type '%s'"), type);
1011
 
    return -1;
1012
 
}
1013
 
 
1014
 
 
1015
 
static char *qemudGetCapabilities(virConnectPtr conn) {
1016
 
    struct qemud_driver *driver = conn->privateData;
1017
 
    virCapsPtr caps = NULL;
1018
 
    char *xml = NULL;
1019
 
 
1020
 
    qemuDriverLock(driver);
1021
 
 
1022
 
    if ((caps = qemuCreateCapabilities(qemu_driver->caps,
1023
 
                                       qemu_driver)) == NULL) {
1024
 
        virCapabilitiesFree(caps);
1025
 
        goto cleanup;
1026
 
    }
1027
 
 
1028
 
    virCapabilitiesFree(qemu_driver->caps);
1029
 
    qemu_driver->caps = caps;
1030
 
 
1031
 
    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
1032
 
        virReportOOMError();
1033
 
 
1034
 
cleanup:
1035
 
    qemuDriverUnlock(driver);
1036
 
 
1037
 
    return xml;
1038
 
}
1039
 
 
1040
 
 
1041
 
static int
1042
 
qemudGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, int pid,
1043
 
                    int tid)
1044
 
{
1045
 
    char *proc;
1046
 
    FILE *pidinfo;
1047
 
    unsigned long long usertime, systime;
1048
 
    int cpu;
1049
 
    int ret;
1050
 
 
1051
 
    if (tid)
1052
 
        ret = virAsprintf(&proc, "/proc/%d/task/%d/stat", pid, tid);
1053
 
    else
1054
 
        ret = virAsprintf(&proc, "/proc/%d/stat", pid);
1055
 
    if (ret < 0)
1056
 
        return -1;
1057
 
 
1058
 
    if (!(pidinfo = fopen(proc, "r"))) {
1059
 
        /* VM probably shut down, so fake 0 */
1060
 
        if (cpuTime)
1061
 
            *cpuTime = 0;
1062
 
        if (lastCpu)
1063
 
            *lastCpu = 0;
1064
 
        VIR_FREE(proc);
1065
 
        return 0;
1066
 
    }
1067
 
    VIR_FREE(proc);
1068
 
 
1069
 
    /* See 'man proc' for information about what all these fields are. We're
1070
 
     * only interested in a very few of them */
1071
 
    if (fscanf(pidinfo,
1072
 
               /* pid -> stime */
1073
 
               "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu"
1074
 
               /* cutime -> endcode */
1075
 
               "%*d %*d %*d %*d %*d %*u %*u %*d %*u %*u %*u %*u"
1076
 
               /* startstack -> processor */
1077
 
               "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %d",
1078
 
               &usertime, &systime, &cpu) != 3) {
1079
 
        VIR_FORCE_FCLOSE(pidinfo);
1080
 
        VIR_WARN("cannot parse process status data");
1081
 
        errno = -EINVAL;
1082
 
        return -1;
1083
 
    }
1084
 
 
1085
 
    /* We got jiffies
1086
 
     * We want nanoseconds
1087
 
     * _SC_CLK_TCK is jiffies per second
1088
 
     * So calulate thus....
1089
 
     */
1090
 
    if (cpuTime)
1091
 
        *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
1092
 
    if (lastCpu)
1093
 
        *lastCpu = cpu;
1094
 
 
1095
 
 
1096
 
    VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d",
1097
 
              pid, tid, usertime, systime, cpu);
1098
 
 
1099
 
    VIR_FORCE_FCLOSE(pidinfo);
1100
 
 
1101
 
    return 0;
1102
 
}
1103
 
 
1104
 
 
1105
 
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
1106
 
                                          int id) {
1107
 
    struct qemud_driver *driver = conn->privateData;
1108
 
    virDomainObjPtr vm;
1109
 
    virDomainPtr dom = NULL;
1110
 
 
1111
 
    qemuDriverLock(driver);
1112
 
    vm  = virDomainFindByID(&driver->domains, id);
1113
 
    qemuDriverUnlock(driver);
1114
 
 
1115
 
    if (!vm) {
1116
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1117
 
                        _("no domain with matching id %d"), id);
1118
 
        goto cleanup;
1119
 
    }
1120
 
 
1121
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1122
 
    if (dom) dom->id = vm->def->id;
1123
 
 
1124
 
cleanup:
1125
 
    if (vm)
1126
 
        virDomainObjUnlock(vm);
1127
 
    return dom;
1128
 
}
1129
 
 
1130
 
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
1131
 
                                            const unsigned char *uuid) {
1132
 
    struct qemud_driver *driver = conn->privateData;
1133
 
    virDomainObjPtr vm;
1134
 
    virDomainPtr dom = NULL;
1135
 
 
1136
 
    qemuDriverLock(driver);
1137
 
    vm = virDomainFindByUUID(&driver->domains, uuid);
1138
 
    qemuDriverUnlock(driver);
1139
 
 
1140
 
    if (!vm) {
1141
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1142
 
        virUUIDFormat(uuid, uuidstr);
1143
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1144
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1145
 
        goto cleanup;
1146
 
    }
1147
 
 
1148
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1149
 
    if (dom) dom->id = vm->def->id;
1150
 
 
1151
 
cleanup:
1152
 
    if (vm)
1153
 
        virDomainObjUnlock(vm);
1154
 
    return dom;
1155
 
}
1156
 
 
1157
 
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
1158
 
                                            const char *name) {
1159
 
    struct qemud_driver *driver = conn->privateData;
1160
 
    virDomainObjPtr vm;
1161
 
    virDomainPtr dom = NULL;
1162
 
 
1163
 
    qemuDriverLock(driver);
1164
 
    vm = virDomainFindByName(&driver->domains, name);
1165
 
    qemuDriverUnlock(driver);
1166
 
 
1167
 
    if (!vm) {
1168
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1169
 
                        _("no domain with matching name '%s'"), name);
1170
 
        goto cleanup;
1171
 
    }
1172
 
 
1173
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1174
 
    if (dom) dom->id = vm->def->id;
1175
 
 
1176
 
cleanup:
1177
 
    if (vm)
1178
 
        virDomainObjUnlock(vm);
1179
 
    return dom;
1180
 
}
1181
 
 
1182
 
 
1183
 
static int qemuDomainIsActive(virDomainPtr dom)
1184
 
{
1185
 
    struct qemud_driver *driver = dom->conn->privateData;
1186
 
    virDomainObjPtr obj;
1187
 
    int ret = -1;
1188
 
 
1189
 
    qemuDriverLock(driver);
1190
 
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
1191
 
    qemuDriverUnlock(driver);
1192
 
    if (!obj) {
1193
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1194
 
        virUUIDFormat(dom->uuid, uuidstr);
1195
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1196
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1197
 
        goto cleanup;
1198
 
    }
1199
 
    ret = virDomainObjIsActive(obj);
1200
 
 
1201
 
cleanup:
1202
 
    if (obj)
1203
 
        virDomainObjUnlock(obj);
1204
 
    return ret;
1205
 
}
1206
 
 
1207
 
static int qemuDomainIsPersistent(virDomainPtr dom)
1208
 
{
1209
 
    struct qemud_driver *driver = dom->conn->privateData;
1210
 
    virDomainObjPtr obj;
1211
 
    int ret = -1;
1212
 
 
1213
 
    qemuDriverLock(driver);
1214
 
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
1215
 
    qemuDriverUnlock(driver);
1216
 
    if (!obj) {
1217
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1218
 
        virUUIDFormat(dom->uuid, uuidstr);
1219
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1220
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1221
 
        goto cleanup;
1222
 
    }
1223
 
    ret = obj->persistent;
1224
 
 
1225
 
cleanup:
1226
 
    if (obj)
1227
 
        virDomainObjUnlock(obj);
1228
 
    return ret;
1229
 
}
1230
 
 
1231
 
static int qemuDomainIsUpdated(virDomainPtr dom)
1232
 
{
1233
 
    struct qemud_driver *driver = dom->conn->privateData;
1234
 
    virDomainObjPtr obj;
1235
 
    int ret = -1;
1236
 
 
1237
 
    qemuDriverLock(driver);
1238
 
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
1239
 
    qemuDriverUnlock(driver);
1240
 
    if (!obj) {
1241
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1242
 
        virUUIDFormat(dom->uuid, uuidstr);
1243
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1244
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1245
 
        goto cleanup;
1246
 
    }
1247
 
    ret = obj->updated;
1248
 
 
1249
 
cleanup:
1250
 
    if (obj)
1251
 
        virDomainObjUnlock(obj);
1252
 
    return ret;
1253
 
}
1254
 
 
1255
 
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
1256
 
    struct qemud_driver *driver = conn->privateData;
1257
 
    int ret = -1;
1258
 
 
1259
 
    qemuDriverLock(driver);
1260
 
    if (qemuCapsExtractVersion(driver->caps, &driver->qemuVersion) < 0)
1261
 
        goto cleanup;
1262
 
 
1263
 
    *version = driver->qemuVersion;
1264
 
    ret = 0;
1265
 
 
1266
 
cleanup:
1267
 
    qemuDriverUnlock(driver);
1268
 
    return ret;
1269
 
}
1270
 
 
1271
 
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
1272
 
    struct qemud_driver *driver = conn->privateData;
1273
 
    int n;
1274
 
 
1275
 
    qemuDriverLock(driver);
1276
 
    n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
1277
 
    qemuDriverUnlock(driver);
1278
 
 
1279
 
    return n;
1280
 
}
1281
 
 
1282
 
static int qemudNumDomains(virConnectPtr conn) {
1283
 
    struct qemud_driver *driver = conn->privateData;
1284
 
    int n;
1285
 
 
1286
 
    qemuDriverLock(driver);
1287
 
    n = virDomainObjListNumOfDomains(&driver->domains, 1);
1288
 
    qemuDriverUnlock(driver);
1289
 
 
1290
 
    return n;
1291
 
}
1292
 
 
1293
 
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
1294
 
                                      unsigned int flags) {
1295
 
    struct qemud_driver *driver = conn->privateData;
1296
 
    virDomainDefPtr def;
1297
 
    virDomainObjPtr vm = NULL;
1298
 
    virDomainPtr dom = NULL;
1299
 
    virDomainEventPtr event = NULL;
1300
 
    virDomainEventPtr event2 = NULL;
1301
 
 
1302
 
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
1303
 
                  VIR_DOMAIN_START_AUTODESTROY, NULL);
1304
 
 
1305
 
    qemuDriverLock(driver);
1306
 
    if (!(def = virDomainDefParseString(driver->caps, xml,
1307
 
                                        QEMU_EXPECTED_VIRT_TYPES,
1308
 
                                        VIR_DOMAIN_XML_INACTIVE)))
1309
 
        goto cleanup;
1310
 
 
1311
 
    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
1312
 
        goto cleanup;
1313
 
 
1314
 
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
1315
 
        goto cleanup;
1316
 
 
1317
 
    if (qemudCanonicalizeMachine(driver, def) < 0)
1318
 
        goto cleanup;
1319
 
 
1320
 
    if (qemuDomainAssignPCIAddresses(def) < 0)
1321
 
        goto cleanup;
1322
 
 
1323
 
    if (!(vm = virDomainAssignDef(driver->caps,
1324
 
                                  &driver->domains,
1325
 
                                  def, false)))
1326
 
        goto cleanup;
1327
 
 
1328
 
    def = NULL;
1329
 
 
1330
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
1331
 
        goto cleanup; /* XXXX free the 'vm' we created ? */
1332
 
 
1333
 
    if (qemuProcessStart(conn, driver, vm, NULL,
1334
 
                         (flags & VIR_DOMAIN_START_PAUSED) != 0,
1335
 
                         (flags & VIR_DOMAIN_START_AUTODESTROY) != 0,
1336
 
                         -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0) {
1337
 
        virDomainAuditStart(vm, "booted", false);
1338
 
        if (qemuDomainObjEndJob(driver, vm) > 0)
1339
 
            qemuDomainRemoveInactive(driver, vm);
1340
 
        vm = NULL;
1341
 
        goto cleanup;
1342
 
    }
1343
 
 
1344
 
    event = virDomainEventNewFromObj(vm,
1345
 
                                     VIR_DOMAIN_EVENT_STARTED,
1346
 
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
1347
 
    if (event && (flags & VIR_DOMAIN_START_PAUSED)) {
1348
 
        /* There are two classes of event-watching clients - those
1349
 
         * that only care about on/off (and must see a started event
1350
 
         * no matter what, but don't care about suspend events), and
1351
 
         * those that also care about running/paused.  To satisfy both
1352
 
         * client types, we have to send two events.  */
1353
 
        event2 = virDomainEventNewFromObj(vm,
1354
 
                                          VIR_DOMAIN_EVENT_SUSPENDED,
1355
 
                                          VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1356
 
    }
1357
 
    virDomainAuditStart(vm, "booted", true);
1358
 
 
1359
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1360
 
    if (dom) dom->id = vm->def->id;
1361
 
 
1362
 
    if (vm &&
1363
 
        qemuDomainObjEndJob(driver, vm) == 0)
1364
 
        vm = NULL;
1365
 
 
1366
 
cleanup:
1367
 
    virDomainDefFree(def);
1368
 
    if (vm)
1369
 
        virDomainObjUnlock(vm);
1370
 
    if (event) {
1371
 
        qemuDomainEventQueue(driver, event);
1372
 
        if (event2)
1373
 
            qemuDomainEventQueue(driver, event2);
1374
 
    }
1375
 
    qemuDriverUnlock(driver);
1376
 
    return dom;
1377
 
}
1378
 
 
1379
 
 
1380
 
static int qemudDomainSuspend(virDomainPtr dom) {
1381
 
    struct qemud_driver *driver = dom->conn->privateData;
1382
 
    virDomainObjPtr vm;
1383
 
    int ret = -1;
1384
 
    virDomainEventPtr event = NULL;
1385
 
    qemuDomainObjPrivatePtr priv;
1386
 
    virDomainPausedReason reason;
1387
 
    int eventDetail;
1388
 
 
1389
 
    qemuDriverLock(driver);
1390
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1391
 
 
1392
 
    if (!vm) {
1393
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1394
 
        virUUIDFormat(dom->uuid, uuidstr);
1395
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1396
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1397
 
        goto cleanup;
1398
 
    }
1399
 
    if (!virDomainObjIsActive(vm)) {
1400
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1401
 
                        "%s", _("domain is not running"));
1402
 
        goto cleanup;
1403
 
    }
1404
 
 
1405
 
    priv = vm->privateData;
1406
 
 
1407
 
    if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) {
1408
 
        reason = VIR_DOMAIN_PAUSED_MIGRATION;
1409
 
        eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED;
1410
 
    } else {
1411
 
        reason = VIR_DOMAIN_PAUSED_USER;
1412
 
        eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
1413
 
    }
1414
 
 
1415
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_SUSPEND) < 0)
1416
 
        goto cleanup;
1417
 
 
1418
 
    if (!virDomainObjIsActive(vm)) {
1419
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1420
 
                        "%s", _("domain is not running"));
1421
 
        goto endjob;
1422
 
    }
1423
 
    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
1424
 
        if (qemuProcessStopCPUs(driver, vm, reason, QEMU_ASYNC_JOB_NONE) < 0) {
1425
 
            goto endjob;
1426
 
        }
1427
 
        event = virDomainEventNewFromObj(vm,
1428
 
                                         VIR_DOMAIN_EVENT_SUSPENDED,
1429
 
                                         eventDetail);
1430
 
    }
1431
 
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
1432
 
        goto endjob;
1433
 
    ret = 0;
1434
 
 
1435
 
endjob:
1436
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
1437
 
        vm = NULL;
1438
 
 
1439
 
cleanup:
1440
 
    if (vm)
1441
 
        virDomainObjUnlock(vm);
1442
 
 
1443
 
    if (event)
1444
 
        qemuDomainEventQueue(driver, event);
1445
 
    qemuDriverUnlock(driver);
1446
 
    return ret;
1447
 
}
1448
 
 
1449
 
 
1450
 
static int qemudDomainResume(virDomainPtr dom) {
1451
 
    struct qemud_driver *driver = dom->conn->privateData;
1452
 
    virDomainObjPtr vm;
1453
 
    int ret = -1;
1454
 
    virDomainEventPtr event = NULL;
1455
 
 
1456
 
    qemuDriverLock(driver);
1457
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1458
 
 
1459
 
    if (!vm) {
1460
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1461
 
        virUUIDFormat(dom->uuid, uuidstr);
1462
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1463
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1464
 
        goto cleanup;
1465
 
    }
1466
 
 
1467
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
1468
 
        goto cleanup;
1469
 
 
1470
 
    if (!virDomainObjIsActive(vm)) {
1471
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1472
 
                        "%s", _("domain is not running"));
1473
 
        goto endjob;
1474
 
    }
1475
 
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
1476
 
        if (qemuProcessStartCPUs(driver, vm, dom->conn,
1477
 
                                 VIR_DOMAIN_RUNNING_UNPAUSED,
1478
 
                                 QEMU_ASYNC_JOB_NONE) < 0) {
1479
 
            if (virGetLastError() == NULL)
1480
 
                qemuReportError(VIR_ERR_OPERATION_FAILED,
1481
 
                                "%s", _("resume operation failed"));
1482
 
            goto endjob;
1483
 
        }
1484
 
        event = virDomainEventNewFromObj(vm,
1485
 
                                         VIR_DOMAIN_EVENT_RESUMED,
1486
 
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
1487
 
    }
1488
 
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
1489
 
        goto endjob;
1490
 
    ret = 0;
1491
 
 
1492
 
endjob:
1493
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
1494
 
        vm = NULL;
1495
 
 
1496
 
cleanup:
1497
 
    if (vm)
1498
 
        virDomainObjUnlock(vm);
1499
 
    if (event)
1500
 
        qemuDomainEventQueue(driver, event);
1501
 
    qemuDriverUnlock(driver);
1502
 
    return ret;
1503
 
}
1504
 
 
1505
 
 
1506
 
static int qemuDomainShutdown(virDomainPtr dom) {
1507
 
    struct qemud_driver *driver = dom->conn->privateData;
1508
 
    virDomainObjPtr vm;
1509
 
    int ret = -1;
1510
 
    qemuDomainObjPrivatePtr priv;
1511
 
 
1512
 
    qemuDriverLock(driver);
1513
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1514
 
    qemuDriverUnlock(driver);
1515
 
 
1516
 
    if (!vm) {
1517
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1518
 
        virUUIDFormat(dom->uuid, uuidstr);
1519
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1520
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1521
 
        goto cleanup;
1522
 
    }
1523
 
 
1524
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1525
 
        goto cleanup;
1526
 
 
1527
 
    if (!virDomainObjIsActive(vm)) {
1528
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1529
 
                        "%s", _("domain is not running"));
1530
 
        goto endjob;
1531
 
    }
1532
 
 
1533
 
    qemuDomainSetFakeReboot(driver, vm, false);
1534
 
 
1535
 
    priv = vm->privateData;
1536
 
    qemuDomainObjEnterMonitor(driver, vm);
1537
 
    ret = qemuMonitorSystemPowerdown(priv->mon);
1538
 
    qemuDomainObjExitMonitor(driver, vm);
1539
 
 
1540
 
endjob:
1541
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
1542
 
        vm = NULL;
1543
 
 
1544
 
cleanup:
1545
 
    if (vm)
1546
 
        virDomainObjUnlock(vm);
1547
 
    return ret;
1548
 
}
1549
 
 
1550
 
 
1551
 
static int qemuDomainReboot(virDomainPtr dom, unsigned int flags) {
1552
 
    struct qemud_driver *driver = dom->conn->privateData;
1553
 
    virDomainObjPtr vm;
1554
 
    int ret = -1;
1555
 
    qemuDomainObjPrivatePtr priv;
1556
 
 
1557
 
    virCheckFlags(0, -1);
1558
 
 
1559
 
    qemuDriverLock(driver);
1560
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1561
 
    qemuDriverUnlock(driver);
1562
 
 
1563
 
    if (!vm) {
1564
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1565
 
        virUUIDFormat(dom->uuid, uuidstr);
1566
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1567
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1568
 
        goto cleanup;
1569
 
    }
1570
 
 
1571
 
    priv = vm->privateData;
1572
 
 
1573
 
    if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
1574
 
        if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) {
1575
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
1576
 
                            _("Reboot is not supported with this QEMU binary"));
1577
 
            goto cleanup;
1578
 
        }
1579
 
 
1580
 
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1581
 
            goto cleanup;
1582
 
 
1583
 
        if (!virDomainObjIsActive(vm)) {
1584
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
1585
 
                            "%s", _("domain is not running"));
1586
 
            goto endjob;
1587
 
        }
1588
 
 
1589
 
        qemuDomainObjEnterMonitor(driver, vm);
1590
 
        ret = qemuMonitorSystemPowerdown(priv->mon);
1591
 
        qemuDomainObjExitMonitor(driver, vm);
1592
 
 
1593
 
        if (ret == 0)
1594
 
            qemuDomainSetFakeReboot(driver, vm, true);
1595
 
 
1596
 
    endjob:
1597
 
        if (qemuDomainObjEndJob(driver, vm) == 0)
1598
 
            vm = NULL;
1599
 
    } else {
1600
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
1601
 
                        _("Reboot is not supported without the JSON monitor"));
1602
 
    }
1603
 
 
1604
 
cleanup:
1605
 
    if (vm)
1606
 
        virDomainObjUnlock(vm);
1607
 
    return ret;
1608
 
}
1609
 
 
1610
 
 
1611
 
static int
1612
 
qemuDomainReset(virDomainPtr dom, unsigned int flags)
1613
 
{
1614
 
    struct qemud_driver *driver = dom->conn->privateData;
1615
 
    virDomainObjPtr vm;
1616
 
    int ret = -1;
1617
 
    qemuDomainObjPrivatePtr priv;
1618
 
 
1619
 
    virCheckFlags(0, -1);
1620
 
 
1621
 
    qemuDriverLock(driver);
1622
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1623
 
    qemuDriverUnlock(driver);
1624
 
 
1625
 
    if (!vm) {
1626
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1627
 
        virUUIDFormat(dom->uuid, uuidstr);
1628
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1629
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1630
 
        goto cleanup;
1631
 
    }
1632
 
 
1633
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1634
 
        goto cleanup;
1635
 
 
1636
 
    if (!virDomainObjIsActive(vm)) {
1637
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1638
 
                        "%s", _("domain is not running"));
1639
 
        goto endjob;
1640
 
    }
1641
 
 
1642
 
    priv = vm->privateData;
1643
 
    qemuDomainObjEnterMonitor(driver, vm);
1644
 
    ret = qemuMonitorSystemReset(priv->mon);
1645
 
    qemuDomainObjExitMonitor(driver, vm);
1646
 
 
1647
 
    priv->fakeReboot = false;
1648
 
 
1649
 
endjob:
1650
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
1651
 
        vm = NULL;
1652
 
 
1653
 
cleanup:
1654
 
    if (vm)
1655
 
        virDomainObjUnlock(vm);
1656
 
    return ret;
1657
 
}
1658
 
 
1659
 
 
1660
 
/* Count how many snapshots in a set have external disk snapshots.  */
1661
 
static void
1662
 
qemuDomainSnapshotCountExternal(void *payload,
1663
 
                                const void *name ATTRIBUTE_UNUSED,
1664
 
                                void *data)
1665
 
{
1666
 
    virDomainSnapshotObjPtr snap = payload;
1667
 
    int *count = data;
1668
 
 
1669
 
    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT)
1670
 
        (*count)++;
1671
 
}
1672
 
 
1673
 
static int
1674
 
qemuDomainDestroyFlags(virDomainPtr dom,
1675
 
                       unsigned int flags)
1676
 
{
1677
 
    struct qemud_driver *driver = dom->conn->privateData;
1678
 
    virDomainObjPtr vm;
1679
 
    int ret = -1;
1680
 
    virDomainEventPtr event = NULL;
1681
 
 
1682
 
    virCheckFlags(0, -1);
1683
 
 
1684
 
    qemuDriverLock(driver);
1685
 
    vm  = virDomainFindByUUID(&driver->domains, dom->uuid);
1686
 
    if (!vm) {
1687
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1688
 
        virUUIDFormat(dom->uuid, uuidstr);
1689
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1690
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1691
 
        goto cleanup;
1692
 
    }
1693
 
 
1694
 
    qemuDomainSetFakeReboot(driver, vm, false);
1695
 
 
1696
 
    /* Although qemuProcessStop does this already, there may
1697
 
     * be an outstanding job active. We want to make sure we
1698
 
     * can kill the process even if a job is active. Killing
1699
 
     * it now means the job will be released
1700
 
     */
1701
 
    qemuProcessKill(vm, false);
1702
 
 
1703
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_DESTROY) < 0)
1704
 
        goto cleanup;
1705
 
 
1706
 
    if (!virDomainObjIsActive(vm)) {
1707
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1708
 
                        "%s", _("domain is not running"));
1709
 
        goto endjob;
1710
 
    }
1711
 
 
1712
 
    qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_DESTROYED);
1713
 
    event = virDomainEventNewFromObj(vm,
1714
 
                                     VIR_DOMAIN_EVENT_STOPPED,
1715
 
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
1716
 
    virDomainAuditStop(vm, "destroyed");
1717
 
 
1718
 
    if (!vm->persistent) {
1719
 
        if (qemuDomainObjEndJob(driver, vm) > 0)
1720
 
            qemuDomainRemoveInactive(driver, vm);
1721
 
        vm = NULL;
1722
 
    }
1723
 
    ret = 0;
1724
 
 
1725
 
endjob:
1726
 
    if (vm &&
1727
 
        qemuDomainObjEndJob(driver, vm) == 0)
1728
 
        vm = NULL;
1729
 
 
1730
 
cleanup:
1731
 
    if (vm)
1732
 
        virDomainObjUnlock(vm);
1733
 
    if (event)
1734
 
        qemuDomainEventQueue(driver, event);
1735
 
    qemuDriverUnlock(driver);
1736
 
    return ret;
1737
 
}
1738
 
 
1739
 
static int
1740
 
qemuDomainDestroy(virDomainPtr dom)
1741
 
{
1742
 
    return qemuDomainDestroyFlags(dom, 0);
1743
 
}
1744
 
 
1745
 
static char *qemudDomainGetOSType(virDomainPtr dom) {
1746
 
    struct qemud_driver *driver = dom->conn->privateData;
1747
 
    virDomainObjPtr vm;
1748
 
    char *type = NULL;
1749
 
 
1750
 
    qemuDriverLock(driver);
1751
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1752
 
    qemuDriverUnlock(driver);
1753
 
    if (!vm) {
1754
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1755
 
        virUUIDFormat(dom->uuid, uuidstr);
1756
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1757
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1758
 
        goto cleanup;
1759
 
    }
1760
 
 
1761
 
    if (!(type = strdup(vm->def->os.type)))
1762
 
        virReportOOMError();
1763
 
 
1764
 
cleanup:
1765
 
    if (vm)
1766
 
        virDomainObjUnlock(vm);
1767
 
    return type;
1768
 
}
1769
 
 
1770
 
/* Returns max memory in kb, 0 if error */
1771
 
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
1772
 
    struct qemud_driver *driver = dom->conn->privateData;
1773
 
    virDomainObjPtr vm;
1774
 
    unsigned long ret = 0;
1775
 
 
1776
 
    qemuDriverLock(driver);
1777
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1778
 
    qemuDriverUnlock(driver);
1779
 
 
1780
 
    if (!vm) {
1781
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1782
 
        virUUIDFormat(dom->uuid, uuidstr);
1783
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1784
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1785
 
        goto cleanup;
1786
 
    }
1787
 
 
1788
 
    ret = vm->def->mem.max_balloon;
1789
 
 
1790
 
cleanup:
1791
 
    if (vm)
1792
 
        virDomainObjUnlock(vm);
1793
 
    return ret;
1794
 
}
1795
 
 
1796
 
static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
1797
 
                                     unsigned int flags) {
1798
 
    struct qemud_driver *driver = dom->conn->privateData;
1799
 
    qemuDomainObjPrivatePtr priv;
1800
 
    virDomainObjPtr vm;
1801
 
    virDomainDefPtr persistentDef = NULL;
1802
 
    int ret = -1, r;
1803
 
    bool isActive;
1804
 
 
1805
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
1806
 
                  VIR_DOMAIN_AFFECT_CONFIG |
1807
 
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
1808
 
 
1809
 
    qemuDriverLock(driver);
1810
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1811
 
    qemuDriverUnlock(driver);
1812
 
    if (!vm) {
1813
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1814
 
        virUUIDFormat(dom->uuid, uuidstr);
1815
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1816
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1817
 
        goto cleanup;
1818
 
    }
1819
 
 
1820
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
1821
 
        goto cleanup;
1822
 
 
1823
 
    isActive = virDomainObjIsActive(vm);
1824
 
 
1825
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
1826
 
        if (isActive)
1827
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
1828
 
        else
1829
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
1830
 
    }
1831
 
    if (flags == VIR_DOMAIN_MEM_MAXIMUM) {
1832
 
        if (isActive)
1833
 
            flags = VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_MEM_MAXIMUM;
1834
 
        else
1835
 
            flags = VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_MEM_MAXIMUM;
1836
 
    }
1837
 
 
1838
 
    if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
1839
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1840
 
                        "%s", _("domain is not running"));
1841
 
        goto endjob;
1842
 
    }
1843
 
 
1844
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1845
 
        if (!vm->persistent) {
1846
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
1847
 
                            _("cannot change persistent config of a transient domain"));
1848
 
            goto endjob;
1849
 
        }
1850
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
1851
 
            goto endjob;
1852
 
    }
1853
 
 
1854
 
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
1855
 
        /* resize the maximum memory */
1856
 
 
1857
 
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
1858
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
1859
 
                            _("cannot resize the maximum memory on an "
1860
 
                              "active domain"));
1861
 
            goto endjob;
1862
 
        }
1863
 
 
1864
 
        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1865
 
            /* Help clang 2.8 decipher the logic flow.  */
1866
 
            sa_assert(persistentDef);
1867
 
            persistentDef->mem.max_balloon = newmem;
1868
 
            if (persistentDef->mem.cur_balloon > newmem)
1869
 
                persistentDef->mem.cur_balloon = newmem;
1870
 
            ret = virDomainSaveConfig(driver->configDir, persistentDef);
1871
 
            goto endjob;
1872
 
        }
1873
 
 
1874
 
    } else {
1875
 
        /* resize the current memory */
1876
 
 
1877
 
        if (newmem > vm->def->mem.max_balloon) {
1878
 
            qemuReportError(VIR_ERR_INVALID_ARG, "%s",
1879
 
                            _("cannot set memory higher than max memory"));
1880
 
            goto endjob;
1881
 
        }
1882
 
 
1883
 
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
1884
 
            priv = vm->privateData;
1885
 
            qemuDomainObjEnterMonitor(driver, vm);
1886
 
            r = qemuMonitorSetBalloon(priv->mon, newmem);
1887
 
            qemuDomainObjExitMonitor(driver, vm);
1888
 
            virDomainAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update",
1889
 
                                 r == 1);
1890
 
            if (r < 0)
1891
 
                goto endjob;
1892
 
 
1893
 
            /* Lack of balloon support is a fatal error */
1894
 
            if (r == 0) {
1895
 
                qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
1896
 
                                _("cannot set memory of an active domain"));
1897
 
                goto endjob;
1898
 
            }
1899
 
        }
1900
 
 
1901
 
        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
1902
 
            sa_assert(persistentDef);
1903
 
            persistentDef->mem.cur_balloon = newmem;
1904
 
            ret = virDomainSaveConfig(driver->configDir, persistentDef);
1905
 
            goto endjob;
1906
 
        }
1907
 
    }
1908
 
 
1909
 
    ret = 0;
1910
 
endjob:
1911
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
1912
 
        vm = NULL;
1913
 
 
1914
 
cleanup:
1915
 
    if (vm)
1916
 
        virDomainObjUnlock(vm);
1917
 
    return ret;
1918
 
}
1919
 
 
1920
 
static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem)
1921
 
{
1922
 
    return qemudDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_AFFECT_LIVE);
1923
 
}
1924
 
 
1925
 
static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
1926
 
{
1927
 
    return qemudDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
1928
 
}
1929
 
 
1930
 
static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
1931
 
{
1932
 
    struct qemud_driver *driver = domain->conn->privateData;
1933
 
    virDomainObjPtr vm = NULL;
1934
 
    int ret = -1;
1935
 
    qemuDomainObjPrivatePtr priv;
1936
 
 
1937
 
    virCheckFlags(0, -1);
1938
 
 
1939
 
    qemuDriverLock(driver);
1940
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
1941
 
    if (!vm) {
1942
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1943
 
        virUUIDFormat(domain->uuid, uuidstr);
1944
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
1945
 
                        _("no domain with matching uuid '%s'"), uuidstr);
1946
 
        goto cleanup;
1947
 
    }
1948
 
 
1949
 
    if (!virDomainObjIsActive(vm)) {
1950
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1951
 
                        "%s", _("domain is not running"));
1952
 
        goto cleanup;
1953
 
    }
1954
 
 
1955
 
    priv = vm->privateData;
1956
 
 
1957
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
1958
 
        goto cleanup;
1959
 
 
1960
 
    if (!virDomainObjIsActive(vm)) {
1961
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
1962
 
                        "%s", _("domain is not running"));
1963
 
        goto endjob;
1964
 
    }
1965
 
 
1966
 
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
1967
 
    ret = qemuMonitorInjectNMI(priv->mon);
1968
 
    qemuDomainObjExitMonitorWithDriver(driver, vm);
1969
 
 
1970
 
endjob:
1971
 
    if (qemuDomainObjEndJob(driver, vm) == 0) {
1972
 
        vm = NULL;
1973
 
        goto cleanup;
1974
 
    }
1975
 
 
1976
 
cleanup:
1977
 
    if (vm)
1978
 
        virDomainObjUnlock(vm);
1979
 
    qemuDriverUnlock(driver);
1980
 
    return ret;
1981
 
}
1982
 
 
1983
 
static int qemuDomainSendKey(virDomainPtr domain,
1984
 
                             unsigned int codeset,
1985
 
                             unsigned int holdtime,
1986
 
                             unsigned int *keycodes,
1987
 
                             int nkeycodes,
1988
 
                             unsigned int flags)
1989
 
{
1990
 
    struct qemud_driver *driver = domain->conn->privateData;
1991
 
    virDomainObjPtr vm = NULL;
1992
 
    int ret = -1;
1993
 
    qemuDomainObjPrivatePtr priv;
1994
 
 
1995
 
    virCheckFlags(0, -1);
1996
 
 
1997
 
    /* translate the keycode to RFB for qemu driver */
1998
 
    if (codeset != VIR_KEYCODE_SET_RFB) {
1999
 
        int i;
2000
 
        int keycode;
2001
 
 
2002
 
        for (i = 0; i < nkeycodes; i++) {
2003
 
            keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_RFB,
2004
 
                                               keycodes[i]);
2005
 
            if (keycode < 0) {
2006
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
2007
 
             _("cannot translate keycode %u of %s codeset to rfb keycode"),
2008
 
                                keycodes[i],
2009
 
                                virKeycodeSetTypeToString(codeset));
2010
 
                return -1;
2011
 
            }
2012
 
            keycodes[i] = keycode;
2013
 
        }
2014
 
    }
2015
 
 
2016
 
    qemuDriverLock(driver);
2017
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
2018
 
    if (!vm) {
2019
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2020
 
        virUUIDFormat(domain->uuid, uuidstr);
2021
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2022
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2023
 
        goto cleanup;
2024
 
    }
2025
 
 
2026
 
    priv = vm->privateData;
2027
 
 
2028
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
2029
 
        goto cleanup;
2030
 
 
2031
 
    if (!virDomainObjIsActive(vm)) {
2032
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
2033
 
                        "%s", _("domain is not running"));
2034
 
        goto endjob;
2035
 
    }
2036
 
 
2037
 
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
2038
 
    ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
2039
 
    qemuDomainObjExitMonitorWithDriver(driver, vm);
2040
 
 
2041
 
endjob:
2042
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
2043
 
        vm = NULL;
2044
 
 
2045
 
cleanup:
2046
 
    if (vm)
2047
 
        virDomainObjUnlock(vm);
2048
 
    qemuDriverUnlock(driver);
2049
 
    return ret;
2050
 
}
2051
 
 
2052
 
static int qemudDomainGetInfo(virDomainPtr dom,
2053
 
                              virDomainInfoPtr info)
2054
 
{
2055
 
    struct qemud_driver *driver = dom->conn->privateData;
2056
 
    virDomainObjPtr vm;
2057
 
    int ret = -1;
2058
 
    int err;
2059
 
    unsigned long balloon;
2060
 
 
2061
 
    qemuDriverLock(driver);
2062
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2063
 
    qemuDriverUnlock(driver);
2064
 
    if (!vm) {
2065
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2066
 
        virUUIDFormat(dom->uuid, uuidstr);
2067
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2068
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2069
 
        goto cleanup;
2070
 
    }
2071
 
 
2072
 
    info->state = virDomainObjGetState(vm, NULL);
2073
 
 
2074
 
    if (!virDomainObjIsActive(vm)) {
2075
 
        info->cpuTime = 0;
2076
 
    } else {
2077
 
        if (qemudGetProcessInfo(&(info->cpuTime), NULL, vm->pid, 0) < 0) {
2078
 
            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
2079
 
                            _("cannot read cputime for domain"));
2080
 
            goto cleanup;
2081
 
        }
2082
 
    }
2083
 
 
2084
 
    info->maxMem = vm->def->mem.max_balloon;
2085
 
 
2086
 
    if (virDomainObjIsActive(vm)) {
2087
 
        qemuDomainObjPrivatePtr priv = vm->privateData;
2088
 
 
2089
 
        if ((vm->def->memballoon != NULL) &&
2090
 
            (vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_NONE)) {
2091
 
            info->memory = vm->def->mem.max_balloon;
2092
 
        } else if (qemuDomainJobAllowed(priv, QEMU_JOB_QUERY)) {
2093
 
            if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
2094
 
                goto cleanup;
2095
 
            if (!virDomainObjIsActive(vm))
2096
 
                err = 0;
2097
 
            else {
2098
 
                qemuDomainObjEnterMonitor(driver, vm);
2099
 
                err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
2100
 
                qemuDomainObjExitMonitor(driver, vm);
2101
 
            }
2102
 
            if (qemuDomainObjEndJob(driver, vm) == 0) {
2103
 
                vm = NULL;
2104
 
                goto cleanup;
2105
 
            }
2106
 
 
2107
 
            if (err < 0) {
2108
 
                /* We couldn't get current memory allocation but that's not
2109
 
                 * a show stopper; we wouldn't get it if there was a job
2110
 
                 * active either
2111
 
                 */
2112
 
                info->memory = vm->def->mem.cur_balloon;
2113
 
            } else if (err == 0) {
2114
 
                /* Balloon not supported, so maxmem is always the allocation */
2115
 
                info->memory = vm->def->mem.max_balloon;
2116
 
            } else {
2117
 
                info->memory = balloon;
2118
 
            }
2119
 
        } else {
2120
 
            info->memory = vm->def->mem.cur_balloon;
2121
 
        }
2122
 
    } else {
2123
 
        info->memory = vm->def->mem.cur_balloon;
2124
 
    }
2125
 
 
2126
 
    info->nrVirtCpu = vm->def->vcpus;
2127
 
    ret = 0;
2128
 
 
2129
 
cleanup:
2130
 
    if (vm)
2131
 
        virDomainObjUnlock(vm);
2132
 
    return ret;
2133
 
}
2134
 
 
2135
 
static int
2136
 
qemuDomainGetState(virDomainPtr dom,
2137
 
                   int *state,
2138
 
                   int *reason,
2139
 
                   unsigned int flags)
2140
 
{
2141
 
    struct qemud_driver *driver = dom->conn->privateData;
2142
 
    virDomainObjPtr vm;
2143
 
    int ret = -1;
2144
 
 
2145
 
    virCheckFlags(0, -1);
2146
 
 
2147
 
    qemuDriverLock(driver);
2148
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2149
 
    qemuDriverUnlock(driver);
2150
 
 
2151
 
    if (!vm) {
2152
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2153
 
        virUUIDFormat(dom->uuid, uuidstr);
2154
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2155
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2156
 
        goto cleanup;
2157
 
    }
2158
 
 
2159
 
    *state = virDomainObjGetState(vm, reason);
2160
 
    ret = 0;
2161
 
 
2162
 
cleanup:
2163
 
    if (vm)
2164
 
        virDomainObjUnlock(vm);
2165
 
    return ret;
2166
 
}
2167
 
 
2168
 
static int
2169
 
qemuDomainGetControlInfo(virDomainPtr dom,
2170
 
                          virDomainControlInfoPtr info,
2171
 
                          unsigned int flags)
2172
 
{
2173
 
    struct qemud_driver *driver = dom->conn->privateData;
2174
 
    virDomainObjPtr vm;
2175
 
    qemuDomainObjPrivatePtr priv;
2176
 
    int ret = -1;
2177
 
 
2178
 
    virCheckFlags(0, -1);
2179
 
 
2180
 
    qemuDriverLock(driver);
2181
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2182
 
    qemuDriverUnlock(driver);
2183
 
 
2184
 
    if (!vm) {
2185
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2186
 
        virUUIDFormat(dom->uuid, uuidstr);
2187
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2188
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2189
 
        goto cleanup;
2190
 
    }
2191
 
 
2192
 
    if (!virDomainObjIsActive(vm)) {
2193
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
2194
 
                        "%s", _("domain is not running"));
2195
 
        goto cleanup;
2196
 
    }
2197
 
 
2198
 
    priv = vm->privateData;
2199
 
 
2200
 
    memset(info, 0, sizeof(*info));
2201
 
 
2202
 
    if (priv->monError) {
2203
 
        info->state = VIR_DOMAIN_CONTROL_ERROR;
2204
 
    } else if (priv->job.active) {
2205
 
        if (!priv->monStart) {
2206
 
            info->state = VIR_DOMAIN_CONTROL_JOB;
2207
 
            if (virTimeMillisNow(&info->stateTime) < 0)
2208
 
                goto cleanup;
2209
 
            info->stateTime -= priv->job.start;
2210
 
        } else {
2211
 
            info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
2212
 
            if (virTimeMillisNow(&info->stateTime) < 0)
2213
 
                goto cleanup;
2214
 
            info->stateTime -= priv->monStart;
2215
 
        }
2216
 
    } else {
2217
 
        info->state = VIR_DOMAIN_CONTROL_OK;
2218
 
    }
2219
 
 
2220
 
    ret = 0;
2221
 
 
2222
 
cleanup:
2223
 
    if (vm)
2224
 
        virDomainObjUnlock(vm);
2225
 
    return ret;
2226
 
}
2227
 
 
2228
 
 
2229
 
#define QEMUD_SAVE_MAGIC   "LibvirtQemudSave"
2230
 
#define QEMUD_SAVE_PARTIAL "LibvirtQemudPart"
2231
 
#define QEMUD_SAVE_VERSION 2
2232
 
 
2233
 
verify(sizeof(QEMUD_SAVE_MAGIC) == sizeof(QEMUD_SAVE_PARTIAL));
2234
 
 
2235
 
enum qemud_save_formats {
2236
 
    QEMUD_SAVE_FORMAT_RAW = 0,
2237
 
    QEMUD_SAVE_FORMAT_GZIP = 1,
2238
 
    QEMUD_SAVE_FORMAT_BZIP2 = 2,
2239
 
    /*
2240
 
     * Deprecated by xz and never used as part of a release
2241
 
     * QEMUD_SAVE_FORMAT_LZMA
2242
 
     */
2243
 
    QEMUD_SAVE_FORMAT_XZ = 3,
2244
 
    QEMUD_SAVE_FORMAT_LZOP = 4,
2245
 
    /* Note: add new members only at the end.
2246
 
       These values are used in the on-disk format.
2247
 
       Do not change or re-use numbers. */
2248
 
 
2249
 
    QEMUD_SAVE_FORMAT_LAST
2250
 
};
2251
 
 
2252
 
VIR_ENUM_DECL(qemudSaveCompression)
2253
 
VIR_ENUM_IMPL(qemudSaveCompression, QEMUD_SAVE_FORMAT_LAST,
2254
 
              "raw",
2255
 
              "gzip",
2256
 
              "bzip2",
2257
 
              "xz",
2258
 
              "lzop")
2259
 
 
2260
 
struct qemud_save_header {
2261
 
    char magic[sizeof(QEMUD_SAVE_MAGIC)-1];
2262
 
    uint32_t version;
2263
 
    uint32_t xml_len;
2264
 
    uint32_t was_running;
2265
 
    uint32_t compressed;
2266
 
    uint32_t unused[15];
2267
 
};
2268
 
 
2269
 
static inline void
2270
 
bswap_header(struct qemud_save_header *hdr) {
2271
 
    hdr->version = bswap_32(hdr->version);
2272
 
    hdr->xml_len = bswap_32(hdr->xml_len);
2273
 
    hdr->was_running = bswap_32(hdr->was_running);
2274
 
    hdr->compressed = bswap_32(hdr->compressed);
2275
 
}
2276
 
 
2277
 
 
2278
 
/* return -errno on failure, or 0 on success */
2279
 
static int
2280
 
qemuDomainSaveHeader(int fd, const char *path, char *xml,
2281
 
                     struct qemud_save_header *header)
2282
 
{
2283
 
    int ret = 0;
2284
 
 
2285
 
    if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
2286
 
        ret = -errno;
2287
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
2288
 
                        _("failed to write header to domain save file '%s'"),
2289
 
                        path);
2290
 
        goto endjob;
2291
 
    }
2292
 
 
2293
 
    if (safewrite(fd, xml, header->xml_len) != header->xml_len) {
2294
 
        ret = -errno;
2295
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
2296
 
                         _("failed to write xml to '%s'"), path);
2297
 
        goto endjob;
2298
 
    }
2299
 
endjob:
2300
 
    return ret;
2301
 
}
2302
 
 
2303
 
/* Given a enum qemud_save_formats compression level, return the name
2304
 
 * of the program to run, or NULL if no program is needed.  */
2305
 
static const char *
2306
 
qemuCompressProgramName(int compress)
2307
 
{
2308
 
    return (compress == QEMUD_SAVE_FORMAT_RAW ? NULL :
2309
 
            qemudSaveCompressionTypeToString(compress));
2310
 
}
2311
 
 
2312
 
/* Internal function to properly create or open existing files, with
2313
 
 * ownership affected by qemu driver setup.  */
2314
 
static int
2315
 
qemuOpenFile(struct qemud_driver *driver, const char *path, int oflags,
2316
 
             bool *needUnlink, bool *bypassSecurityDriver)
2317
 
{
2318
 
    struct stat sb;
2319
 
    bool is_reg = true;
2320
 
    bool need_unlink = false;
2321
 
    bool bypass_security = false;
2322
 
    int fd = -1;
2323
 
    uid_t uid = getuid();
2324
 
    gid_t gid = getgid();
2325
 
 
2326
 
    /* path might be a pre-existing block dev, in which case
2327
 
     * we need to skip the create step, and also avoid unlink
2328
 
     * in the failure case */
2329
 
    if (oflags & O_CREAT) {
2330
 
        need_unlink = true;
2331
 
        if (stat(path, &sb) == 0) {
2332
 
            is_reg = !!S_ISREG(sb.st_mode);
2333
 
            /* If the path is regular file which exists
2334
 
             * already and dynamic_ownership is off, we don't
2335
 
             * want to change it's ownership, just open it as-is */
2336
 
            if (is_reg && !driver->dynamicOwnership) {
2337
 
                uid = sb.st_uid;
2338
 
                gid = sb.st_gid;
2339
 
            }
2340
 
        }
2341
 
    }
2342
 
 
2343
 
    /* First try creating the file as root */
2344
 
    if (!is_reg) {
2345
 
        fd = open(path, oflags & ~O_CREAT);
2346
 
        if (fd < 0) {
2347
 
            virReportSystemError(errno, _("unable to open %s"), path);
2348
 
            goto cleanup;
2349
 
        }
2350
 
    } else {
2351
 
        if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR,
2352
 
                                uid, gid, 0)) < 0) {
2353
 
            /* If we failed as root, and the error was permission-denied
2354
 
               (EACCES or EPERM), assume it's on a network-connected share
2355
 
               where root access is restricted (eg, root-squashed NFS). If the
2356
 
               qemu user (driver->user) is non-root, just set a flag to
2357
 
               bypass security driver shenanigans, and retry the operation
2358
 
               after doing setuid to qemu user */
2359
 
            if ((fd != -EACCES && fd != -EPERM) ||
2360
 
                driver->user == getuid()) {
2361
 
                virReportSystemError(-fd,
2362
 
                                     _("Failed to create file '%s'"),
2363
 
                                     path);
2364
 
                goto cleanup;
2365
 
            }
2366
 
 
2367
 
            /* On Linux we can also verify the FS-type of the directory. */
2368
 
            switch (virStorageFileIsSharedFS(path)) {
2369
 
                case 1:
2370
 
                   /* it was on a network share, so we'll continue
2371
 
                    * as outlined above
2372
 
                    */
2373
 
                   break;
2374
 
 
2375
 
                case -1:
2376
 
                   virReportSystemError(errno,
2377
 
                                        _("Failed to create file "
2378
 
                                          "'%s': couldn't determine fs type"),
2379
 
                                        path);
2380
 
                   goto cleanup;
2381
 
 
2382
 
                case 0:
2383
 
                default:
2384
 
                   /* local file - log the error returned by virFileOpenAs */
2385
 
                   virReportSystemError(-fd,
2386
 
                                        _("Failed to create file '%s'"),
2387
 
                                        path);
2388
 
                   goto cleanup;
2389
 
            }
2390
 
 
2391
 
            /* Retry creating the file as driver->user */
2392
 
 
2393
 
            if ((fd = virFileOpenAs(path, oflags,
2394
 
                                    S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
2395
 
                                    driver->user, driver->group,
2396
 
                                    VIR_FILE_OPEN_AS_UID)) < 0) {
2397
 
                virReportSystemError(-fd,
2398
 
                                   _("Error from child process creating '%s'"),
2399
 
                                     path);
2400
 
                goto cleanup;
2401
 
            }
2402
 
 
2403
 
            /* Since we had to setuid to create the file, and the fstype
2404
 
               is NFS, we assume it's a root-squashing NFS share, and that
2405
 
               the security driver stuff would have failed anyway */
2406
 
 
2407
 
            bypass_security = true;
2408
 
        }
2409
 
    }
2410
 
cleanup:
2411
 
    if (needUnlink)
2412
 
        *needUnlink = need_unlink;
2413
 
    if (bypassSecurityDriver)
2414
 
        *bypassSecurityDriver = bypass_security;
2415
 
 
2416
 
    return fd;
2417
 
}
2418
 
 
2419
 
/* This internal function expects the driver lock to already be held on
2420
 
 * entry and the vm must be active + locked. Vm will be unlocked and
2421
 
 * potentially free'd after this returns (eg transient VMs are freed
2422
 
 * shutdown). So 'vm' must not be referenced by the caller after
2423
 
 * this returns (whether returning success or failure).
2424
 
 */
2425
 
static int
2426
 
qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
2427
 
                       virDomainObjPtr vm, const char *path,
2428
 
                       int compressed, const char *xmlin, unsigned int flags)
2429
 
{
2430
 
    char *xml = NULL;
2431
 
    struct qemud_save_header header;
2432
 
    bool bypassSecurityDriver = false;
2433
 
    int ret = -1;
2434
 
    int rc;
2435
 
    virDomainEventPtr event = NULL;
2436
 
    qemuDomainObjPrivatePtr priv;
2437
 
    bool needUnlink = false;
2438
 
    size_t len;
2439
 
    unsigned long long offset;
2440
 
    unsigned long long pad;
2441
 
    int fd = -1;
2442
 
    int directFlag = 0;
2443
 
    virFileDirectFdPtr directFd = NULL;
2444
 
    bool bypass_cache = flags & VIR_DOMAIN_SAVE_BYPASS_CACHE;
2445
 
 
2446
 
    if (qemuProcessAutoDestroyActive(driver, vm)) {
2447
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
2448
 
                        "%s", _("domain is marked for auto destroy"));
2449
 
        goto cleanup;
2450
 
    }
2451
 
 
2452
 
    memset(&header, 0, sizeof(header));
2453
 
    memcpy(header.magic, QEMUD_SAVE_PARTIAL, sizeof(header.magic));
2454
 
    header.version = QEMUD_SAVE_VERSION;
2455
 
 
2456
 
    header.compressed = compressed;
2457
 
 
2458
 
    priv = vm->privateData;
2459
 
 
2460
 
    if (qemuDomainObjBeginAsyncJobWithDriver(driver, vm,
2461
 
                                             QEMU_ASYNC_JOB_SAVE) < 0)
2462
 
        goto cleanup;
2463
 
 
2464
 
    memset(&priv->job.info, 0, sizeof(priv->job.info));
2465
 
    priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
2466
 
 
2467
 
    /* Pause */
2468
 
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
2469
 
        header.was_running = 1;
2470
 
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
2471
 
                                QEMU_ASYNC_JOB_SAVE) < 0)
2472
 
            goto endjob;
2473
 
 
2474
 
        if (!virDomainObjIsActive(vm)) {
2475
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2476
 
                            _("guest unexpectedly quit"));
2477
 
            goto endjob;
2478
 
        }
2479
 
    }
2480
 
    /* libvirt.c already guaranteed these two flags are exclusive.  */
2481
 
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
2482
 
        header.was_running = 1;
2483
 
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
2484
 
        header.was_running = 0;
2485
 
 
2486
 
    /* Get XML for the domain.  Restore needs only the inactive xml,
2487
 
     * including secure.  We should get the same result whether xmlin
2488
 
     * is NULL or whether it was the live xml of the domain moments
2489
 
     * before.  */
2490
 
    if (xmlin) {
2491
 
        virDomainDefPtr def = NULL;
2492
 
 
2493
 
        if (!(def = virDomainDefParseString(driver->caps, xmlin,
2494
 
                                            QEMU_EXPECTED_VIRT_TYPES,
2495
 
                                            VIR_DOMAIN_XML_INACTIVE))) {
2496
 
            goto endjob;
2497
 
        }
2498
 
        if (!virDomainDefCheckABIStability(vm->def, def)) {
2499
 
            virDomainDefFree(def);
2500
 
            goto endjob;
2501
 
        }
2502
 
        xml = virDomainDefFormat(def, (VIR_DOMAIN_XML_INACTIVE |
2503
 
                                       VIR_DOMAIN_XML_SECURE));
2504
 
    } else {
2505
 
        xml = virDomainDefFormat(vm->def, (VIR_DOMAIN_XML_INACTIVE |
2506
 
                                           VIR_DOMAIN_XML_SECURE));
2507
 
    }
2508
 
    if (!xml) {
2509
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
2510
 
                        "%s", _("failed to get domain xml"));
2511
 
        goto endjob;
2512
 
    }
2513
 
    len = strlen(xml) + 1;
2514
 
    offset = sizeof(header) + len;
2515
 
 
2516
 
    /* Due to way we append QEMU state on our header with dd,
2517
 
     * we need to ensure there's a 512 byte boundary. Unfortunately
2518
 
     * we don't have an explicit offset in the header, so we fake
2519
 
     * it by padding the XML string with NUL bytes.  Additionally,
2520
 
     * we want to ensure that virDomainSaveImageDefineXML can supply
2521
 
     * slightly larger XML, so we add a miminum padding prior to
2522
 
     * rounding out to page boundaries.
2523
 
     */
2524
 
    pad = 1024;
2525
 
    pad += (QEMU_MONITOR_MIGRATE_TO_FILE_BS -
2526
 
            ((offset + pad) % QEMU_MONITOR_MIGRATE_TO_FILE_BS));
2527
 
    if (VIR_EXPAND_N(xml, len, pad) < 0) {
2528
 
        virReportOOMError();
2529
 
        goto endjob;
2530
 
    }
2531
 
    offset += pad;
2532
 
    header.xml_len = len;
2533
 
 
2534
 
    /* Obtain the file handle.  */
2535
 
    if (bypass_cache) {
2536
 
        directFlag = virFileDirectFdFlag();
2537
 
        if (directFlag < 0) {
2538
 
            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
2539
 
                            _("bypass cache unsupported by this system"));
2540
 
            goto cleanup;
2541
 
        }
2542
 
    }
2543
 
    fd = qemuOpenFile(driver, path, O_WRONLY | O_TRUNC | O_CREAT | directFlag,
2544
 
                      &needUnlink, &bypassSecurityDriver);
2545
 
    if (fd < 0)
2546
 
        goto endjob;
2547
 
    if (bypass_cache && (directFd = virFileDirectFdNew(&fd, path)) == NULL)
2548
 
        goto endjob;
2549
 
 
2550
 
    /* Write header to file, followed by XML */
2551
 
    if (qemuDomainSaveHeader(fd, path, xml, &header) < 0) {
2552
 
        VIR_FORCE_CLOSE(fd);
2553
 
        goto endjob;
2554
 
    }
2555
 
 
2556
 
    /* Perform the migration */
2557
 
    if (qemuMigrationToFile(driver, vm, fd, offset, path,
2558
 
                            qemuCompressProgramName(compressed),
2559
 
                            bypassSecurityDriver,
2560
 
                            QEMU_ASYNC_JOB_SAVE) < 0)
2561
 
        goto endjob;
2562
 
 
2563
 
    /* Touch up file header to mark image complete.  */
2564
 
    if (bypass_cache) {
2565
 
        /* Reopen the file to touch up the header, since we aren't set
2566
 
         * up to seek backwards on directFd.  The reopened fd will
2567
 
         * trigger a single page of file system cache pollution, but
2568
 
         * that's acceptable.  */
2569
 
        if (VIR_CLOSE(fd) < 0) {
2570
 
            virReportSystemError(errno, _("unable to close %s"), path);
2571
 
            goto endjob;
2572
 
        }
2573
 
        if (virFileDirectFdClose(directFd) < 0)
2574
 
            goto endjob;
2575
 
        fd = qemuOpenFile(driver, path, O_WRONLY, NULL, NULL);
2576
 
        if (fd < 0)
2577
 
            goto endjob;
2578
 
    } else {
2579
 
        if (lseek(fd, 0, SEEK_SET) != 0) {
2580
 
            virReportSystemError(errno, _("unable to seek %s"), path);
2581
 
            goto endjob;
2582
 
        }
2583
 
    }
2584
 
    memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
2585
 
    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
2586
 
        virReportSystemError(errno, _("unable to write %s"), path);
2587
 
        goto endjob;
2588
 
    }
2589
 
    if (VIR_CLOSE(fd) < 0) {
2590
 
        virReportSystemError(errno, _("unable to close %s"), path);
2591
 
        goto endjob;
2592
 
    }
2593
 
 
2594
 
    ret = 0;
2595
 
 
2596
 
    /* Shut it down */
2597
 
    qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_SAVED);
2598
 
    virDomainAuditStop(vm, "saved");
2599
 
    event = virDomainEventNewFromObj(vm,
2600
 
                                     VIR_DOMAIN_EVENT_STOPPED,
2601
 
                                     VIR_DOMAIN_EVENT_STOPPED_SAVED);
2602
 
    if (!vm->persistent) {
2603
 
        if (qemuDomainObjEndAsyncJob(driver, vm) > 0)
2604
 
            qemuDomainRemoveInactive(driver, vm);
2605
 
        vm = NULL;
2606
 
    }
2607
 
 
2608
 
endjob:
2609
 
    if (vm) {
2610
 
        if (ret != 0) {
2611
 
            if (header.was_running && virDomainObjIsActive(vm)) {
2612
 
                rc = qemuProcessStartCPUs(driver, vm, dom->conn,
2613
 
                                          VIR_DOMAIN_RUNNING_SAVE_CANCELED,
2614
 
                                          QEMU_ASYNC_JOB_SAVE);
2615
 
                if (rc < 0)
2616
 
                    VIR_WARN("Unable to resume guest CPUs after save failure");
2617
 
            }
2618
 
        }
2619
 
        if (qemuDomainObjEndAsyncJob(driver, vm) == 0)
2620
 
            vm = NULL;
2621
 
    }
2622
 
 
2623
 
cleanup:
2624
 
    VIR_FORCE_CLOSE(fd);
2625
 
    virFileDirectFdFree(directFd);
2626
 
    VIR_FREE(xml);
2627
 
    if (ret != 0 && needUnlink)
2628
 
        unlink(path);
2629
 
    if (event)
2630
 
        qemuDomainEventQueue(driver, event);
2631
 
    if (vm)
2632
 
        virDomainObjUnlock(vm);
2633
 
    return ret;
2634
 
}
2635
 
 
2636
 
/* Returns true if a compression program is available in PATH */
2637
 
static bool qemudCompressProgramAvailable(enum qemud_save_formats compress)
2638
 
{
2639
 
    const char *prog;
2640
 
    char *c;
2641
 
 
2642
 
    if (compress == QEMUD_SAVE_FORMAT_RAW)
2643
 
        return true;
2644
 
    prog = qemudSaveCompressionTypeToString(compress);
2645
 
    c = virFindFileInPath(prog);
2646
 
    if (!c)
2647
 
        return false;
2648
 
    VIR_FREE(c);
2649
 
    return true;
2650
 
}
2651
 
 
2652
 
static int
2653
 
qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
2654
 
                    unsigned int flags)
2655
 
{
2656
 
    struct qemud_driver *driver = dom->conn->privateData;
2657
 
    int compressed;
2658
 
    int ret = -1;
2659
 
    virDomainObjPtr vm = NULL;
2660
 
 
2661
 
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
2662
 
                  VIR_DOMAIN_SAVE_RUNNING |
2663
 
                  VIR_DOMAIN_SAVE_PAUSED, -1);
2664
 
 
2665
 
    qemuDriverLock(driver);
2666
 
 
2667
 
    if (driver->saveImageFormat == NULL)
2668
 
        compressed = QEMUD_SAVE_FORMAT_RAW;
2669
 
    else {
2670
 
        compressed = qemudSaveCompressionTypeFromString(driver->saveImageFormat);
2671
 
        if (compressed < 0) {
2672
 
            qemuReportError(VIR_ERR_OPERATION_FAILED,
2673
 
                            "%s", _("Invalid save image format specified "
2674
 
                                    "in configuration file"));
2675
 
            goto cleanup;
2676
 
        }
2677
 
        if (!qemudCompressProgramAvailable(compressed)) {
2678
 
            qemuReportError(VIR_ERR_OPERATION_FAILED,
2679
 
                            "%s", _("Compression program for image format "
2680
 
                                    "in configuration file isn't available"));
2681
 
            goto cleanup;
2682
 
        }
2683
 
    }
2684
 
 
2685
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2686
 
    if (!vm) {
2687
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2688
 
        virUUIDFormat(dom->uuid, uuidstr);
2689
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2690
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2691
 
        goto cleanup;
2692
 
    }
2693
 
 
2694
 
    if (!virDomainObjIsActive(vm)) {
2695
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
2696
 
                        "%s", _("domain is not running"));
2697
 
        goto cleanup;
2698
 
    }
2699
 
 
2700
 
    ret = qemuDomainSaveInternal(driver, dom, vm, path, compressed,
2701
 
                                 dxml, flags);
2702
 
    vm = NULL;
2703
 
 
2704
 
cleanup:
2705
 
    if (vm)
2706
 
        virDomainObjUnlock(vm);
2707
 
    qemuDriverUnlock(driver);
2708
 
 
2709
 
    return ret;
2710
 
}
2711
 
 
2712
 
static int
2713
 
qemuDomainSave(virDomainPtr dom, const char *path)
2714
 
{
2715
 
    return qemuDomainSaveFlags(dom, path, NULL, 0);
2716
 
}
2717
 
 
2718
 
static char *
2719
 
qemuDomainManagedSavePath(struct qemud_driver *driver, virDomainObjPtr vm) {
2720
 
    char *ret;
2721
 
 
2722
 
    if (virAsprintf(&ret, "%s/%s.save", driver->saveDir, vm->def->name) < 0) {
2723
 
        virReportOOMError();
2724
 
        return(NULL);
2725
 
    }
2726
 
 
2727
 
    return(ret);
2728
 
}
2729
 
 
2730
 
static int
2731
 
qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
2732
 
{
2733
 
    struct qemud_driver *driver = dom->conn->privateData;
2734
 
    virDomainObjPtr vm = NULL;
2735
 
    char *name = NULL;
2736
 
    int ret = -1;
2737
 
    int compressed;
2738
 
 
2739
 
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
2740
 
                  VIR_DOMAIN_SAVE_RUNNING |
2741
 
                  VIR_DOMAIN_SAVE_PAUSED, -1);
2742
 
 
2743
 
    qemuDriverLock(driver);
2744
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2745
 
    if (!vm) {
2746
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2747
 
        virUUIDFormat(dom->uuid, uuidstr);
2748
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2749
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2750
 
        goto cleanup;
2751
 
    }
2752
 
 
2753
 
    if (!virDomainObjIsActive(vm)) {
2754
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
2755
 
                        "%s", _("domain is not running"));
2756
 
        goto cleanup;
2757
 
    }
2758
 
    if (!vm->persistent) {
2759
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
2760
 
                        _("cannot do managed save for transient domain"));
2761
 
        goto cleanup;
2762
 
    }
2763
 
 
2764
 
    name = qemuDomainManagedSavePath(driver, vm);
2765
 
    if (name == NULL)
2766
 
        goto cleanup;
2767
 
 
2768
 
    VIR_INFO("Saving state to %s", name);
2769
 
 
2770
 
    compressed = QEMUD_SAVE_FORMAT_RAW;
2771
 
    ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed,
2772
 
                                 NULL, flags);
2773
 
    vm = NULL;
2774
 
 
2775
 
cleanup:
2776
 
    if (vm)
2777
 
        virDomainObjUnlock(vm);
2778
 
    qemuDriverUnlock(driver);
2779
 
    VIR_FREE(name);
2780
 
 
2781
 
    return ret;
2782
 
}
2783
 
 
2784
 
static int
2785
 
qemuDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
2786
 
{
2787
 
    struct qemud_driver *driver = dom->conn->privateData;
2788
 
    virDomainObjPtr vm = NULL;
2789
 
    int ret = -1;
2790
 
    char *name = NULL;
2791
 
 
2792
 
    virCheckFlags(0, -1);
2793
 
 
2794
 
    qemuDriverLock(driver);
2795
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2796
 
    if (!vm) {
2797
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2798
 
        virUUIDFormat(dom->uuid, uuidstr);
2799
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2800
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2801
 
        goto cleanup;
2802
 
    }
2803
 
 
2804
 
    name = qemuDomainManagedSavePath(driver, vm);
2805
 
    if (name == NULL)
2806
 
        goto cleanup;
2807
 
 
2808
 
    ret = virFileExists(name);
2809
 
 
2810
 
cleanup:
2811
 
    VIR_FREE(name);
2812
 
    if (vm)
2813
 
        virDomainObjUnlock(vm);
2814
 
    qemuDriverUnlock(driver);
2815
 
    return ret;
2816
 
}
2817
 
 
2818
 
static int
2819
 
qemuDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
2820
 
{
2821
 
    struct qemud_driver *driver = dom->conn->privateData;
2822
 
    virDomainObjPtr vm = NULL;
2823
 
    int ret = -1;
2824
 
    char *name = NULL;
2825
 
 
2826
 
    virCheckFlags(0, -1);
2827
 
 
2828
 
    qemuDriverLock(driver);
2829
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2830
 
    if (!vm) {
2831
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2832
 
        virUUIDFormat(dom->uuid, uuidstr);
2833
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2834
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2835
 
        goto cleanup;
2836
 
    }
2837
 
 
2838
 
    name = qemuDomainManagedSavePath(driver, vm);
2839
 
    if (name == NULL)
2840
 
        goto cleanup;
2841
 
 
2842
 
    ret = unlink(name);
2843
 
 
2844
 
cleanup:
2845
 
    VIR_FREE(name);
2846
 
    if (vm)
2847
 
        virDomainObjUnlock(vm);
2848
 
    qemuDriverUnlock(driver);
2849
 
    return ret;
2850
 
}
2851
 
 
2852
 
static int
2853
 
doCoreDump(struct qemud_driver *driver,
2854
 
           virDomainObjPtr vm,
2855
 
           const char *path,
2856
 
           enum qemud_save_formats compress,
2857
 
           bool bypass_cache)
2858
 
{
2859
 
    int fd = -1;
2860
 
    int ret = -1;
2861
 
    virFileDirectFdPtr directFd = NULL;
2862
 
    int directFlag = 0;
2863
 
 
2864
 
    /* Create an empty file with appropriate ownership.  */
2865
 
    if (bypass_cache) {
2866
 
        directFlag = virFileDirectFdFlag();
2867
 
        if (directFlag < 0) {
2868
 
            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
2869
 
                            _("bypass cache unsupported by this system"));
2870
 
            goto cleanup;
2871
 
        }
2872
 
    }
2873
 
    /* Core dumps usually imply last-ditch analysis efforts are
2874
 
     * desired, so we intentionally do not unlink even if a file was
2875
 
     * created.  */
2876
 
    if ((fd = qemuOpenFile(driver, path,
2877
 
                           O_CREAT | O_TRUNC | O_WRONLY | directFlag,
2878
 
                           NULL, NULL)) < 0)
2879
 
        goto cleanup;
2880
 
 
2881
 
    if (bypass_cache && (directFd = virFileDirectFdNew(&fd, path)) == NULL)
2882
 
        goto cleanup;
2883
 
 
2884
 
    if (qemuMigrationToFile(driver, vm, fd, 0, path,
2885
 
                            qemuCompressProgramName(compress), false,
2886
 
                            QEMU_ASYNC_JOB_DUMP) < 0)
2887
 
        goto cleanup;
2888
 
 
2889
 
    if (VIR_CLOSE(fd) < 0) {
2890
 
        virReportSystemError(errno,
2891
 
                             _("unable to save file %s"),
2892
 
                             path);
2893
 
        goto cleanup;
2894
 
    }
2895
 
    if (virFileDirectFdClose(directFd) < 0)
2896
 
        goto cleanup;
2897
 
 
2898
 
    ret = 0;
2899
 
 
2900
 
cleanup:
2901
 
    VIR_FORCE_CLOSE(fd);
2902
 
    virFileDirectFdFree(directFd);
2903
 
    if (ret != 0)
2904
 
        unlink(path);
2905
 
    return ret;
2906
 
}
2907
 
 
2908
 
static enum qemud_save_formats
2909
 
getCompressionType(struct qemud_driver *driver)
2910
 
{
2911
 
    int compress = QEMUD_SAVE_FORMAT_RAW;
2912
 
 
2913
 
    /*
2914
 
     * We reuse "save" flag for "dump" here. Then, we can support the same
2915
 
     * format in "save" and "dump".
2916
 
     */
2917
 
    if (driver->dumpImageFormat) {
2918
 
        compress = qemudSaveCompressionTypeFromString(driver->dumpImageFormat);
2919
 
        /* Use "raw" as the format if the specified format is not valid,
2920
 
         * or the compress program is not available.
2921
 
         */
2922
 
        if (compress < 0) {
2923
 
            VIR_WARN("%s", _("Invalid dump image format specified in "
2924
 
                             "configuration file, using raw"));
2925
 
            return QEMUD_SAVE_FORMAT_RAW;
2926
 
        }
2927
 
        if (!qemudCompressProgramAvailable(compress)) {
2928
 
            VIR_WARN("%s", _("Compression program for dump image format "
2929
 
                             "in configuration file isn't available, "
2930
 
                             "using raw"));
2931
 
            return QEMUD_SAVE_FORMAT_RAW;
2932
 
        }
2933
 
    }
2934
 
    return compress;
2935
 
}
2936
 
 
2937
 
static int qemudDomainCoreDump(virDomainPtr dom,
2938
 
                               const char *path,
2939
 
                               unsigned int flags)
2940
 
{
2941
 
    struct qemud_driver *driver = dom->conn->privateData;
2942
 
    virDomainObjPtr vm;
2943
 
    qemuDomainObjPrivatePtr priv;
2944
 
    int resume = 0, paused = 0;
2945
 
    int ret = -1;
2946
 
    virDomainEventPtr event = NULL;
2947
 
 
2948
 
    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
2949
 
                  VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET, -1);
2950
 
 
2951
 
    qemuDriverLock(driver);
2952
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2953
 
 
2954
 
    if (!vm) {
2955
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
2956
 
        virUUIDFormat(dom->uuid, uuidstr);
2957
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
2958
 
                        _("no domain with matching uuid '%s'"), uuidstr);
2959
 
        goto cleanup;
2960
 
    }
2961
 
 
2962
 
    if (qemuDomainObjBeginAsyncJobWithDriver(driver, vm,
2963
 
                                             QEMU_ASYNC_JOB_DUMP) < 0)
2964
 
        goto cleanup;
2965
 
 
2966
 
    if (!virDomainObjIsActive(vm)) {
2967
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
2968
 
                        "%s", _("domain is not running"));
2969
 
        goto endjob;
2970
 
    }
2971
 
 
2972
 
    /* Migrate will always stop the VM, so the resume condition is
2973
 
       independent of whether the stop command is issued.  */
2974
 
    resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
2975
 
 
2976
 
    /* Pause domain for non-live dump */
2977
 
    if (!(flags & VIR_DUMP_LIVE) &&
2978
 
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
2979
 
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_DUMP,
2980
 
                                QEMU_ASYNC_JOB_DUMP) < 0)
2981
 
            goto endjob;
2982
 
        paused = 1;
2983
 
 
2984
 
        if (!virDomainObjIsActive(vm)) {
2985
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2986
 
                            _("guest unexpectedly quit"));
2987
 
            goto endjob;
2988
 
        }
2989
 
    }
2990
 
 
2991
 
    ret = doCoreDump(driver, vm, path, getCompressionType(driver),
2992
 
                     (flags & VIR_DUMP_BYPASS_CACHE) != 0);
2993
 
    if (ret < 0)
2994
 
        goto endjob;
2995
 
 
2996
 
    paused = 1;
2997
 
 
2998
 
endjob:
2999
 
    if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
3000
 
        qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_CRASHED);
3001
 
        virDomainAuditStop(vm, "crashed");
3002
 
        event = virDomainEventNewFromObj(vm,
3003
 
                                         VIR_DOMAIN_EVENT_STOPPED,
3004
 
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
3005
 
    }
3006
 
 
3007
 
    /* Since the monitor is always attached to a pty for libvirt, it
3008
 
       will support synchronous operations so we always get here after
3009
 
       the migration is complete.  */
3010
 
    else if (((resume && paused) || (flags & VIR_DUMP_RESET)) &&
3011
 
             virDomainObjIsActive(vm)) {
3012
 
        if ((ret == 0) && (flags & VIR_DUMP_RESET)) {
3013
 
            priv =  vm->privateData;
3014
 
            qemuDomainObjEnterMonitorWithDriver(driver, vm);
3015
 
            ret = qemuMonitorSystemReset(priv->mon);
3016
 
            qemuDomainObjExitMonitorWithDriver(driver, vm);
3017
 
        }
3018
 
 
3019
 
        if (resume && qemuProcessStartCPUs(driver, vm, dom->conn,
3020
 
                                           VIR_DOMAIN_RUNNING_UNPAUSED,
3021
 
                                           QEMU_ASYNC_JOB_DUMP) < 0) {
3022
 
            if (virGetLastError() == NULL)
3023
 
                qemuReportError(VIR_ERR_OPERATION_FAILED,
3024
 
                                "%s", _("resuming after dump failed"));
3025
 
        }
3026
 
    }
3027
 
 
3028
 
    if (qemuDomainObjEndAsyncJob(driver, vm) == 0)
3029
 
        vm = NULL;
3030
 
    else if ((ret == 0) && (flags & VIR_DUMP_CRASH) && !vm->persistent) {
3031
 
        qemuDomainRemoveInactive(driver, vm);
3032
 
        vm = NULL;
3033
 
    }
3034
 
 
3035
 
cleanup:
3036
 
    if (vm)
3037
 
        virDomainObjUnlock(vm);
3038
 
    if (event)
3039
 
        qemuDomainEventQueue(driver, event);
3040
 
    qemuDriverUnlock(driver);
3041
 
    return ret;
3042
 
}
3043
 
 
3044
 
static char *
3045
 
qemuDomainScreenshot(virDomainPtr dom,
3046
 
                     virStreamPtr st,
3047
 
                     unsigned int screen,
3048
 
                     unsigned int flags)
3049
 
{
3050
 
    struct qemud_driver *driver = dom->conn->privateData;
3051
 
    virDomainObjPtr vm;
3052
 
    qemuDomainObjPrivatePtr priv;
3053
 
    char *tmp = NULL;
3054
 
    int tmp_fd = -1;
3055
 
    char *ret = NULL;
3056
 
    bool unlink_tmp = false;
3057
 
 
3058
 
    virCheckFlags(0, NULL);
3059
 
 
3060
 
    qemuDriverLock(driver);
3061
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3062
 
    qemuDriverUnlock(driver);
3063
 
 
3064
 
    if (!vm) {
3065
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
3066
 
        virUUIDFormat(dom->uuid, uuidstr);
3067
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
3068
 
                        _("no domain matching uuid '%s'"), uuidstr);
3069
 
        goto cleanup;
3070
 
    }
3071
 
 
3072
 
    priv = vm->privateData;
3073
 
 
3074
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
3075
 
        goto cleanup;
3076
 
 
3077
 
    if (!virDomainObjIsActive(vm)) {
3078
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
3079
 
                        "%s", _("domain is not running"));
3080
 
        goto endjob;
3081
 
    }
3082
 
 
3083
 
    /* Well, even if qemu allows multiple graphic cards, heads, whatever,
3084
 
     * screenshot command does not */
3085
 
    if (screen) {
3086
 
        qemuReportError(VIR_ERR_INVALID_ARG,
3087
 
                        "%s", _("currently is supported only taking "
3088
 
                                "screenshots of screen ID 0"));
3089
 
        goto endjob;
3090
 
    }
3091
 
 
3092
 
    if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", driver->cacheDir) < 0) {
3093
 
        virReportOOMError();
3094
 
        goto endjob;
3095
 
    }
3096
 
 
3097
 
    if ((tmp_fd = mkstemp(tmp)) == -1) {
3098
 
        virReportSystemError(errno, _("mkstemp(\"%s\") failed"), tmp);
3099
 
        goto endjob;
3100
 
    }
3101
 
    unlink_tmp = true;
3102
 
 
3103
 
    virSecurityManagerSetSavedStateLabel(qemu_driver->securityManager, vm, tmp);
3104
 
 
3105
 
    qemuDomainObjEnterMonitor(driver, vm);
3106
 
    if (qemuMonitorScreendump(priv->mon, tmp) < 0) {
3107
 
        qemuDomainObjExitMonitor(driver, vm);
3108
 
        goto endjob;
3109
 
    }
3110
 
    qemuDomainObjExitMonitor(driver, vm);
3111
 
 
3112
 
    if (VIR_CLOSE(tmp_fd) < 0) {
3113
 
        virReportSystemError(errno, _("unable to close %s"), tmp);
3114
 
        goto endjob;
3115
 
    }
3116
 
 
3117
 
    if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
3118
 
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
3119
 
                        _("unable to open stream"));
3120
 
        goto endjob;
3121
 
    }
3122
 
 
3123
 
    ret = strdup("image/x-portable-pixmap");
3124
 
 
3125
 
endjob:
3126
 
    VIR_FORCE_CLOSE(tmp_fd);
3127
 
    if (unlink_tmp)
3128
 
        unlink(tmp);
3129
 
    VIR_FREE(tmp);
3130
 
 
3131
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
3132
 
        vm = NULL;
3133
 
 
3134
 
cleanup:
3135
 
    if (vm)
3136
 
        virDomainObjUnlock(vm);
3137
 
    return ret;
3138
 
}
3139
 
 
3140
 
static void processWatchdogEvent(void *data, void *opaque)
3141
 
{
3142
 
    int ret;
3143
 
    struct qemuDomainWatchdogEvent *wdEvent = data;
3144
 
    struct qemud_driver *driver = opaque;
3145
 
 
3146
 
    qemuDriverLock(driver);
3147
 
    virDomainObjLock(wdEvent->vm);
3148
 
 
3149
 
    switch (wdEvent->action) {
3150
 
    case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
3151
 
        {
3152
 
            char *dumpfile;
3153
 
 
3154
 
            if (virAsprintf(&dumpfile, "%s/%s-%u",
3155
 
                            driver->autoDumpPath,
3156
 
                            wdEvent->vm->def->name,
3157
 
                            (unsigned int)time(NULL)) < 0) {
3158
 
                virReportOOMError();
3159
 
                goto unlock;
3160
 
            }
3161
 
 
3162
 
            if (qemuDomainObjBeginAsyncJobWithDriver(driver, wdEvent->vm,
3163
 
                                                     QEMU_ASYNC_JOB_DUMP) < 0) {
3164
 
                VIR_FREE(dumpfile);
3165
 
                goto unlock;
3166
 
            }
3167
 
 
3168
 
            if (!virDomainObjIsActive(wdEvent->vm)) {
3169
 
                qemuReportError(VIR_ERR_OPERATION_INVALID,
3170
 
                                "%s", _("domain is not running"));
3171
 
                VIR_FREE(dumpfile);
3172
 
                goto endjob;
3173
 
            }
3174
 
 
3175
 
            ret = doCoreDump(driver, wdEvent->vm, dumpfile,
3176
 
                             getCompressionType(driver),
3177
 
                             driver->autoDumpBypassCache);
3178
 
            if (ret < 0)
3179
 
                qemuReportError(VIR_ERR_OPERATION_FAILED,
3180
 
                                "%s", _("Dump failed"));
3181
 
 
3182
 
            ret = qemuProcessStartCPUs(driver, wdEvent->vm, NULL,
3183
 
                                       VIR_DOMAIN_RUNNING_UNPAUSED,
3184
 
                                       QEMU_ASYNC_JOB_DUMP);
3185
 
 
3186
 
            if (ret < 0)
3187
 
                qemuReportError(VIR_ERR_OPERATION_FAILED,
3188
 
                                "%s", _("Resuming after dump failed"));
3189
 
 
3190
 
            VIR_FREE(dumpfile);
3191
 
        }
3192
 
        break;
3193
 
    default:
3194
 
        goto unlock;
3195
 
    }
3196
 
 
3197
 
endjob:
3198
 
    /* Safe to ignore value since ref count was incremented in
3199
 
     * qemuProcessHandleWatchdog().
3200
 
     */
3201
 
    ignore_value(qemuDomainObjEndAsyncJob(driver, wdEvent->vm));
3202
 
 
3203
 
unlock:
3204
 
    if (virDomainObjUnref(wdEvent->vm) > 0)
3205
 
        virDomainObjUnlock(wdEvent->vm);
3206
 
    qemuDriverUnlock(driver);
3207
 
    VIR_FREE(wdEvent);
3208
 
}
3209
 
 
3210
 
static int qemudDomainHotplugVcpus(struct qemud_driver *driver,
3211
 
                                   virDomainObjPtr vm,
3212
 
                                   unsigned int nvcpus)
3213
 
{
3214
 
    qemuDomainObjPrivatePtr priv = vm->privateData;
3215
 
    int i, rc = 1;
3216
 
    int ret = -1;
3217
 
    int oldvcpus = vm->def->vcpus;
3218
 
    int vcpus = oldvcpus;
3219
 
 
3220
 
    qemuDomainObjEnterMonitor(driver, vm);
3221
 
 
3222
 
    /* We need different branches here, because we want to offline
3223
 
     * in reverse order to onlining, so any partial fail leaves us in a
3224
 
     * reasonably sensible state */
3225
 
    if (nvcpus > vcpus) {
3226
 
        for (i = vcpus ; i < nvcpus ; i++) {
3227
 
            /* Online new CPU */
3228
 
            rc = qemuMonitorSetCPU(priv->mon, i, 1);
3229
 
            if (rc == 0)
3230
 
                goto unsupported;
3231
 
            if (rc < 0)
3232
 
                goto cleanup;
3233
 
 
3234
 
            vcpus++;
3235
 
        }
3236
 
    } else {
3237
 
        for (i = vcpus - 1 ; i >= nvcpus ; i--) {
3238
 
            /* Offline old CPU */
3239
 
            rc = qemuMonitorSetCPU(priv->mon, i, 0);
3240
 
            if (rc == 0)
3241
 
                goto unsupported;
3242
 
            if (rc < 0)
3243
 
                goto cleanup;
3244
 
 
3245
 
            vcpus--;
3246
 
        }
3247
 
    }
3248
 
 
3249
 
    ret = 0;
3250
 
 
3251
 
cleanup:
3252
 
    qemuDomainObjExitMonitor(driver, vm);
3253
 
    vm->def->vcpus = vcpus;
3254
 
    virDomainAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1);
3255
 
    return ret;
3256
 
 
3257
 
unsupported:
3258
 
    qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3259
 
                    _("cannot change vcpu count of this domain"));
3260
 
    goto cleanup;
3261
 
}
3262
 
 
3263
 
 
3264
 
static int
3265
 
qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
3266
 
                        unsigned int flags)
3267
 
{
3268
 
    struct qemud_driver *driver = dom->conn->privateData;
3269
 
    virDomainObjPtr vm;
3270
 
    virDomainDefPtr persistentDef;
3271
 
    const char * type;
3272
 
    int max;
3273
 
    int ret = -1;
3274
 
    bool isActive;
3275
 
    bool maximum;
3276
 
 
3277
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
3278
 
                  VIR_DOMAIN_AFFECT_CONFIG |
3279
 
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);
3280
 
 
3281
 
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
3282
 
        qemuReportError(VIR_ERR_INVALID_ARG,
3283
 
                        _("argument out of range: %d"), nvcpus);
3284
 
        return -1;
3285
 
    }
3286
 
 
3287
 
    qemuDriverLock(driver);
3288
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3289
 
    qemuDriverUnlock(driver);
3290
 
 
3291
 
    if (!vm) {
3292
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
3293
 
        virUUIDFormat(dom->uuid, uuidstr);
3294
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
3295
 
                        _("no domain with matching uuid '%s'"), uuidstr);
3296
 
        goto cleanup;
3297
 
    }
3298
 
 
3299
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
3300
 
        goto cleanup;
3301
 
 
3302
 
    isActive = virDomainObjIsActive(vm);
3303
 
    maximum = (flags & VIR_DOMAIN_VCPU_MAXIMUM) != 0;
3304
 
    flags &= ~VIR_DOMAIN_VCPU_MAXIMUM;
3305
 
 
3306
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
3307
 
        if (isActive)
3308
 
            flags |= VIR_DOMAIN_AFFECT_LIVE;
3309
 
        else
3310
 
            flags |= VIR_DOMAIN_AFFECT_CONFIG;
3311
 
    }
3312
 
 
3313
 
    /* MAXIMUM cannot be mixed with LIVE.  */
3314
 
    if (maximum && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
3315
 
        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
3316
 
                        _("cannot adjust maximum on running domain"));
3317
 
        goto endjob;
3318
 
    }
3319
 
 
3320
 
    if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
3321
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
3322
 
                         "%s", _("domain is not running"));
3323
 
        goto endjob;
3324
 
    }
3325
 
 
3326
 
    if (!vm->persistent && (flags & VIR_DOMAIN_AFFECT_CONFIG)) {
3327
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
3328
 
                        _("cannot change persistent config of a transient domain"));
3329
 
        goto endjob;
3330
 
    }
3331
 
 
3332
 
    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
3333
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
3334
 
                        _("unknown virt type in domain definition '%d'"),
3335
 
                        vm->def->virtType);
3336
 
        goto endjob;
3337
 
    }
3338
 
 
3339
 
    if ((max = qemudGetMaxVCPUs(NULL, type)) < 0) {
3340
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3341
 
                        _("could not determine max vcpus for the domain"));
3342
 
        goto endjob;
3343
 
    }
3344
 
 
3345
 
    if (!maximum && vm->def->maxvcpus < max) {
3346
 
        max = vm->def->maxvcpus;
3347
 
    }
3348
 
 
3349
 
    if (nvcpus > max) {
3350
 
        qemuReportError(VIR_ERR_INVALID_ARG,
3351
 
                        _("requested vcpus is greater than max allowable"
3352
 
                          " vcpus for the domain: %d > %d"), nvcpus, max);
3353
 
        goto endjob;
3354
 
    }
3355
 
 
3356
 
    if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
3357
 
        goto endjob;
3358
 
 
3359
 
    switch (flags) {
3360
 
    case VIR_DOMAIN_AFFECT_CONFIG:
3361
 
        if (maximum) {
3362
 
            persistentDef->maxvcpus = nvcpus;
3363
 
            if (nvcpus < persistentDef->vcpus)
3364
 
                persistentDef->vcpus = nvcpus;
3365
 
        } else {
3366
 
            persistentDef->vcpus = nvcpus;
3367
 
        }
3368
 
        ret = 0;
3369
 
        break;
3370
 
 
3371
 
    case VIR_DOMAIN_AFFECT_LIVE:
3372
 
        ret = qemudDomainHotplugVcpus(driver, vm, nvcpus);
3373
 
        break;
3374
 
 
3375
 
    case VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG:
3376
 
        ret = qemudDomainHotplugVcpus(driver, vm, nvcpus);
3377
 
        if (ret == 0) {
3378
 
            persistentDef->vcpus = nvcpus;
3379
 
        }
3380
 
        break;
3381
 
    }
3382
 
 
3383
 
    /* Save the persistent config to disk */
3384
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG)
3385
 
        ret = virDomainSaveConfig(driver->configDir, persistentDef);
3386
 
 
3387
 
endjob:
3388
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
3389
 
        vm = NULL;
3390
 
 
3391
 
cleanup:
3392
 
    if (vm)
3393
 
        virDomainObjUnlock(vm);
3394
 
    return ret;
3395
 
}
3396
 
 
3397
 
static int
3398
 
qemuDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
3399
 
{
3400
 
    return qemuDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE);
3401
 
}
3402
 
 
3403
 
 
3404
 
static int
3405
 
qemudDomainPinVcpuFlags(virDomainPtr dom,
3406
 
                        unsigned int vcpu,
3407
 
                        unsigned char *cpumap,
3408
 
                        int maplen,
3409
 
                        unsigned int flags) {
3410
 
 
3411
 
    struct qemud_driver *driver = dom->conn->privateData;
3412
 
    virDomainObjPtr vm;
3413
 
    virDomainDefPtr persistentDef = NULL;
3414
 
    int maxcpu, hostcpus;
3415
 
    virNodeInfo nodeinfo;
3416
 
    int ret = -1;
3417
 
    bool isActive;
3418
 
    qemuDomainObjPrivatePtr priv;
3419
 
    bool canResetting = true;
3420
 
    int pcpu;
3421
 
 
3422
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
3423
 
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
3424
 
 
3425
 
    qemuDriverLock(driver);
3426
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3427
 
    qemuDriverUnlock(driver);
3428
 
 
3429
 
    if (!vm) {
3430
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
3431
 
        virUUIDFormat(dom->uuid, uuidstr);
3432
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
3433
 
                        _("no domain with matching uuid '%s'"), uuidstr);
3434
 
        goto cleanup;
3435
 
    }
3436
 
 
3437
 
    isActive = virDomainObjIsActive(vm);
3438
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
3439
 
        if (isActive)
3440
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
3441
 
        else
3442
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
3443
 
    }
3444
 
 
3445
 
    if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
3446
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
3447
 
                        _("a domain is inactive; can change only "
3448
 
                          "persistent config"));
3449
 
        goto cleanup;
3450
 
    }
3451
 
 
3452
 
    priv = vm->privateData;
3453
 
 
3454
 
    if (vcpu > (priv->nvcpupids-1)) {
3455
 
        qemuReportError(VIR_ERR_INVALID_ARG,
3456
 
                        _("vcpu number out of range %d > %d"),
3457
 
                        vcpu, priv->nvcpupids);
3458
 
        goto cleanup;
3459
 
    }
3460
 
 
3461
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
3462
 
        if (!vm->persistent) {
3463
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
3464
 
                   _("cannot change persistent config of a transient domain"));
3465
 
            goto cleanup;
3466
 
        }
3467
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
3468
 
            goto cleanup;
3469
 
    }
3470
 
 
3471
 
    if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
3472
 
        goto cleanup;
3473
 
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
3474
 
    maxcpu = maplen * 8;
3475
 
    if (maxcpu > hostcpus)
3476
 
        maxcpu = hostcpus;
3477
 
    /* pinning to all physical cpus means resetting,
3478
 
     * so check if we can reset setting.
3479
 
     */
3480
 
    for (pcpu = 0; pcpu < hostcpus; pcpu++) {
3481
 
        if ((cpumap[pcpu/8] & (1 << (pcpu % 8))) == 0) {
3482
 
            canResetting = false;
3483
 
            break;
3484
 
        }
3485
 
    }
3486
 
 
3487
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
3488
 
 
3489
 
        if (priv->vcpupids != NULL) {
3490
 
            if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
3491
 
                                          cpumap, maplen, maxcpu) < 0)
3492
 
                goto cleanup;
3493
 
        } else {
3494
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
3495
 
                            "%s", _("cpu affinity is not supported"));
3496
 
            goto cleanup;
3497
 
        }
3498
 
 
3499
 
        if (canResetting) {
3500
 
            if (virDomainVcpuPinDel(vm->def, vcpu) < 0) {
3501
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3502
 
                                _("failed to delete vcpupin xml of "
3503
 
                                  "a running domain"));
3504
 
                goto cleanup;
3505
 
            }
3506
 
        } else {
3507
 
            if (virDomainVcpuPinAdd(vm->def, cpumap, maplen, vcpu) < 0) {
3508
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3509
 
                                _("failed to update or add vcpupin xml of "
3510
 
                                  "a running domain"));
3511
 
                goto cleanup;
3512
 
            }
3513
 
        }
3514
 
 
3515
 
        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
3516
 
            goto cleanup;
3517
 
    }
3518
 
 
3519
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
3520
 
 
3521
 
        if (canResetting) {
3522
 
            if (virDomainVcpuPinDel(persistentDef, vcpu) < 0) {
3523
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3524
 
                                _("failed to delete vcpupin xml of "
3525
 
                                  "a persistent domain"));
3526
 
                goto cleanup;
3527
 
            }
3528
 
        } else {
3529
 
            if (virDomainVcpuPinAdd(persistentDef, cpumap, maplen, vcpu) < 0) {
3530
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3531
 
                                _("failed to update or add vcpupin xml of "
3532
 
                                  "a persistent domain"));
3533
 
                goto cleanup;
3534
 
            }
3535
 
        }
3536
 
 
3537
 
        ret = virDomainSaveConfig(driver->configDir, persistentDef);
3538
 
        goto cleanup;
3539
 
    }
3540
 
 
3541
 
    ret = 0;
3542
 
 
3543
 
cleanup:
3544
 
    if (vm)
3545
 
        virDomainObjUnlock(vm);
3546
 
    return ret;
3547
 
}
3548
 
 
3549
 
static int
3550
 
qemudDomainPinVcpu(virDomainPtr dom,
3551
 
                   unsigned int vcpu,
3552
 
                   unsigned char *cpumap,
3553
 
                   int maplen) {
3554
 
    return qemudDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
3555
 
                                   VIR_DOMAIN_AFFECT_LIVE);
3556
 
}
3557
 
 
3558
 
static int
3559
 
qemudDomainGetVcpuPinInfo(virDomainPtr dom,
3560
 
                          int ncpumaps,
3561
 
                          unsigned char *cpumaps,
3562
 
                          int maplen,
3563
 
                          unsigned int flags) {
3564
 
 
3565
 
    struct qemud_driver *driver = dom->conn->privateData;
3566
 
    virDomainObjPtr vm = NULL;
3567
 
    virNodeInfo nodeinfo;
3568
 
    virDomainDefPtr targetDef = NULL;
3569
 
    int ret = -1;
3570
 
    bool isActive;
3571
 
    int maxcpu, hostcpus, vcpu, pcpu;
3572
 
    int n;
3573
 
    virDomainVcpuPinDefPtr *vcpupin_list;
3574
 
    char *cpumask = NULL;
3575
 
    unsigned char *cpumap;
3576
 
 
3577
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
3578
 
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
3579
 
 
3580
 
    qemuDriverLock(driver);
3581
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3582
 
    qemuDriverUnlock(driver);
3583
 
 
3584
 
    if (!vm) {
3585
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
3586
 
        virUUIDFormat(dom->uuid, uuidstr);
3587
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
3588
 
                        _("no domain with matching uuid '%s'"), uuidstr);
3589
 
        goto cleanup;
3590
 
    }
3591
 
 
3592
 
    isActive = virDomainObjIsActive(vm);
3593
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
3594
 
        if (isActive)
3595
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
3596
 
        else
3597
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
3598
 
    }
3599
 
 
3600
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
3601
 
        if (!isActive) {
3602
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
3603
 
                            "%s", _("domain is not running"));
3604
 
            goto cleanup;
3605
 
        }
3606
 
        targetDef = vm->def;
3607
 
    }
3608
 
 
3609
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
3610
 
        if (!vm->persistent) {
3611
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
3612
 
                   _("cannot get persistent config of a transient domain"));
3613
 
            goto cleanup;
3614
 
        }
3615
 
        if (!(targetDef = virDomainObjGetPersistentDef(driver->caps, vm)))
3616
 
            goto cleanup;
3617
 
    }
3618
 
 
3619
 
    /* Coverity didn't realize that targetDef must be set if we got here.  */
3620
 
    sa_assert(targetDef);
3621
 
 
3622
 
    if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
3623
 
        goto cleanup;
3624
 
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
3625
 
    maxcpu = maplen * 8;
3626
 
    if (maxcpu > hostcpus)
3627
 
        maxcpu = hostcpus;
3628
 
 
3629
 
    /* Clamp to actual number of vcpus */
3630
 
    if (ncpumaps > targetDef->vcpus)
3631
 
        ncpumaps = targetDef->vcpus;
3632
 
 
3633
 
    if (ncpumaps < 1) {
3634
 
        goto cleanup;
3635
 
    }
3636
 
 
3637
 
    /* initialize cpumaps */
3638
 
    memset(cpumaps, 0xff, maplen * ncpumaps);
3639
 
    if (maxcpu % 8) {
3640
 
        for (vcpu = 0; vcpu < ncpumaps; vcpu++) {
3641
 
            cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
3642
 
            cpumap[maplen - 1] &= (1 << maxcpu % 8) - 1;
3643
 
        }
3644
 
    }
3645
 
 
3646
 
    /* if vcpupin setting exists, there are unused physical cpus */
3647
 
    for (n = 0; n < targetDef->cputune.nvcpupin; n++) {
3648
 
        vcpupin_list = targetDef->cputune.vcpupin;
3649
 
        vcpu = vcpupin_list[n]->vcpuid;
3650
 
        cpumask = vcpupin_list[n]->cpumask;
3651
 
        cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
3652
 
        for (pcpu = 0; pcpu < maxcpu; pcpu++) {
3653
 
            if (cpumask[pcpu] == 0)
3654
 
                VIR_UNUSE_CPU(cpumap, pcpu);
3655
 
        }
3656
 
    }
3657
 
    ret = ncpumaps;
3658
 
 
3659
 
cleanup:
3660
 
    if (vm)
3661
 
        virDomainObjUnlock(vm);
3662
 
    return ret;
3663
 
}
3664
 
 
3665
 
static int
3666
 
qemudDomainGetVcpus(virDomainPtr dom,
3667
 
                    virVcpuInfoPtr info,
3668
 
                    int maxinfo,
3669
 
                    unsigned char *cpumaps,
3670
 
                    int maplen) {
3671
 
    struct qemud_driver *driver = dom->conn->privateData;
3672
 
    virDomainObjPtr vm;
3673
 
    virNodeInfo nodeinfo;
3674
 
    int i, v, maxcpu, hostcpus;
3675
 
    int ret = -1;
3676
 
    qemuDomainObjPrivatePtr priv;
3677
 
 
3678
 
    qemuDriverLock(driver);
3679
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3680
 
    qemuDriverUnlock(driver);
3681
 
 
3682
 
    if (!vm) {
3683
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
3684
 
        virUUIDFormat(dom->uuid, uuidstr);
3685
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
3686
 
                        _("no domain with matching uuid '%s'"), uuidstr);
3687
 
        goto cleanup;
3688
 
    }
3689
 
 
3690
 
    if (!virDomainObjIsActive(vm)) {
3691
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
3692
 
                        "%s",
3693
 
                        _("cannot list vcpu pinning for an inactive domain"));
3694
 
        goto cleanup;
3695
 
    }
3696
 
 
3697
 
    priv = vm->privateData;
3698
 
 
3699
 
    if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
3700
 
        goto cleanup;
3701
 
 
3702
 
    hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
3703
 
    maxcpu = maplen * 8;
3704
 
    if (maxcpu > hostcpus)
3705
 
        maxcpu = hostcpus;
3706
 
 
3707
 
    /* Clamp to actual number of vcpus */
3708
 
    if (maxinfo > priv->nvcpupids)
3709
 
        maxinfo = priv->nvcpupids;
3710
 
 
3711
 
    if (maxinfo >= 1) {
3712
 
        if (info != NULL) {
3713
 
            memset(info, 0, sizeof(*info) * maxinfo);
3714
 
            for (i = 0 ; i < maxinfo ; i++) {
3715
 
                info[i].number = i;
3716
 
                info[i].state = VIR_VCPU_RUNNING;
3717
 
 
3718
 
                if (priv->vcpupids != NULL &&
3719
 
                    qemudGetProcessInfo(&(info[i].cpuTime),
3720
 
                                        &(info[i].cpu),
3721
 
                                        vm->pid,
3722
 
                                        priv->vcpupids[i]) < 0) {
3723
 
                    virReportSystemError(errno, "%s",
3724
 
                                         _("cannot get vCPU placement & pCPU time"));
3725
 
                    goto cleanup;
3726
 
                }
3727
 
            }
3728
 
        }
3729
 
 
3730
 
        if (cpumaps != NULL) {
3731
 
            memset(cpumaps, 0, maplen * maxinfo);
3732
 
            if (priv->vcpupids != NULL) {
3733
 
                for (v = 0 ; v < maxinfo ; v++) {
3734
 
                    unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
3735
 
 
3736
 
                    if (virProcessInfoGetAffinity(priv->vcpupids[v],
3737
 
                                                  cpumap, maplen, maxcpu) < 0)
3738
 
                        goto cleanup;
3739
 
                }
3740
 
            } else {
3741
 
                qemuReportError(VIR_ERR_OPERATION_INVALID,
3742
 
                                "%s", _("cpu affinity is not available"));
3743
 
                goto cleanup;
3744
 
            }
3745
 
        }
3746
 
    }
3747
 
    ret = maxinfo;
3748
 
 
3749
 
cleanup:
3750
 
    if (vm)
3751
 
        virDomainObjUnlock(vm);
3752
 
    return ret;
3753
 
}
3754
 
 
3755
 
 
3756
 
static int
3757
 
qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
3758
 
{
3759
 
    struct qemud_driver *driver = dom->conn->privateData;
3760
 
    virDomainObjPtr vm;
3761
 
    virDomainDefPtr def;
3762
 
    int ret = -1;
3763
 
    bool active;
3764
 
 
3765
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
3766
 
                  VIR_DOMAIN_AFFECT_CONFIG |
3767
 
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);
3768
 
 
3769
 
    qemuDriverLock(driver);
3770
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3771
 
    qemuDriverUnlock(driver);
3772
 
 
3773
 
    if (!vm) {
3774
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
3775
 
        virUUIDFormat(dom->uuid, uuidstr);
3776
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
3777
 
                        _("no domain with matching uuid '%s'"), uuidstr);
3778
 
        goto cleanup;
3779
 
    }
3780
 
 
3781
 
    active = virDomainObjIsActive(vm);
3782
 
 
3783
 
    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0) {
3784
 
        if (active)
3785
 
            flags |= VIR_DOMAIN_VCPU_LIVE;
3786
 
        else
3787
 
            flags |= VIR_DOMAIN_VCPU_CONFIG;
3788
 
    }
3789
 
    if ((flags & VIR_DOMAIN_AFFECT_LIVE) && (flags & VIR_DOMAIN_AFFECT_CONFIG)) {
3790
 
        qemuReportError(VIR_ERR_INVALID_ARG,
3791
 
                        _("invalid flag combination: (0x%x)"), flags);
3792
 
        return -1;
3793
 
    }
3794
 
 
3795
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
3796
 
        if (!active) {
3797
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
3798
 
                            _("domain not active"));
3799
 
            goto cleanup;
3800
 
        }
3801
 
        def = vm->def;
3802
 
    } else {
3803
 
        if (!vm->persistent) {
3804
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
3805
 
                            _("domain is transient"));
3806
 
            goto cleanup;
3807
 
        }
3808
 
        def = vm->newDef ? vm->newDef : vm->def;
3809
 
    }
3810
 
 
3811
 
    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
3812
 
 
3813
 
cleanup:
3814
 
    if (vm)
3815
 
        virDomainObjUnlock(vm);
3816
 
    return ret;
3817
 
}
3818
 
 
3819
 
static int
3820
 
qemudDomainGetMaxVcpus(virDomainPtr dom)
3821
 
{
3822
 
    return qemudDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
3823
 
                                          VIR_DOMAIN_VCPU_MAXIMUM));
3824
 
}
3825
 
 
3826
 
static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
3827
 
{
3828
 
    struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
3829
 
    virDomainObjPtr vm;
3830
 
    int ret = -1;
3831
 
 
3832
 
    qemuDriverLock(driver);
3833
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
3834
 
 
3835
 
    memset(seclabel, 0, sizeof(*seclabel));
3836
 
 
3837
 
    if (!vm) {
3838
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
3839
 
        virUUIDFormat(dom->uuid, uuidstr);
3840
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
3841
 
                        _("no domain with matching uuid '%s'"), uuidstr);
3842
 
        goto cleanup;
3843
 
    }
3844
 
 
3845
 
    if (!virDomainVirtTypeToString(vm->def->virtType)) {
3846
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
3847
 
                        _("unknown virt type in domain definition '%d'"),
3848
 
                        vm->def->virtType);
3849
 
        goto cleanup;
3850
 
    }
3851
 
 
3852
 
    /*
3853
 
     * Theoretically, the pid can be replaced during this operation and
3854
 
     * return the label of a different process.  If atomicity is needed,
3855
 
     * further validation will be required.
3856
 
     *
3857
 
     * Comment from Dan Berrange:
3858
 
     *
3859
 
     *   Well the PID as stored in the virDomainObjPtr can't be changed
3860
 
     *   because you've got a locked object.  The OS level PID could have
3861
 
     *   exited, though and in extreme circumstances have cycled through all
3862
 
     *   PIDs back to ours. We could sanity check that our PID still exists
3863
 
     *   after reading the label, by checking that our FD connecting to the
3864
 
     *   QEMU monitor hasn't seen SIGHUP/ERR on poll().
3865
 
     */
3866
 
    if (virDomainObjIsActive(vm)) {
3867
 
        if (virSecurityManagerGetProcessLabel(driver->securityManager,
3868
 
                                              vm, seclabel) < 0) {
3869
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
3870
 
                            "%s", _("Failed to get security label"));
3871
 
            goto cleanup;
3872
 
        }
3873
 
    }
3874
 
 
3875
 
    ret = 0;
3876
 
 
3877
 
cleanup:
3878
 
    if (vm)
3879
 
        virDomainObjUnlock(vm);
3880
 
    qemuDriverUnlock(driver);
3881
 
    return ret;
3882
 
}
3883
 
 
3884
 
static int qemudNodeGetSecurityModel(virConnectPtr conn,
3885
 
                                     virSecurityModelPtr secmodel)
3886
 
{
3887
 
    struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
3888
 
    char *p;
3889
 
    int ret = 0;
3890
 
 
3891
 
    qemuDriverLock(driver);
3892
 
    memset(secmodel, 0, sizeof(*secmodel));
3893
 
 
3894
 
    /* NULL indicates no driver, which we treat as
3895
 
     * success, but simply return no data in *secmodel */
3896
 
    if (driver->caps->host.secModel.model == NULL)
3897
 
        goto cleanup;
3898
 
 
3899
 
    p = driver->caps->host.secModel.model;
3900
 
    if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
3901
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
3902
 
                        _("security model string exceeds max %d bytes"),
3903
 
                        VIR_SECURITY_MODEL_BUFLEN-1);
3904
 
        ret = -1;
3905
 
        goto cleanup;
3906
 
    }
3907
 
    strcpy(secmodel->model, p);
3908
 
 
3909
 
    p = driver->caps->host.secModel.doi;
3910
 
    if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
3911
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
3912
 
                        _("security DOI string exceeds max %d bytes"),
3913
 
                        VIR_SECURITY_DOI_BUFLEN-1);
3914
 
        ret = -1;
3915
 
        goto cleanup;
3916
 
    }
3917
 
    strcpy(secmodel->doi, p);
3918
 
 
3919
 
cleanup:
3920
 
    qemuDriverUnlock(driver);
3921
 
    return ret;
3922
 
}
3923
 
 
3924
 
/* Return -1 on most failures after raising error, -2 if edit was specified
3925
 
 * but xmlin and state (-1 for no change, 0 for paused, 1 for running) do
3926
 
 * not represent any changes (no error raised), -3 if corrupt image was
3927
 
 * unlinked (no error raised), and opened fd on success.  */
3928
 
static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
3929
 
qemuDomainSaveImageOpen(struct qemud_driver *driver,
3930
 
                        const char *path,
3931
 
                        virDomainDefPtr *ret_def,
3932
 
                        struct qemud_save_header *ret_header,
3933
 
                        bool bypass_cache, virFileDirectFdPtr *directFd,
3934
 
                        const char *xmlin, int state, bool edit,
3935
 
                        bool unlink_corrupt)
3936
 
{
3937
 
    int fd;
3938
 
    struct qemud_save_header header;
3939
 
    char *xml = NULL;
3940
 
    virDomainDefPtr def = NULL;
3941
 
    int oflags = edit ? O_RDWR : O_RDONLY;
3942
 
 
3943
 
    if (bypass_cache) {
3944
 
        int directFlag = virFileDirectFdFlag();
3945
 
        if (directFlag < 0) {
3946
 
            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
3947
 
                            _("bypass cache unsupported by this system"));
3948
 
            goto error;
3949
 
        }
3950
 
        oflags |= directFlag;
3951
 
    }
3952
 
 
3953
 
    if ((fd = qemuOpenFile(driver, path, oflags, NULL, NULL)) < 0)
3954
 
        goto error;
3955
 
    if (bypass_cache && (*directFd = virFileDirectFdNew(&fd, path)) == NULL)
3956
 
        goto error;
3957
 
 
3958
 
    if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
3959
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
3960
 
                        "%s", _("failed to read qemu header"));
3961
 
        goto error;
3962
 
    }
3963
 
 
3964
 
    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
3965
 
        const char *msg = _("image magic is incorrect");
3966
 
 
3967
 
        if (memcmp(header.magic, QEMUD_SAVE_PARTIAL,
3968
 
                   sizeof(header.magic)) == 0) {
3969
 
            msg = _("save image is incomplete");
3970
 
            if (unlink_corrupt) {
3971
 
                if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
3972
 
                    virReportSystemError(errno,
3973
 
                                         _("cannot remove corrupt file: %s"),
3974
 
                                         path);
3975
 
                    goto error;
3976
 
                }
3977
 
                return -3;
3978
 
            }
3979
 
        }
3980
 
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", msg);
3981
 
        goto error;
3982
 
    }
3983
 
 
3984
 
    if (header.version > QEMUD_SAVE_VERSION) {
3985
 
        /* convert endianess and try again */
3986
 
        bswap_header(&header);
3987
 
    }
3988
 
 
3989
 
    if (header.version > QEMUD_SAVE_VERSION) {
3990
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
3991
 
                        _("image version is not supported (%d > %d)"),
3992
 
                        header.version, QEMUD_SAVE_VERSION);
3993
 
        goto error;
3994
 
    }
3995
 
 
3996
 
    if (header.xml_len <= 0) {
3997
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
3998
 
                        _("invalid XML length: %d"), header.xml_len);
3999
 
        goto error;
4000
 
    }
4001
 
 
4002
 
    if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
4003
 
        virReportOOMError();
4004
 
        goto error;
4005
 
    }
4006
 
 
4007
 
    if (saferead(fd, xml, header.xml_len) != header.xml_len) {
4008
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
4009
 
                        "%s", _("failed to read XML"));
4010
 
        goto error;
4011
 
    }
4012
 
 
4013
 
    if (edit && STREQ(xml, xmlin) &&
4014
 
        (state < 0 || state == header.was_running)) {
4015
 
        VIR_FREE(xml);
4016
 
        if (VIR_CLOSE(fd) < 0) {
4017
 
            virReportSystemError(errno, _("cannot close file: %s"), path);
4018
 
            goto error;
4019
 
        }
4020
 
        return -2;
4021
 
    }
4022
 
    if (state >= 0)
4023
 
        header.was_running = state;
4024
 
 
4025
 
    /* Create a domain from this XML */
4026
 
    if (!(def = virDomainDefParseString(driver->caps, xml,
4027
 
                                        QEMU_EXPECTED_VIRT_TYPES,
4028
 
                                        VIR_DOMAIN_XML_INACTIVE)))
4029
 
        goto error;
4030
 
    if (xmlin) {
4031
 
        virDomainDefPtr def2 = NULL;
4032
 
 
4033
 
        if (!(def2 = virDomainDefParseString(driver->caps, xmlin,
4034
 
                                             QEMU_EXPECTED_VIRT_TYPES,
4035
 
                                             VIR_DOMAIN_XML_INACTIVE)))
4036
 
            goto error;
4037
 
        if (!virDomainDefCheckABIStability(def, def2)) {
4038
 
            virDomainDefFree(def2);
4039
 
            goto error;
4040
 
        }
4041
 
        virDomainDefFree(def);
4042
 
        def = def2;
4043
 
    }
4044
 
 
4045
 
    VIR_FREE(xml);
4046
 
 
4047
 
    *ret_def = def;
4048
 
    *ret_header = header;
4049
 
 
4050
 
    return fd;
4051
 
 
4052
 
error:
4053
 
    virDomainDefFree(def);
4054
 
    VIR_FREE(xml);
4055
 
    VIR_FORCE_CLOSE(fd);
4056
 
 
4057
 
    return -1;
4058
 
}
4059
 
 
4060
 
static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6)
4061
 
qemuDomainSaveImageStartVM(virConnectPtr conn,
4062
 
                           struct qemud_driver *driver,
4063
 
                           virDomainObjPtr vm,
4064
 
                           int *fd,
4065
 
                           const struct qemud_save_header *header,
4066
 
                           const char *path,
4067
 
                           bool start_paused)
4068
 
{
4069
 
    int ret = -1;
4070
 
    virDomainEventPtr event;
4071
 
    int intermediatefd = -1;
4072
 
    virCommandPtr cmd = NULL;
4073
 
 
4074
 
    if (header->version == 2) {
4075
 
        const char *prog = qemudSaveCompressionTypeToString(header->compressed);
4076
 
        if (prog == NULL) {
4077
 
            qemuReportError(VIR_ERR_OPERATION_FAILED,
4078
 
                            _("Invalid compressed save format %d"),
4079
 
                            header->compressed);
4080
 
            goto out;
4081
 
        }
4082
 
 
4083
 
        if (header->compressed != QEMUD_SAVE_FORMAT_RAW) {
4084
 
            cmd = virCommandNewArgList(prog, "-dc", NULL);
4085
 
            intermediatefd = *fd;
4086
 
            *fd = -1;
4087
 
 
4088
 
            virCommandSetInputFD(cmd, intermediatefd);
4089
 
            virCommandSetOutputFD(cmd, fd);
4090
 
 
4091
 
            if (virCommandRunAsync(cmd, NULL) < 0) {
4092
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
4093
 
                                _("Failed to start decompression binary %s"),
4094
 
                                prog);
4095
 
                *fd = intermediatefd;
4096
 
                goto out;
4097
 
            }
4098
 
        }
4099
 
    }
4100
 
 
4101
 
    /* Set the migration source and start it up. */
4102
 
    ret = qemuProcessStart(conn, driver, vm, "stdio", true,
4103
 
                           false, *fd, path, NULL, VIR_NETDEV_VPORT_PROFILE_OP_RESTORE);
4104
 
 
4105
 
    if (intermediatefd != -1) {
4106
 
        if (ret < 0) {
4107
 
            /* if there was an error setting up qemu, the intermediate
4108
 
             * process will wait forever to write to stdout, so we
4109
 
             * must manually kill it.
4110
 
             */
4111
 
            VIR_FORCE_CLOSE(intermediatefd);
4112
 
            VIR_FORCE_CLOSE(*fd);
4113
 
        }
4114
 
 
4115
 
        if (virCommandWait(cmd, NULL) < 0)
4116
 
            ret = -1;
4117
 
    }
4118
 
    VIR_FORCE_CLOSE(intermediatefd);
4119
 
 
4120
 
    if (VIR_CLOSE(*fd) < 0) {
4121
 
        virReportSystemError(errno, _("cannot close file: %s"), path);
4122
 
        ret = -1;
4123
 
    }
4124
 
 
4125
 
    if (ret < 0) {
4126
 
        virDomainAuditStart(vm, "restored", false);
4127
 
        goto out;
4128
 
    }
4129
 
 
4130
 
    event = virDomainEventNewFromObj(vm,
4131
 
                                     VIR_DOMAIN_EVENT_STARTED,
4132
 
                                     VIR_DOMAIN_EVENT_STARTED_RESTORED);
4133
 
    virDomainAuditStart(vm, "restored", true);
4134
 
    if (event)
4135
 
        qemuDomainEventQueue(driver, event);
4136
 
 
4137
 
 
4138
 
    /* If it was running before, resume it now unless caller requested pause. */
4139
 
    if (header->was_running && !start_paused) {
4140
 
        if (qemuProcessStartCPUs(driver, vm, conn,
4141
 
                                 VIR_DOMAIN_RUNNING_RESTORED,
4142
 
                                 QEMU_ASYNC_JOB_NONE) < 0) {
4143
 
            if (virGetLastError() == NULL)
4144
 
                qemuReportError(VIR_ERR_OPERATION_FAILED,
4145
 
                                "%s", _("failed to resume domain"));
4146
 
            goto out;
4147
 
        }
4148
 
        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
4149
 
            VIR_WARN("Failed to save status on vm %s", vm->def->name);
4150
 
            goto out;
4151
 
        }
4152
 
    } else {
4153
 
        int detail = (start_paused ? VIR_DOMAIN_EVENT_SUSPENDED_PAUSED :
4154
 
                      VIR_DOMAIN_EVENT_SUSPENDED_RESTORED);
4155
 
        event = virDomainEventNewFromObj(vm,
4156
 
                                         VIR_DOMAIN_EVENT_SUSPENDED,
4157
 
                                         detail);
4158
 
        if (event)
4159
 
            qemuDomainEventQueue(driver, event);
4160
 
    }
4161
 
 
4162
 
    ret = 0;
4163
 
 
4164
 
out:
4165
 
    virCommandFree(cmd);
4166
 
    if (virSecurityManagerRestoreSavedStateLabel(driver->securityManager,
4167
 
                                                 vm, path) < 0)
4168
 
        VIR_WARN("failed to restore save state label on %s", path);
4169
 
 
4170
 
    return ret;
4171
 
}
4172
 
 
4173
 
static int
4174
 
qemuDomainRestoreFlags(virConnectPtr conn,
4175
 
                       const char *path,
4176
 
                       const char *dxml,
4177
 
                       unsigned int flags)
4178
 
{
4179
 
    struct qemud_driver *driver = conn->privateData;
4180
 
    virDomainDefPtr def = NULL;
4181
 
    virDomainObjPtr vm = NULL;
4182
 
    int fd = -1;
4183
 
    int ret = -1;
4184
 
    struct qemud_save_header header;
4185
 
    virFileDirectFdPtr directFd = NULL;
4186
 
    int state = -1;
4187
 
 
4188
 
    virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
4189
 
                  VIR_DOMAIN_SAVE_RUNNING |
4190
 
                  VIR_DOMAIN_SAVE_PAUSED, -1);
4191
 
 
4192
 
    qemuDriverLock(driver);
4193
 
 
4194
 
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
4195
 
        state = 1;
4196
 
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
4197
 
        state = 0;
4198
 
 
4199
 
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
4200
 
                                 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
4201
 
                                 &directFd, dxml, state, false, false);
4202
 
    if (fd < 0)
4203
 
        goto cleanup;
4204
 
 
4205
 
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
4206
 
        goto cleanup;
4207
 
 
4208
 
    if (!(vm = virDomainAssignDef(driver->caps,
4209
 
                                  &driver->domains,
4210
 
                                  def, true))) {
4211
 
        /* virDomainAssignDef already set the error */
4212
 
        goto cleanup;
4213
 
    }
4214
 
    def = NULL;
4215
 
 
4216
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
4217
 
        goto cleanup;
4218
 
 
4219
 
    ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path,
4220
 
                                     false);
4221
 
    if (virFileDirectFdClose(directFd) < 0)
4222
 
        VIR_WARN("Failed to close %s", path);
4223
 
 
4224
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
4225
 
        vm = NULL;
4226
 
    else if (ret < 0 && !vm->persistent) {
4227
 
        qemuDomainRemoveInactive(driver, vm);
4228
 
        vm = NULL;
4229
 
    }
4230
 
 
4231
 
cleanup:
4232
 
    virDomainDefFree(def);
4233
 
    VIR_FORCE_CLOSE(fd);
4234
 
    virFileDirectFdFree(directFd);
4235
 
    if (vm)
4236
 
        virDomainObjUnlock(vm);
4237
 
    qemuDriverUnlock(driver);
4238
 
    return ret;
4239
 
}
4240
 
 
4241
 
static int
4242
 
qemuDomainRestore(virConnectPtr conn,
4243
 
                  const char *path)
4244
 
{
4245
 
    return qemuDomainRestoreFlags(conn, path, NULL, 0);
4246
 
}
4247
 
 
4248
 
static char *
4249
 
qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
4250
 
                              unsigned int flags)
4251
 
{
4252
 
    struct qemud_driver *driver = conn->privateData;
4253
 
    char *ret = NULL;
4254
 
    virDomainDefPtr def = NULL;
4255
 
    int fd = -1;
4256
 
    struct qemud_save_header header;
4257
 
 
4258
 
    /* We only take subset of virDomainDefFormat flags.  */
4259
 
    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);
4260
 
 
4261
 
    qemuDriverLock(driver);
4262
 
 
4263
 
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
4264
 
                                 NULL, -1, false, false);
4265
 
 
4266
 
    if (fd < 0)
4267
 
        goto cleanup;
4268
 
 
4269
 
    ret = qemuDomainDefFormatXML(driver, def, flags);
4270
 
 
4271
 
cleanup:
4272
 
    virDomainDefFree(def);
4273
 
    VIR_FORCE_CLOSE(fd);
4274
 
    qemuDriverUnlock(driver);
4275
 
    return ret;
4276
 
}
4277
 
 
4278
 
static int
4279
 
qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
4280
 
                             const char *dxml, unsigned int flags)
4281
 
{
4282
 
    struct qemud_driver *driver = conn->privateData;
4283
 
    int ret = -1;
4284
 
    virDomainDefPtr def = NULL;
4285
 
    int fd = -1;
4286
 
    struct qemud_save_header header;
4287
 
    char *xml = NULL;
4288
 
    size_t len;
4289
 
    int state = -1;
4290
 
 
4291
 
    virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
4292
 
                  VIR_DOMAIN_SAVE_PAUSED, -1);
4293
 
 
4294
 
    qemuDriverLock(driver);
4295
 
 
4296
 
    if (flags & VIR_DOMAIN_SAVE_RUNNING)
4297
 
        state = 1;
4298
 
    else if (flags & VIR_DOMAIN_SAVE_PAUSED)
4299
 
        state = 0;
4300
 
 
4301
 
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
4302
 
                                 dxml, state, true, false);
4303
 
 
4304
 
    if (fd < 0) {
4305
 
        /* Check for special case of no change needed.  */
4306
 
        if (fd == -2)
4307
 
            ret = 0;
4308
 
        goto cleanup;
4309
 
    }
4310
 
 
4311
 
    xml = qemuDomainDefFormatXML(driver, def, (VIR_DOMAIN_XML_INACTIVE |
4312
 
                                               VIR_DOMAIN_XML_SECURE));
4313
 
    if (!xml)
4314
 
        goto cleanup;
4315
 
    len = strlen(xml) + 1;
4316
 
 
4317
 
    if (len > header.xml_len) {
4318
 
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
4319
 
                        _("new xml too large to fit in file"));
4320
 
        goto cleanup;
4321
 
    }
4322
 
    if (VIR_EXPAND_N(xml, len, header.xml_len - len) < 0) {
4323
 
        virReportOOMError();
4324
 
        goto cleanup;
4325
 
    }
4326
 
 
4327
 
    if (lseek(fd, 0, SEEK_SET) != 0) {
4328
 
        virReportSystemError(errno, _("cannot seek in '%s'"), path);
4329
 
        goto cleanup;
4330
 
    }
4331
 
    if (safewrite(fd, &header, sizeof(header)) != sizeof(header) ||
4332
 
        safewrite(fd, xml, len) != len ||
4333
 
        VIR_CLOSE(fd) < 0) {
4334
 
        virReportSystemError(errno, _("failed to write xml to '%s'"), path);
4335
 
        goto cleanup;
4336
 
    }
4337
 
 
4338
 
    ret = 0;
4339
 
 
4340
 
cleanup:
4341
 
    virDomainDefFree(def);
4342
 
    VIR_FORCE_CLOSE(fd);
4343
 
    VIR_FREE(xml);
4344
 
    qemuDriverUnlock(driver);
4345
 
    return ret;
4346
 
}
4347
 
 
4348
 
/* Return 0 on success, 1 if incomplete saved image was silently unlinked,
4349
 
 * and -1 on failure with error raised.  */
4350
 
static int
4351
 
qemuDomainObjRestore(virConnectPtr conn,
4352
 
                     struct qemud_driver *driver,
4353
 
                     virDomainObjPtr vm,
4354
 
                     const char *path,
4355
 
                     bool start_paused,
4356
 
                     bool bypass_cache)
4357
 
{
4358
 
    virDomainDefPtr def = NULL;
4359
 
    int fd = -1;
4360
 
    int ret = -1;
4361
 
    struct qemud_save_header header;
4362
 
    virFileDirectFdPtr directFd = NULL;
4363
 
 
4364
 
    fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
4365
 
                                 bypass_cache, &directFd, NULL, -1, false,
4366
 
                                 true);
4367
 
    if (fd < 0) {
4368
 
        if (fd == -3)
4369
 
            ret = 1;
4370
 
        goto cleanup;
4371
 
    }
4372
 
 
4373
 
    if (STRNEQ(vm->def->name, def->name) ||
4374
 
        memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
4375
 
        char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
4376
 
        char def_uuidstr[VIR_UUID_STRING_BUFLEN];
4377
 
        virUUIDFormat(vm->def->uuid, vm_uuidstr);
4378
 
        virUUIDFormat(def->uuid, def_uuidstr);
4379
 
        qemuReportError(VIR_ERR_OPERATION_FAILED,
4380
 
                        _("cannot restore domain '%s' uuid %s from a file"
4381
 
                          " which belongs to domain '%s' uuid %s"),
4382
 
                        vm->def->name, vm_uuidstr,
4383
 
                        def->name, def_uuidstr);
4384
 
        goto cleanup;
4385
 
    }
4386
 
 
4387
 
    virDomainObjAssignDef(vm, def, true);
4388
 
    def = NULL;
4389
 
 
4390
 
    ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, &header, path,
4391
 
                                     start_paused);
4392
 
    if (virFileDirectFdClose(directFd) < 0)
4393
 
        VIR_WARN("Failed to close %s", path);
4394
 
 
4395
 
cleanup:
4396
 
    virDomainDefFree(def);
4397
 
    VIR_FORCE_CLOSE(fd);
4398
 
    virFileDirectFdFree(directFd);
4399
 
    return ret;
4400
 
}
4401
 
 
4402
 
 
4403
 
static char *qemuDomainGetXMLDesc(virDomainPtr dom,
4404
 
                                  unsigned int flags)
4405
 
{
4406
 
    struct qemud_driver *driver = dom->conn->privateData;
4407
 
    virDomainObjPtr vm;
4408
 
    char *ret = NULL;
4409
 
    unsigned long balloon;
4410
 
    int err = 0;
4411
 
 
4412
 
    /* Flags checked by virDomainDefFormat */
4413
 
 
4414
 
    qemuDriverLock(driver);
4415
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4416
 
 
4417
 
    if (!vm) {
4418
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
4419
 
        virUUIDFormat(dom->uuid, uuidstr);
4420
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
4421
 
                        _("no domain with matching uuid '%s'"), uuidstr);
4422
 
        goto cleanup;
4423
 
    }
4424
 
 
4425
 
    /* Refresh current memory based on balloon info if supported */
4426
 
    if ((vm->def->memballoon != NULL) &&
4427
 
        (vm->def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE) &&
4428
 
        (virDomainObjIsActive(vm))) {
4429
 
        qemuDomainObjPrivatePtr priv = vm->privateData;
4430
 
        /* Don't delay if someone's using the monitor, just use
4431
 
         * existing most recent data instead */
4432
 
        if (qemuDomainJobAllowed(priv, QEMU_JOB_QUERY)) {
4433
 
            if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_QUERY) < 0)
4434
 
                goto cleanup;
4435
 
 
4436
 
            if (!virDomainObjIsActive(vm)) {
4437
 
                qemuReportError(VIR_ERR_OPERATION_INVALID,
4438
 
                                "%s", _("domain is not running"));
4439
 
                goto endjob;
4440
 
            }
4441
 
 
4442
 
            qemuDomainObjEnterMonitorWithDriver(driver, vm);
4443
 
            err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
4444
 
            qemuDomainObjExitMonitorWithDriver(driver, vm);
4445
 
 
4446
 
endjob:
4447
 
            if (qemuDomainObjEndJob(driver, vm) == 0) {
4448
 
                vm = NULL;
4449
 
                goto cleanup;
4450
 
            }
4451
 
            if (err < 0)
4452
 
                goto cleanup;
4453
 
            if (err > 0)
4454
 
                vm->def->mem.cur_balloon = balloon;
4455
 
            /* err == 0 indicates no balloon support, so ignore it */
4456
 
        }
4457
 
    }
4458
 
 
4459
 
    ret = qemuDomainFormatXML(driver, vm, flags);
4460
 
 
4461
 
cleanup:
4462
 
    if (vm)
4463
 
        virDomainObjUnlock(vm);
4464
 
    qemuDriverUnlock(driver);
4465
 
    return ret;
4466
 
}
4467
 
 
4468
 
 
4469
 
static char *qemuDomainXMLFromNative(virConnectPtr conn,
4470
 
                                     const char *format,
4471
 
                                     const char *config,
4472
 
                                     unsigned int flags)
4473
 
{
4474
 
    struct qemud_driver *driver = conn->privateData;
4475
 
    virDomainDefPtr def = NULL;
4476
 
    char *xml = NULL;
4477
 
 
4478
 
    virCheckFlags(0, NULL);
4479
 
 
4480
 
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
4481
 
        qemuReportError(VIR_ERR_INVALID_ARG,
4482
 
                        _("unsupported config type %s"), format);
4483
 
        goto cleanup;
4484
 
    }
4485
 
 
4486
 
    qemuDriverLock(driver);
4487
 
    def = qemuParseCommandLineString(driver->caps, config,
4488
 
                                     NULL, NULL, NULL);
4489
 
    qemuDriverUnlock(driver);
4490
 
    if (!def)
4491
 
        goto cleanup;
4492
 
 
4493
 
    if (!def->name &&
4494
 
        !(def->name = strdup("unnamed"))) {
4495
 
        virReportOOMError();
4496
 
        goto cleanup;
4497
 
    }
4498
 
 
4499
 
    xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
4500
 
 
4501
 
cleanup:
4502
 
    virDomainDefFree(def);
4503
 
    return xml;
4504
 
}
4505
 
 
4506
 
static char *qemuDomainXMLToNative(virConnectPtr conn,
4507
 
                                   const char *format,
4508
 
                                   const char *xmlData,
4509
 
                                   unsigned int flags)
4510
 
{
4511
 
    struct qemud_driver *driver = conn->privateData;
4512
 
    virDomainDefPtr def = NULL;
4513
 
    virDomainChrSourceDef monConfig;
4514
 
    virBitmapPtr qemuCaps = NULL;
4515
 
    bool monitor_json = false;
4516
 
    virCommandPtr cmd = NULL;
4517
 
    char *ret = NULL;
4518
 
    int i;
4519
 
 
4520
 
    virCheckFlags(0, NULL);
4521
 
 
4522
 
    qemuDriverLock(driver);
4523
 
 
4524
 
    if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
4525
 
        qemuReportError(VIR_ERR_INVALID_ARG,
4526
 
                        _("unsupported config type %s"), format);
4527
 
        goto cleanup;
4528
 
    }
4529
 
 
4530
 
    def = virDomainDefParseString(driver->caps, xmlData,
4531
 
                                  QEMU_EXPECTED_VIRT_TYPES, 0);
4532
 
    if (!def)
4533
 
        goto cleanup;
4534
 
 
4535
 
    /* Since we're just exporting args, we can't do bridge/network/direct
4536
 
     * setups, since libvirt will normally create TAP/macvtap devices
4537
 
     * directly. We convert those configs into generic 'ethernet'
4538
 
     * config and assume the user has suitable 'ifup-qemu' scripts
4539
 
     */
4540
 
    for (i = 0 ; i < def->nnets ; i++) {
4541
 
        virDomainNetDefPtr net = def->nets[i];
4542
 
        int bootIndex = net->bootIndex;
4543
 
        if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
4544
 
            int actualType = virDomainNetGetActualType(net);
4545
 
            const char *brname;
4546
 
 
4547
 
            VIR_FREE(net->data.network.name);
4548
 
            VIR_FREE(net->data.network.portgroup);
4549
 
            if ((actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
4550
 
                (brname = virDomainNetGetActualBridgeName(net))) {
4551
 
 
4552
 
                char *brnamecopy = strdup(brname);
4553
 
                if (!brnamecopy) {
4554
 
                    virReportOOMError();
4555
 
                    goto cleanup;
4556
 
                }
4557
 
 
4558
 
                virDomainActualNetDefFree(net->data.network.actual);
4559
 
 
4560
 
                memset(net, 0, sizeof *net);
4561
 
 
4562
 
                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
4563
 
                net->data.ethernet.dev = brnamecopy;
4564
 
                net->data.ethernet.script = NULL;
4565
 
                net->data.ethernet.ipaddr = NULL;
4566
 
            } else {
4567
 
                /* actualType is either NETWORK or DIRECT. In either
4568
 
                 * case, the best we can do is NULL everything out.
4569
 
                 */
4570
 
                virDomainActualNetDefFree(net->data.network.actual);
4571
 
                memset(net, 0, sizeof *net);
4572
 
 
4573
 
                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
4574
 
                net->data.ethernet.dev = NULL;
4575
 
                net->data.ethernet.script = NULL;
4576
 
                net->data.ethernet.ipaddr = NULL;
4577
 
            }
4578
 
        } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
4579
 
            VIR_FREE(net->data.direct.linkdev);
4580
 
            VIR_FREE(net->data.direct.virtPortProfile);
4581
 
 
4582
 
            memset(net, 0, sizeof *net);
4583
 
 
4584
 
            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
4585
 
            net->data.ethernet.dev = NULL;
4586
 
            net->data.ethernet.script = NULL;
4587
 
            net->data.ethernet.ipaddr = NULL;
4588
 
        } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
4589
 
            char *brname = net->data.bridge.brname;
4590
 
            char *script = net->data.bridge.script;
4591
 
            char *ipaddr = net->data.bridge.ipaddr;
4592
 
 
4593
 
            memset(net, 0, sizeof *net);
4594
 
 
4595
 
            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
4596
 
            net->data.ethernet.dev = brname;
4597
 
            net->data.ethernet.script = script;
4598
 
            net->data.ethernet.ipaddr = ipaddr;
4599
 
        }
4600
 
        net->bootIndex = bootIndex;
4601
 
    }
4602
 
    for (i = 0 ; i < def->ngraphics ; i++) {
4603
 
        if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
4604
 
            def->graphics[i]->data.vnc.autoport)
4605
 
            def->graphics[i]->data.vnc.port = QEMU_VNC_PORT_MIN;
4606
 
    }
4607
 
 
4608
 
    if (qemuCapsExtractVersionInfo(def->emulator, def->os.arch,
4609
 
                                   NULL,
4610
 
                                   &qemuCaps) < 0)
4611
 
        goto cleanup;
4612
 
 
4613
 
    monitor_json = qemuCapsGet(qemuCaps, QEMU_CAPS_MONITOR_JSON);
4614
 
 
4615
 
    if (qemuProcessPrepareMonitorChr(driver, &monConfig, def->name) < 0)
4616
 
        goto cleanup;
4617
 
 
4618
 
    if (qemuAssignDeviceAliases(def, qemuCaps) < 0)
4619
 
        goto cleanup;
4620
 
 
4621
 
    if (!(cmd = qemuBuildCommandLine(conn, driver, def,
4622
 
                                     &monConfig, monitor_json, qemuCaps,
4623
 
                                     NULL, -1, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP)))
4624
 
        goto cleanup;
4625
 
 
4626
 
    ret = virCommandToString(cmd);
4627
 
 
4628
 
cleanup:
4629
 
    qemuDriverUnlock(driver);
4630
 
 
4631
 
    qemuCapsFree(qemuCaps);
4632
 
    virCommandFree(cmd);
4633
 
    virDomainDefFree(def);
4634
 
    return ret;
4635
 
}
4636
 
 
4637
 
 
4638
 
static int qemudListDefinedDomains(virConnectPtr conn,
4639
 
                            char **const names, int nnames) {
4640
 
    struct qemud_driver *driver = conn->privateData;
4641
 
    int n;
4642
 
 
4643
 
    qemuDriverLock(driver);
4644
 
    n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
4645
 
    qemuDriverUnlock(driver);
4646
 
    return n;
4647
 
}
4648
 
 
4649
 
static int qemudNumDefinedDomains(virConnectPtr conn) {
4650
 
    struct qemud_driver *driver = conn->privateData;
4651
 
    int n;
4652
 
 
4653
 
    qemuDriverLock(driver);
4654
 
    n = virDomainObjListNumOfDomains(&driver->domains, 0);
4655
 
    qemuDriverUnlock(driver);
4656
 
 
4657
 
    return n;
4658
 
}
4659
 
 
4660
 
 
4661
 
static int
4662
 
qemuDomainObjStart(virConnectPtr conn,
4663
 
                   struct qemud_driver *driver,
4664
 
                   virDomainObjPtr vm,
4665
 
                   unsigned int flags)
4666
 
{
4667
 
    int ret = -1;
4668
 
    char *managed_save;
4669
 
    bool start_paused = (flags & VIR_DOMAIN_START_PAUSED) != 0;
4670
 
    bool autodestroy = (flags & VIR_DOMAIN_START_AUTODESTROY) != 0;
4671
 
    bool bypass_cache = (flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0;
4672
 
    bool force_boot = (flags & VIR_DOMAIN_START_FORCE_BOOT) != 0;
4673
 
 
4674
 
    /*
4675
 
     * If there is a managed saved state restore it instead of starting
4676
 
     * from scratch. The old state is removed once the restoring succeeded.
4677
 
     */
4678
 
    managed_save = qemuDomainManagedSavePath(driver, vm);
4679
 
 
4680
 
    if (!managed_save)
4681
 
        goto cleanup;
4682
 
 
4683
 
    if (virFileExists(managed_save)) {
4684
 
        if (force_boot) {
4685
 
            if (unlink(managed_save) < 0) {
4686
 
                virReportSystemError(errno,
4687
 
                                     _("cannot remove managed save file %s"),
4688
 
                                     managed_save);
4689
 
                goto cleanup;
4690
 
            }
4691
 
        } else {
4692
 
            ret = qemuDomainObjRestore(conn, driver, vm, managed_save,
4693
 
                                       start_paused, bypass_cache);
4694
 
 
4695
 
            if (ret == 0 && unlink(managed_save) < 0)
4696
 
                VIR_WARN("Failed to remove the managed state %s", managed_save);
4697
 
            if (ret > 0)
4698
 
                VIR_WARN("Ignoring incomplete managed state %s", managed_save);
4699
 
            else
4700
 
                goto cleanup;
4701
 
        }
4702
 
    }
4703
 
 
4704
 
    ret = qemuProcessStart(conn, driver, vm, NULL, start_paused,
4705
 
                           autodestroy, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE);
4706
 
    virDomainAuditStart(vm, "booted", ret >= 0);
4707
 
    if (ret >= 0) {
4708
 
        virDomainEventPtr event =
4709
 
            virDomainEventNewFromObj(vm,
4710
 
                                     VIR_DOMAIN_EVENT_STARTED,
4711
 
                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
4712
 
        if (event) {
4713
 
            qemuDomainEventQueue(driver, event);
4714
 
            if (start_paused) {
4715
 
                event = virDomainEventNewFromObj(vm,
4716
 
                                                 VIR_DOMAIN_EVENT_SUSPENDED,
4717
 
                                                 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
4718
 
                if (event)
4719
 
                    qemuDomainEventQueue(driver, event);
4720
 
            }
4721
 
        }
4722
 
    }
4723
 
 
4724
 
cleanup:
4725
 
    VIR_FREE(managed_save);
4726
 
    return ret;
4727
 
}
4728
 
 
4729
 
static int
4730
 
qemuDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
4731
 
{
4732
 
    struct qemud_driver *driver = dom->conn->privateData;
4733
 
    virDomainObjPtr vm;
4734
 
    int ret = -1;
4735
 
 
4736
 
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
4737
 
                  VIR_DOMAIN_START_AUTODESTROY |
4738
 
                  VIR_DOMAIN_START_BYPASS_CACHE |
4739
 
                  VIR_DOMAIN_START_FORCE_BOOT, -1);
4740
 
 
4741
 
    qemuDriverLock(driver);
4742
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4743
 
 
4744
 
    if (!vm) {
4745
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
4746
 
        virUUIDFormat(dom->uuid, uuidstr);
4747
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
4748
 
                        _("no domain with matching uuid '%s'"), uuidstr);
4749
 
        goto cleanup;
4750
 
    }
4751
 
 
4752
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
4753
 
        goto cleanup;
4754
 
 
4755
 
    if (virDomainObjIsActive(vm)) {
4756
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
4757
 
                        "%s", _("domain is already running"));
4758
 
        goto endjob;
4759
 
    }
4760
 
 
4761
 
    if (qemuDomainObjStart(dom->conn, driver, vm, flags) < 0)
4762
 
        goto endjob;
4763
 
 
4764
 
    ret = 0;
4765
 
 
4766
 
endjob:
4767
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
4768
 
        vm = NULL;
4769
 
 
4770
 
cleanup:
4771
 
    if (vm)
4772
 
        virDomainObjUnlock(vm);
4773
 
    qemuDriverUnlock(driver);
4774
 
    return ret;
4775
 
}
4776
 
 
4777
 
static int
4778
 
qemuDomainStart(virDomainPtr dom)
4779
 
{
4780
 
    return qemuDomainStartWithFlags(dom, 0);
4781
 
}
4782
 
 
4783
 
static int
4784
 
qemudCanonicalizeMachineFromInfo(virDomainDefPtr def,
4785
 
                                 virCapsGuestDomainInfoPtr info,
4786
 
                                 char **canonical)
4787
 
{
4788
 
    int i;
4789
 
 
4790
 
    *canonical = NULL;
4791
 
 
4792
 
    for (i = 0; i < info->nmachines; i++) {
4793
 
        virCapsGuestMachinePtr machine = info->machines[i];
4794
 
 
4795
 
        if (!machine->canonical)
4796
 
            continue;
4797
 
 
4798
 
        if (def->os.machine && STRNEQ(def->os.machine, machine->name))
4799
 
            continue;
4800
 
 
4801
 
        if (!(*canonical = strdup(machine->canonical))) {
4802
 
            virReportOOMError();
4803
 
            return -1;
4804
 
        }
4805
 
 
4806
 
        break;
4807
 
    }
4808
 
 
4809
 
    return 0;
4810
 
}
4811
 
 
4812
 
static int
4813
 
qemudCanonicalizeMachineDirect(virDomainDefPtr def, char **canonical)
4814
 
{
4815
 
    virCapsGuestMachinePtr *machines = NULL;
4816
 
    int i, nmachines = 0;
4817
 
 
4818
 
    if (qemuCapsProbeMachineTypes(def->emulator, &machines, &nmachines) < 0)
4819
 
        return -1;
4820
 
 
4821
 
    for (i = 0; i < nmachines; i++) {
4822
 
        if (!machines[i]->canonical)
4823
 
            continue;
4824
 
 
4825
 
        if (def->os.machine && STRNEQ(def->os.machine, machines[i]->name))
4826
 
            continue;
4827
 
 
4828
 
        *canonical = machines[i]->canonical;
4829
 
        machines[i]->canonical = NULL;
4830
 
        break;
4831
 
    }
4832
 
 
4833
 
    virCapabilitiesFreeMachines(machines, nmachines);
4834
 
 
4835
 
    return 0;
4836
 
}
4837
 
 
4838
 
int
4839
 
qemudCanonicalizeMachine(struct qemud_driver *driver, virDomainDefPtr def)
4840
 
{
4841
 
    char *canonical = NULL;
4842
 
    int i;
4843
 
 
4844
 
    for (i = 0; i < driver->caps->nguests; i++) {
4845
 
        virCapsGuestPtr guest = driver->caps->guests[i];
4846
 
        virCapsGuestDomainInfoPtr info;
4847
 
        int j;
4848
 
 
4849
 
        for (j = 0; j < guest->arch.ndomains; j++) {
4850
 
            info = &guest->arch.domains[j]->info;
4851
 
 
4852
 
            if (!info->emulator || !STREQ(info->emulator, def->emulator))
4853
 
                continue;
4854
 
 
4855
 
            if (!info->nmachines)
4856
 
                info = &guest->arch.defaultInfo;
4857
 
 
4858
 
            if (qemudCanonicalizeMachineFromInfo(def, info, &canonical) < 0)
4859
 
                return -1;
4860
 
            goto out;
4861
 
        }
4862
 
 
4863
 
        info = &guest->arch.defaultInfo;
4864
 
 
4865
 
        if (info->emulator && STREQ(info->emulator, def->emulator)) {
4866
 
            if (qemudCanonicalizeMachineFromInfo(def, info, &canonical) < 0)
4867
 
                return -1;
4868
 
            goto out;
4869
 
        }
4870
 
    }
4871
 
 
4872
 
    if (qemudCanonicalizeMachineDirect(def, &canonical) < 0)
4873
 
        return -1;
4874
 
 
4875
 
out:
4876
 
    if (canonical) {
4877
 
        VIR_FREE(def->os.machine);
4878
 
        def->os.machine = canonical;
4879
 
    }
4880
 
    return 0;
4881
 
}
4882
 
 
4883
 
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
4884
 
    struct qemud_driver *driver = conn->privateData;
4885
 
    virDomainDefPtr def;
4886
 
    virDomainObjPtr vm = NULL;
4887
 
    virDomainPtr dom = NULL;
4888
 
    virDomainEventPtr event = NULL;
4889
 
    int dupVM;
4890
 
 
4891
 
    qemuDriverLock(driver);
4892
 
    if (!(def = virDomainDefParseString(driver->caps, xml,
4893
 
                                        QEMU_EXPECTED_VIRT_TYPES,
4894
 
                                        VIR_DOMAIN_XML_INACTIVE)))
4895
 
        goto cleanup;
4896
 
 
4897
 
    if (virSecurityManagerVerify(driver->securityManager, def) < 0)
4898
 
        goto cleanup;
4899
 
 
4900
 
    if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
4901
 
        goto cleanup;
4902
 
 
4903
 
    if (qemudCanonicalizeMachine(driver, def) < 0)
4904
 
        goto cleanup;
4905
 
 
4906
 
    if (qemuDomainAssignPCIAddresses(def) < 0)
4907
 
        goto cleanup;
4908
 
 
4909
 
    if (!(vm = virDomainAssignDef(driver->caps,
4910
 
                                  &driver->domains,
4911
 
                                  def, false))) {
4912
 
        goto cleanup;
4913
 
    }
4914
 
    def = NULL;
4915
 
    vm->persistent = 1;
4916
 
 
4917
 
    if (virDomainSaveConfig(driver->configDir,
4918
 
                            vm->newDef ? vm->newDef : vm->def) < 0) {
4919
 
        VIR_INFO("Defining domain '%s'", vm->def->name);
4920
 
        qemuDomainRemoveInactive(driver, vm);
4921
 
        vm = NULL;
4922
 
        goto cleanup;
4923
 
    }
4924
 
 
4925
 
    event = virDomainEventNewFromObj(vm,
4926
 
                                     VIR_DOMAIN_EVENT_DEFINED,
4927
 
                                     !dupVM ?
4928
 
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
4929
 
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
4930
 
 
4931
 
    VIR_INFO("Creating domain '%s'", vm->def->name);
4932
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
4933
 
    if (dom) dom->id = vm->def->id;
4934
 
 
4935
 
cleanup:
4936
 
    virDomainDefFree(def);
4937
 
    if (vm)
4938
 
        virDomainObjUnlock(vm);
4939
 
    if (event)
4940
 
        qemuDomainEventQueue(driver, event);
4941
 
    qemuDriverUnlock(driver);
4942
 
    return dom;
4943
 
}
4944
 
 
4945
 
static int
4946
 
qemuDomainUndefineFlags(virDomainPtr dom,
4947
 
                        unsigned int flags)
4948
 
{
4949
 
    struct qemud_driver *driver = dom->conn->privateData;
4950
 
    virDomainObjPtr vm;
4951
 
    virDomainEventPtr event = NULL;
4952
 
    char *name = NULL;
4953
 
    int ret = -1;
4954
 
    int nsnapshots;
4955
 
 
4956
 
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
4957
 
                  VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
4958
 
 
4959
 
    qemuDriverLock(driver);
4960
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
4961
 
 
4962
 
    if (!vm) {
4963
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
4964
 
        virUUIDFormat(dom->uuid, uuidstr);
4965
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
4966
 
                        _("no domain with matching uuid '%s'"), uuidstr);
4967
 
        goto cleanup;
4968
 
    }
4969
 
 
4970
 
    if (!vm->persistent) {
4971
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
4972
 
                        "%s", _("cannot undefine transient domain"));
4973
 
        goto cleanup;
4974
 
    }
4975
 
 
4976
 
    if (!virDomainObjIsActive(vm) &&
4977
 
        (nsnapshots = virDomainSnapshotObjListNum(&vm->snapshots, 0))) {
4978
 
        if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
4979
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
4980
 
                            _("cannot delete inactive domain with %d "
4981
 
                              "snapshots"),
4982
 
                            nsnapshots);
4983
 
            goto cleanup;
4984
 
        }
4985
 
        if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0)
4986
 
            goto cleanup;
4987
 
    }
4988
 
 
4989
 
    name = qemuDomainManagedSavePath(driver, vm);
4990
 
    if (name == NULL)
4991
 
        goto cleanup;
4992
 
 
4993
 
    if (virFileExists(name)) {
4994
 
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
4995
 
            if (unlink(name) < 0) {
4996
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4997
 
                                _("Failed to remove domain managed "
4998
 
                                  "save image"));
4999
 
                goto cleanup;
5000
 
            }
5001
 
        } else {
5002
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
5003
 
                            _("Refusing to undefine while domain managed "
5004
 
                              "save image exists"));
5005
 
            goto cleanup;
5006
 
        }
5007
 
    }
5008
 
 
5009
 
    if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0)
5010
 
        goto cleanup;
5011
 
 
5012
 
    event = virDomainEventNewFromObj(vm,
5013
 
                                     VIR_DOMAIN_EVENT_UNDEFINED,
5014
 
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
5015
 
 
5016
 
    VIR_INFO("Undefining domain '%s'", vm->def->name);
5017
 
 
5018
 
    /* If the domain is active, keep it running but set it as transient.
5019
 
     * domainDestroy and domainShutdown will take care of removing the
5020
 
     * domain obj from the hash table.
5021
 
     */
5022
 
    if (virDomainObjIsActive(vm)) {
5023
 
        vm->persistent = 0;
5024
 
    } else {
5025
 
        qemuDomainRemoveInactive(driver, vm);
5026
 
        vm = NULL;
5027
 
    }
5028
 
 
5029
 
    ret = 0;
5030
 
 
5031
 
cleanup:
5032
 
    VIR_FREE(name);
5033
 
    if (vm)
5034
 
        virDomainObjUnlock(vm);
5035
 
    if (event)
5036
 
        qemuDomainEventQueue(driver, event);
5037
 
    qemuDriverUnlock(driver);
5038
 
    return ret;
5039
 
}
5040
 
 
5041
 
static int
5042
 
qemudDomainUndefine(virDomainPtr dom)
5043
 
{
5044
 
    return qemuDomainUndefineFlags(dom, 0);
5045
 
}
5046
 
 
5047
 
static int
5048
 
qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
5049
 
                               struct qemud_driver *driver,
5050
 
                               virDomainObjPtr vm,
5051
 
                               virDomainDeviceDefPtr dev)
5052
 
{
5053
 
    virDomainDiskDefPtr disk = dev->data.disk;
5054
 
    virCgroupPtr cgroup = NULL;
5055
 
    int ret = -1;
5056
 
 
5057
 
    if (disk->driverName != NULL && !STREQ(disk->driverName, "qemu")) {
5058
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5059
 
                        _("unsupported driver name '%s' for disk '%s'"),
5060
 
                        disk->driverName, disk->src);
5061
 
        goto end;
5062
 
    }
5063
 
 
5064
 
    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
5065
 
        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0)) {
5066
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
5067
 
                            _("Unable to find cgroup for %s"),
5068
 
                            vm->def->name);
5069
 
            goto end;
5070
 
        }
5071
 
        if (qemuSetupDiskCgroup(driver, vm, cgroup, disk) < 0)
5072
 
            goto end;
5073
 
    }
5074
 
    switch (disk->device)  {
5075
 
    case VIR_DOMAIN_DISK_DEVICE_CDROM:
5076
 
    case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
5077
 
        ret = qemuDomainChangeEjectableMedia(driver, vm, disk, false);
5078
 
        break;
5079
 
    case VIR_DOMAIN_DISK_DEVICE_DISK:
5080
 
        if (disk->bus == VIR_DOMAIN_DISK_BUS_USB)
5081
 
            ret = qemuDomainAttachUsbMassstorageDevice(conn, driver, vm,
5082
 
                                                       disk);
5083
 
        else if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)
5084
 
            ret = qemuDomainAttachPciDiskDevice(conn, driver, vm, disk);
5085
 
        else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI)
5086
 
            ret = qemuDomainAttachSCSIDisk(conn, driver, vm, disk);
5087
 
        else
5088
 
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5089
 
                            _("disk bus '%s' cannot be hotplugged."),
5090
 
                            virDomainDiskBusTypeToString(disk->bus));
5091
 
        break;
5092
 
    default:
5093
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5094
 
                        _("disk device type '%s' cannot be hotplugged"),
5095
 
                        virDomainDiskDeviceTypeToString(disk->device));
5096
 
        break;
5097
 
    }
5098
 
 
5099
 
    if (ret != 0 && cgroup) {
5100
 
        if (qemuTeardownDiskCgroup(driver, vm, cgroup, disk) < 0)
5101
 
            VIR_WARN("Failed to teardown cgroup for disk path %s",
5102
 
                     NULLSTR(disk->src));
5103
 
    }
5104
 
end:
5105
 
    if (cgroup)
5106
 
        virCgroupFree(&cgroup);
5107
 
    return ret;
5108
 
}
5109
 
 
5110
 
static int
5111
 
qemuDomainAttachDeviceControllerLive(struct qemud_driver *driver,
5112
 
                                     virDomainObjPtr vm,
5113
 
                                     virDomainDeviceDefPtr dev)
5114
 
{
5115
 
    virDomainControllerDefPtr cont = dev->data.controller;
5116
 
    int ret = -1;
5117
 
 
5118
 
    switch (cont->type) {
5119
 
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5120
 
        ret = qemuDomainAttachPciControllerDevice(driver, vm, cont);
5121
 
        break;
5122
 
    default:
5123
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5124
 
                        _("disk controller bus '%s' cannot be hotplugged."),
5125
 
                        virDomainControllerTypeToString(cont->type));
5126
 
        break;
5127
 
    }
5128
 
    return ret;
5129
 
}
5130
 
 
5131
 
static int
5132
 
qemuDomainAttachDeviceLive(virDomainObjPtr vm,
5133
 
                           virDomainDeviceDefPtr dev,
5134
 
                           virDomainPtr dom)
5135
 
{
5136
 
    struct qemud_driver *driver = dom->conn->privateData;
5137
 
    int ret = -1;
5138
 
 
5139
 
    switch (dev->type) {
5140
 
    case VIR_DOMAIN_DEVICE_DISK:
5141
 
        qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, -1);
5142
 
        ret = qemuDomainAttachDeviceDiskLive(dom->conn, driver, vm, dev);
5143
 
        if (!ret)
5144
 
            dev->data.disk = NULL;
5145
 
        break;
5146
 
 
5147
 
    case VIR_DOMAIN_DEVICE_CONTROLLER:
5148
 
        ret = qemuDomainAttachDeviceControllerLive(driver, vm, dev);
5149
 
        if (!ret)
5150
 
            dev->data.controller = NULL;
5151
 
        break;
5152
 
 
5153
 
    case VIR_DOMAIN_DEVICE_LEASE:
5154
 
        ret = qemuDomainAttachLease(driver, vm,
5155
 
                                    dev->data.lease);
5156
 
        if (ret == 0)
5157
 
            dev->data.lease = NULL;
5158
 
        break;
5159
 
 
5160
 
    case VIR_DOMAIN_DEVICE_NET:
5161
 
        qemuDomainObjCheckNetTaint(driver, vm, dev->data.net, -1);
5162
 
        ret = qemuDomainAttachNetDevice(dom->conn, driver, vm,
5163
 
                                        dev->data.net);
5164
 
        if (!ret)
5165
 
            dev->data.net = NULL;
5166
 
        break;
5167
 
 
5168
 
    case VIR_DOMAIN_DEVICE_HOSTDEV:
5169
 
        ret = qemuDomainAttachHostDevice(driver, vm,
5170
 
                                         dev->data.hostdev);
5171
 
        if (!ret)
5172
 
            dev->data.hostdev = NULL;
5173
 
        break;
5174
 
 
5175
 
    case VIR_DOMAIN_DEVICE_REDIRDEV:
5176
 
        ret = qemuDomainAttachRedirdevDevice(driver, vm,
5177
 
                                             dev->data.redirdev);
5178
 
        if (!ret)
5179
 
            dev->data.redirdev = NULL;
5180
 
        break;
5181
 
 
5182
 
    default:
5183
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5184
 
                        _("device type '%s' cannot be attached"),
5185
 
                        virDomainDeviceTypeToString(dev->type));
5186
 
        break;
5187
 
    }
5188
 
 
5189
 
    return ret;
5190
 
}
5191
 
 
5192
 
static int
5193
 
qemuDomainDetachDeviceDiskLive(struct qemud_driver *driver,
5194
 
                               virDomainObjPtr vm,
5195
 
                               virDomainDeviceDefPtr dev)
5196
 
{
5197
 
    virDomainDiskDefPtr disk = dev->data.disk;
5198
 
    int ret = -1;
5199
 
 
5200
 
    switch (disk->device) {
5201
 
    case VIR_DOMAIN_DISK_DEVICE_DISK:
5202
 
        if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)
5203
 
            ret = qemuDomainDetachPciDiskDevice(driver, vm, dev);
5204
 
        else if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI)
5205
 
            ret =  qemuDomainDetachDiskDevice(driver, vm, dev);
5206
 
        else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB)
5207
 
            ret = qemuDomainDetachDiskDevice(driver, vm, dev);
5208
 
        else
5209
 
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5210
 
                            _("This type of disk cannot be hot unplugged"));
5211
 
        break;
5212
 
    default:
5213
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5214
 
                        _("disk device type '%s' cannot be detached"),
5215
 
                        virDomainDiskDeviceTypeToString(disk->type));
5216
 
        break;
5217
 
    }
5218
 
    return ret;
5219
 
}
5220
 
 
5221
 
static int
5222
 
qemuDomainDetachDeviceControllerLive(struct qemud_driver *driver,
5223
 
                                     virDomainObjPtr vm,
5224
 
                                     virDomainDeviceDefPtr dev)
5225
 
{
5226
 
    virDomainControllerDefPtr cont = dev->data.controller;
5227
 
    int ret = -1;
5228
 
 
5229
 
    switch (cont->type) {
5230
 
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
5231
 
        ret = qemuDomainDetachPciControllerDevice(driver, vm, dev);
5232
 
        break;
5233
 
    default :
5234
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5235
 
                        _("disk controller bus '%s' cannot be hotunplugged."),
5236
 
                        virDomainControllerTypeToString(cont->type));
5237
 
    }
5238
 
    return ret;
5239
 
}
5240
 
 
5241
 
static int
5242
 
qemuDomainDetachDeviceLive(virDomainObjPtr vm,
5243
 
                           virDomainDeviceDefPtr dev,
5244
 
                           virDomainPtr dom)
5245
 
{
5246
 
    struct qemud_driver *driver = dom->conn->privateData;
5247
 
    int ret = -1;
5248
 
 
5249
 
    switch (dev->type) {
5250
 
    case VIR_DOMAIN_DEVICE_DISK:
5251
 
        ret = qemuDomainDetachDeviceDiskLive(driver, vm, dev);
5252
 
        break;
5253
 
    case VIR_DOMAIN_DEVICE_CONTROLLER:
5254
 
        ret = qemuDomainDetachDeviceControllerLive(driver, vm, dev);
5255
 
        break;
5256
 
    case VIR_DOMAIN_DEVICE_LEASE:
5257
 
        ret = qemuDomainDetachLease(driver, vm, dev->data.lease);
5258
 
        break;
5259
 
    case VIR_DOMAIN_DEVICE_NET:
5260
 
        ret = qemuDomainDetachNetDevice(driver, vm, dev);
5261
 
        break;
5262
 
    case VIR_DOMAIN_DEVICE_HOSTDEV:
5263
 
        ret = qemuDomainDetachHostDevice(driver, vm, dev);
5264
 
        break;
5265
 
    default:
5266
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5267
 
                        "%s", _("This type of device cannot be hot unplugged"));
5268
 
        break;
5269
 
    }
5270
 
 
5271
 
    return ret;
5272
 
}
5273
 
 
5274
 
static int
5275
 
qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
5276
 
                              virDomainDeviceDefPtr dev,
5277
 
                              struct qemud_driver *driver,
5278
 
                              bool force)
5279
 
{
5280
 
    virDomainDiskDefPtr disk = dev->data.disk;
5281
 
    virCgroupPtr cgroup = NULL;
5282
 
    int ret = -1;
5283
 
 
5284
 
    if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
5285
 
        if (virCgroupForDomain(driver->cgroup,
5286
 
                               vm->def->name, &cgroup, 0) != 0) {
5287
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
5288
 
                            _("Unable to find cgroup for %s"),
5289
 
                            vm->def->name);
5290
 
            goto end;
5291
 
        }
5292
 
        if (qemuSetupDiskCgroup(driver, vm, cgroup, disk) < 0)
5293
 
            goto end;
5294
 
    }
5295
 
 
5296
 
    switch (disk->device) {
5297
 
    case VIR_DOMAIN_DISK_DEVICE_CDROM:
5298
 
    case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
5299
 
        ret = qemuDomainChangeEjectableMedia(driver, vm, disk, force);
5300
 
        if (ret == 0)
5301
 
            dev->data.disk = NULL;
5302
 
        break;
5303
 
    default:
5304
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5305
 
                        _("disk bus '%s' cannot be updated."),
5306
 
                        virDomainDiskBusTypeToString(disk->bus));
5307
 
        break;
5308
 
    }
5309
 
 
5310
 
    if (ret != 0 && cgroup) {
5311
 
        if (qemuTeardownDiskCgroup(driver, vm, cgroup, disk) < 0)
5312
 
             VIR_WARN("Failed to teardown cgroup for disk path %s",
5313
 
                      NULLSTR(disk->src));
5314
 
    }
5315
 
end:
5316
 
    if (cgroup)
5317
 
        virCgroupFree(&cgroup);
5318
 
    return ret;
5319
 
}
5320
 
 
5321
 
static int
5322
 
qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
5323
 
                           virDomainDeviceDefPtr dev,
5324
 
                           virDomainPtr dom,
5325
 
                           bool force)
5326
 
{
5327
 
    struct qemud_driver *driver = dom->conn->privateData;
5328
 
    int ret = -1;
5329
 
 
5330
 
    switch (dev->type) {
5331
 
    case VIR_DOMAIN_DEVICE_DISK:
5332
 
        ret = qemuDomainChangeDiskMediaLive(vm, dev, driver, force);
5333
 
        break;
5334
 
    case VIR_DOMAIN_DEVICE_GRAPHICS:
5335
 
        ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
5336
 
        break;
5337
 
    case VIR_DOMAIN_DEVICE_NET:
5338
 
        ret = qemuDomainChangeNet(driver, vm, dom, dev->data.net);
5339
 
        break;
5340
 
    default:
5341
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5342
 
                        _("device type '%s' cannot be updated"),
5343
 
                        virDomainDeviceTypeToString(dev->type));
5344
 
        break;
5345
 
    }
5346
 
 
5347
 
    return ret;
5348
 
}
5349
 
 
5350
 
static int
5351
 
qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
5352
 
                             virDomainDeviceDefPtr dev)
5353
 
{
5354
 
    virDomainDiskDefPtr disk;
5355
 
    virDomainNetDefPtr net;
5356
 
    virDomainLeaseDefPtr lease;
5357
 
 
5358
 
    switch (dev->type) {
5359
 
    case VIR_DOMAIN_DEVICE_DISK:
5360
 
        disk = dev->data.disk;
5361
 
        if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
5362
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5363
 
                            _("target %s already exists."), disk->dst);
5364
 
            return -1;
5365
 
        }
5366
 
        if (virDomainDiskInsert(vmdef, disk)) {
5367
 
            virReportOOMError();
5368
 
            return -1;
5369
 
        }
5370
 
        /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
5371
 
        dev->data.disk = NULL;
5372
 
        if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
5373
 
            if (virDomainDefAddImplicitControllers(vmdef) < 0)
5374
 
                return -1;
5375
 
        if (qemuDomainAssignPCIAddresses(vmdef) < 0)
5376
 
            return -1;
5377
 
        break;
5378
 
 
5379
 
    case VIR_DOMAIN_DEVICE_NET:
5380
 
        net = dev->data.net;
5381
 
        if (virDomainNetIndexByMac(vmdef, net->mac) >= 0) {
5382
 
            char macbuf[VIR_MAC_STRING_BUFLEN];
5383
 
            virFormatMacAddr(net->mac, macbuf);
5384
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5385
 
                            _("mac %s already exists"), macbuf);
5386
 
            return -1;
5387
 
        }
5388
 
        if (virDomainNetInsert(vmdef, net)) {
5389
 
            virReportOOMError();
5390
 
            return -1;
5391
 
        }
5392
 
        dev->data.net = NULL;
5393
 
        if (qemuDomainAssignPCIAddresses(vmdef) < 0)
5394
 
            return -1;
5395
 
        break;
5396
 
 
5397
 
    case VIR_DOMAIN_DEVICE_LEASE:
5398
 
        lease = dev->data.lease;
5399
 
        if (virDomainLeaseIndex(vmdef, lease) >= 0) {
5400
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5401
 
                            _("Lease %s in lockspace %s already exists"),
5402
 
                            lease->key, NULLSTR(lease->lockspace));
5403
 
            return -1;
5404
 
        }
5405
 
        if (virDomainLeaseInsert(vmdef, lease) < 0)
5406
 
            return -1;
5407
 
 
5408
 
        /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
5409
 
        dev->data.lease = NULL;
5410
 
        break;
5411
 
 
5412
 
    default:
5413
 
         qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5414
 
                         _("persistent attach of device is not supported"));
5415
 
         return -1;
5416
 
    }
5417
 
    return 0;
5418
 
}
5419
 
 
5420
 
 
5421
 
static int
5422
 
qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
5423
 
                             virDomainDeviceDefPtr dev)
5424
 
{
5425
 
    virDomainDiskDefPtr disk;
5426
 
    virDomainNetDefPtr net;
5427
 
    virDomainLeaseDefPtr lease;
5428
 
 
5429
 
    switch (dev->type) {
5430
 
    case VIR_DOMAIN_DEVICE_DISK:
5431
 
        disk = dev->data.disk;
5432
 
        if (virDomainDiskRemoveByName(vmdef, disk->dst)) {
5433
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5434
 
                            _("no target device %s"), disk->dst);
5435
 
            return -1;
5436
 
        }
5437
 
        break;
5438
 
 
5439
 
    case VIR_DOMAIN_DEVICE_NET:
5440
 
        net = dev->data.net;
5441
 
        if (virDomainNetRemoveByMac(vmdef, net->mac)) {
5442
 
            char macbuf[VIR_MAC_STRING_BUFLEN];
5443
 
 
5444
 
            virFormatMacAddr(net->mac, macbuf);
5445
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5446
 
                            _("no nic of mac %s"), macbuf);
5447
 
            return -1;
5448
 
        }
5449
 
        break;
5450
 
 
5451
 
    case VIR_DOMAIN_DEVICE_LEASE:
5452
 
        lease = dev->data.lease;
5453
 
        if (virDomainLeaseRemove(vmdef, lease) < 0) {
5454
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5455
 
                            _("Lease %s in lockspace %s does not exist"),
5456
 
                            lease->key, NULLSTR(lease->lockspace));
5457
 
            return -1;
5458
 
        }
5459
 
        break;
5460
 
 
5461
 
    default:
5462
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5463
 
                        _("persistent detach of device is not supported"));
5464
 
        return -1;
5465
 
    }
5466
 
    return 0;
5467
 
}
5468
 
 
5469
 
static int
5470
 
qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
5471
 
                             virDomainDeviceDefPtr dev)
5472
 
{
5473
 
    virDomainDiskDefPtr orig, disk;
5474
 
    virDomainNetDefPtr net;
5475
 
    int pos;
5476
 
 
5477
 
    switch (dev->type) {
5478
 
    case VIR_DOMAIN_DEVICE_DISK:
5479
 
        disk = dev->data.disk;
5480
 
        pos = virDomainDiskIndexByName(vmdef, disk->dst, false);
5481
 
        if (pos < 0) {
5482
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5483
 
                            _("target %s doesn't exist."), disk->dst);
5484
 
            return -1;
5485
 
        }
5486
 
        orig = vmdef->disks[pos];
5487
 
        if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
5488
 
            !(orig->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) {
5489
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5490
 
                            _("this disk doesn't support update"));
5491
 
            return -1;
5492
 
        }
5493
 
        /*
5494
 
         * Update 'orig'
5495
 
         * We allow updating src/type//driverType/cachemode/
5496
 
         */
5497
 
        VIR_FREE(orig->src);
5498
 
        orig->src = disk->src;
5499
 
        orig->type = disk->type;
5500
 
        orig->cachemode = disk->cachemode;
5501
 
        if (disk->driverName) {
5502
 
            VIR_FREE(orig->driverName);
5503
 
            orig->driverName = disk->driverName;
5504
 
            disk->driverName = NULL;
5505
 
        }
5506
 
        if (disk->driverType) {
5507
 
            VIR_FREE(orig->driverType);
5508
 
            orig->driverType = disk->driverType;
5509
 
            disk->driverType = NULL;
5510
 
        }
5511
 
        disk->src = NULL;
5512
 
        break;
5513
 
 
5514
 
    case VIR_DOMAIN_DEVICE_NET:
5515
 
        net = dev->data.net;
5516
 
        if ((pos = virDomainNetIndexByMac(vmdef, net->mac)) < 0) {
5517
 
            char macbuf[VIR_MAC_STRING_BUFLEN];
5518
 
            virFormatMacAddr(net->mac, macbuf);
5519
 
            qemuReportError(VIR_ERR_INVALID_ARG,
5520
 
                            _("mac %s doesn't exist"), macbuf);
5521
 
            return -1;
5522
 
        }
5523
 
 
5524
 
        VIR_FREE(vmdef->nets[pos]);
5525
 
 
5526
 
        vmdef->nets[pos] = net;
5527
 
        dev->data.net = NULL;
5528
 
 
5529
 
        if (qemuDomainAssignPCIAddresses(vmdef) < 0)
5530
 
            return -1;
5531
 
        break;
5532
 
 
5533
 
    default:
5534
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5535
 
                         _("persistent update of device is not supported"));
5536
 
        return -1;
5537
 
    }
5538
 
    return 0;
5539
 
}
5540
 
 
5541
 
/* Actions for qemuDomainModifyDeviceFlags */
5542
 
enum {
5543
 
    QEMU_DEVICE_ATTACH,
5544
 
    QEMU_DEVICE_DETACH,
5545
 
    QEMU_DEVICE_UPDATE,
5546
 
};
5547
 
 
5548
 
 
5549
 
static int
5550
 
qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
5551
 
                            unsigned int flags, int action)
5552
 
{
5553
 
    struct qemud_driver *driver = dom->conn->privateData;
5554
 
    virDomainObjPtr vm = NULL;
5555
 
    virDomainDefPtr vmdef = NULL;
5556
 
    virDomainDeviceDefPtr dev = NULL;
5557
 
    bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
5558
 
    int ret = -1;
5559
 
    unsigned int affect;
5560
 
 
5561
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5562
 
                  VIR_DOMAIN_AFFECT_CONFIG |
5563
 
                  (action == QEMU_DEVICE_UPDATE ?
5564
 
                   VIR_DOMAIN_DEVICE_MODIFY_FORCE : 0), -1);
5565
 
 
5566
 
    affect = flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG);
5567
 
 
5568
 
    qemuDriverLock(driver);
5569
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
5570
 
    if (!vm) {
5571
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
5572
 
        virUUIDFormat(dom->uuid, uuidstr);
5573
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
5574
 
                        _("no domain with matching uuid '%s'"), uuidstr);
5575
 
        goto cleanup;
5576
 
    }
5577
 
 
5578
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
5579
 
        goto cleanup;
5580
 
 
5581
 
    if (virDomainObjIsActive(vm)) {
5582
 
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
5583
 
            flags |= VIR_DOMAIN_AFFECT_LIVE;
5584
 
    } else {
5585
 
        if (affect == VIR_DOMAIN_AFFECT_CURRENT)
5586
 
            flags |= VIR_DOMAIN_AFFECT_CONFIG;
5587
 
        /* check consistency between flags and the vm state */
5588
 
        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
5589
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
5590
 
                            "%s",
5591
 
                            _("cannot do live update a device on "
5592
 
                              "inactive domain"));
5593
 
            goto endjob;
5594
 
        }
5595
 
    }
5596
 
 
5597
 
    if ((flags & VIR_DOMAIN_AFFECT_CONFIG) && !vm->persistent) {
5598
 
         qemuReportError(VIR_ERR_OPERATION_INVALID,
5599
 
                         "%s", _("cannot modify device on transient domain"));
5600
 
         goto endjob;
5601
 
    }
5602
 
 
5603
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
5604
 
        dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
5605
 
                                      VIR_DOMAIN_XML_INACTIVE);
5606
 
        if (dev == NULL)
5607
 
            goto endjob;
5608
 
 
5609
 
        /* Make a copy for updated domain. */
5610
 
        vmdef = virDomainObjCopyPersistentDef(driver->caps, vm);
5611
 
        if (!vmdef)
5612
 
            goto endjob;
5613
 
        switch (action) {
5614
 
        case QEMU_DEVICE_ATTACH:
5615
 
            ret = qemuDomainAttachDeviceConfig(vmdef, dev);
5616
 
            break;
5617
 
        case QEMU_DEVICE_DETACH:
5618
 
            ret = qemuDomainDetachDeviceConfig(vmdef, dev);
5619
 
            break;
5620
 
        case QEMU_DEVICE_UPDATE:
5621
 
            ret = qemuDomainUpdateDeviceConfig(vmdef, dev);
5622
 
            break;
5623
 
        default:
5624
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
5625
 
                            _("unknown domain modify action %d"), action);
5626
 
            break;
5627
 
        }
5628
 
 
5629
 
        if (ret == -1)
5630
 
            goto endjob;
5631
 
    }
5632
 
 
5633
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
5634
 
        /* If dev exists it was created to modify the domain config. Free it. */
5635
 
        virDomainDeviceDefFree(dev);
5636
 
        dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
5637
 
                                      VIR_DOMAIN_XML_INACTIVE);
5638
 
        if (dev == NULL) {
5639
 
            ret = -1;
5640
 
            goto endjob;
5641
 
        }
5642
 
 
5643
 
        switch (action) {
5644
 
        case QEMU_DEVICE_ATTACH:
5645
 
            ret = qemuDomainAttachDeviceLive(vm, dev, dom);
5646
 
            break;
5647
 
        case QEMU_DEVICE_DETACH:
5648
 
            ret = qemuDomainDetachDeviceLive(vm, dev, dom);
5649
 
            break;
5650
 
        case QEMU_DEVICE_UPDATE:
5651
 
            ret = qemuDomainUpdateDeviceLive(vm, dev, dom, force);
5652
 
            break;
5653
 
        default:
5654
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
5655
 
                            _("unknown domain modify action %d"), action);
5656
 
            ret = -1;
5657
 
            break;
5658
 
        }
5659
 
 
5660
 
        if (ret == -1)
5661
 
            goto endjob;
5662
 
        /*
5663
 
         * update domain status forcibly because the domain status may be
5664
 
         * changed even if we failed to attach the device. For example,
5665
 
         * a new controller may be created.
5666
 
         */
5667
 
        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
5668
 
            ret = -1;
5669
 
            goto endjob;
5670
 
        }
5671
 
    }
5672
 
 
5673
 
    /* Finally, if no error until here, we can save config. */
5674
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
5675
 
        ret = virDomainSaveConfig(driver->configDir, vmdef);
5676
 
        if (!ret) {
5677
 
            virDomainObjAssignDef(vm, vmdef, false);
5678
 
            vmdef = NULL;
5679
 
        }
5680
 
    }
5681
 
 
5682
 
endjob:
5683
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
5684
 
        vm = NULL;
5685
 
 
5686
 
cleanup:
5687
 
    virDomainDefFree(vmdef);
5688
 
    virDomainDeviceDefFree(dev);
5689
 
    if (vm)
5690
 
        virDomainObjUnlock(vm);
5691
 
    qemuDriverUnlock(driver);
5692
 
    return ret;
5693
 
}
5694
 
 
5695
 
static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
5696
 
                                       unsigned int flags)
5697
 
{
5698
 
    return qemuDomainModifyDeviceFlags(dom, xml, flags, QEMU_DEVICE_ATTACH);
5699
 
}
5700
 
 
5701
 
static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml)
5702
 
{
5703
 
    return qemuDomainAttachDeviceFlags(dom, xml,
5704
 
                                       VIR_DOMAIN_AFFECT_LIVE);
5705
 
}
5706
 
 
5707
 
 
5708
 
static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
5709
 
                                       const char *xml,
5710
 
                                       unsigned int flags)
5711
 
{
5712
 
    return qemuDomainModifyDeviceFlags(dom, xml, flags, QEMU_DEVICE_UPDATE);
5713
 
}
5714
 
 
5715
 
static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
5716
 
                                       unsigned int flags)
5717
 
{
5718
 
    return qemuDomainModifyDeviceFlags(dom, xml, flags, QEMU_DEVICE_DETACH);
5719
 
}
5720
 
 
5721
 
static int qemuDomainDetachDevice(virDomainPtr dom, const char *xml)
5722
 
{
5723
 
    return qemuDomainDetachDeviceFlags(dom, xml,
5724
 
                                       VIR_DOMAIN_AFFECT_LIVE);
5725
 
}
5726
 
 
5727
 
static int qemudDomainGetAutostart(virDomainPtr dom,
5728
 
                                   int *autostart) {
5729
 
    struct qemud_driver *driver = dom->conn->privateData;
5730
 
    virDomainObjPtr vm;
5731
 
    int ret = -1;
5732
 
 
5733
 
    qemuDriverLock(driver);
5734
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
5735
 
    qemuDriverUnlock(driver);
5736
 
 
5737
 
    if (!vm) {
5738
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
5739
 
        virUUIDFormat(dom->uuid, uuidstr);
5740
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
5741
 
                        _("no domain with matching uuid '%s'"), uuidstr);
5742
 
        goto cleanup;
5743
 
    }
5744
 
 
5745
 
    *autostart = vm->autostart;
5746
 
    ret = 0;
5747
 
 
5748
 
cleanup:
5749
 
    if (vm)
5750
 
        virDomainObjUnlock(vm);
5751
 
    return ret;
5752
 
}
5753
 
 
5754
 
static int qemudDomainSetAutostart(virDomainPtr dom,
5755
 
                                   int autostart) {
5756
 
    struct qemud_driver *driver = dom->conn->privateData;
5757
 
    virDomainObjPtr vm;
5758
 
    char *configFile = NULL, *autostartLink = NULL;
5759
 
    int ret = -1;
5760
 
 
5761
 
    qemuDriverLock(driver);
5762
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
5763
 
 
5764
 
    if (!vm) {
5765
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
5766
 
        virUUIDFormat(dom->uuid, uuidstr);
5767
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
5768
 
                        _("no domain with matching uuid '%s'"), uuidstr);
5769
 
        goto cleanup;
5770
 
    }
5771
 
 
5772
 
    if (!vm->persistent) {
5773
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
5774
 
                        "%s", _("cannot set autostart for transient domain"));
5775
 
        goto cleanup;
5776
 
    }
5777
 
 
5778
 
    autostart = (autostart != 0);
5779
 
 
5780
 
    if (vm->autostart != autostart) {
5781
 
        if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
5782
 
            goto cleanup;
5783
 
        if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
5784
 
            goto cleanup;
5785
 
 
5786
 
        if (autostart) {
5787
 
            if (virFileMakePath(driver->autostartDir) < 0) {
5788
 
                virReportSystemError(errno,
5789
 
                                     _("cannot create autostart directory %s"),
5790
 
                                     driver->autostartDir);
5791
 
                goto cleanup;
5792
 
            }
5793
 
 
5794
 
            if (symlink(configFile, autostartLink) < 0) {
5795
 
                virReportSystemError(errno,
5796
 
                                     _("Failed to create symlink '%s to '%s'"),
5797
 
                                     autostartLink, configFile);
5798
 
                goto cleanup;
5799
 
            }
5800
 
        } else {
5801
 
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
5802
 
                virReportSystemError(errno,
5803
 
                                     _("Failed to delete symlink '%s'"),
5804
 
                                     autostartLink);
5805
 
                goto cleanup;
5806
 
            }
5807
 
        }
5808
 
 
5809
 
        vm->autostart = autostart;
5810
 
    }
5811
 
    ret = 0;
5812
 
 
5813
 
cleanup:
5814
 
    VIR_FREE(configFile);
5815
 
    VIR_FREE(autostartLink);
5816
 
    if (vm)
5817
 
        virDomainObjUnlock(vm);
5818
 
    qemuDriverUnlock(driver);
5819
 
    return ret;
5820
 
}
5821
 
 
5822
 
 
5823
 
/*
5824
 
 * check whether the host supports CFS bandwidth
5825
 
 *
5826
 
 * Return 1 when CFS bandwidth is supported, 0 when CFS bandwidth is not
5827
 
 * supported, -1 on error.
5828
 
 */
5829
 
static int qemuGetCpuBWStatus(virCgroupPtr cgroup)
5830
 
{
5831
 
    char *cfs_period_path = NULL;
5832
 
    int ret = -1;
5833
 
 
5834
 
    if (!cgroup)
5835
 
        return 0;
5836
 
 
5837
 
    if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
5838
 
                                  "cpu.cfs_period_us", &cfs_period_path) < 0) {
5839
 
        VIR_INFO("cannot get the path of cgroup CPU controller");
5840
 
        ret = 0;
5841
 
        goto cleanup;
5842
 
    }
5843
 
 
5844
 
    if (access(cfs_period_path, F_OK) < 0) {
5845
 
        ret = 0;
5846
 
    } else {
5847
 
        ret = 1;
5848
 
    }
5849
 
 
5850
 
cleanup:
5851
 
    VIR_FREE(cfs_period_path);
5852
 
    return ret;
5853
 
}
5854
 
 
5855
 
 
5856
 
static char *qemuGetSchedulerType(virDomainPtr dom,
5857
 
                                  int *nparams)
5858
 
{
5859
 
    struct qemud_driver *driver = dom->conn->privateData;
5860
 
    char *ret = NULL;
5861
 
    int rc;
5862
 
 
5863
 
    qemuDriverLock(driver);
5864
 
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
5865
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
5866
 
                        "%s", _("cgroup CPU controller is not mounted"));
5867
 
        goto cleanup;
5868
 
    }
5869
 
 
5870
 
    if (nparams) {
5871
 
        rc = qemuGetCpuBWStatus(driver->cgroup);
5872
 
        if (rc < 0)
5873
 
            goto cleanup;
5874
 
        else if (rc == 0)
5875
 
            *nparams = 1;
5876
 
        else
5877
 
            *nparams = 3;
5878
 
    }
5879
 
 
5880
 
    ret = strdup("posix");
5881
 
    if (!ret)
5882
 
        virReportOOMError();
5883
 
 
5884
 
cleanup:
5885
 
    qemuDriverUnlock(driver);
5886
 
    return ret;
5887
 
}
5888
 
 
5889
 
/* deviceWeightStr in the form of /device/path,weight,/device/path,weight
5890
 
 * for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800
5891
 
 */
5892
 
static int
5893
 
qemuDomainParseDeviceWeightStr(char *deviceWeightStr,
5894
 
                               virBlkioDeviceWeightPtr *dw, size_t *size)
5895
 
{
5896
 
    char *temp;
5897
 
    int ndevices = 0;
5898
 
    int nsep = 0;
5899
 
    int i;
5900
 
    virBlkioDeviceWeightPtr result = NULL;
5901
 
 
5902
 
    temp = deviceWeightStr;
5903
 
    while (temp) {
5904
 
        temp = strchr(temp, ',');
5905
 
        if (temp) {
5906
 
            temp++;
5907
 
            nsep++;
5908
 
        }
5909
 
    }
5910
 
 
5911
 
    /* A valid string must have even number of fields, hence an odd
5912
 
     * number of commas.  */
5913
 
    if (!(nsep & 1))
5914
 
        goto error;
5915
 
 
5916
 
    ndevices = (nsep + 1) / 2;
5917
 
 
5918
 
    if (VIR_ALLOC_N(result, ndevices) < 0) {
5919
 
        virReportOOMError();
5920
 
        return -1;
5921
 
    }
5922
 
 
5923
 
    i = 0;
5924
 
    temp = deviceWeightStr;
5925
 
    while (temp) {
5926
 
        char *p = temp;
5927
 
 
5928
 
        /* device path */
5929
 
        p = strchr(p, ',');
5930
 
        if (!p)
5931
 
            goto error;
5932
 
 
5933
 
        result[i].path = strndup(temp, p - temp);
5934
 
        if (!result[i].path) {
5935
 
            virReportOOMError();
5936
 
            goto cleanup;
5937
 
        }
5938
 
 
5939
 
        /* weight */
5940
 
        temp = p + 1;
5941
 
 
5942
 
        if (virStrToLong_ui(temp, &p, 10, &result[i].weight) < 0)
5943
 
            goto error;
5944
 
 
5945
 
        i++;
5946
 
 
5947
 
        if (*p == '\0')
5948
 
            break;
5949
 
        else if (*p != ',')
5950
 
            goto error;
5951
 
        temp = p + 1;
5952
 
    }
5953
 
 
5954
 
    if (!i)
5955
 
        VIR_FREE(result);
5956
 
 
5957
 
    *dw = result;
5958
 
    *size = i;
5959
 
 
5960
 
    return 0;
5961
 
 
5962
 
error:
5963
 
    qemuReportError(VIR_ERR_INVALID_ARG,
5964
 
                    _("unable to parse %s"), deviceWeightStr);
5965
 
cleanup:
5966
 
    virBlkioDeviceWeightArrayClear(result, ndevices);
5967
 
    VIR_FREE(result);
5968
 
    return -1;
5969
 
}
5970
 
 
5971
 
/* Modify def to reflect all device weight changes described in tmp.  */
5972
 
static int
5973
 
qemuDomainMergeDeviceWeights(virBlkioDeviceWeightPtr *def, size_t *def_size,
5974
 
                             virBlkioDeviceWeightPtr tmp, size_t tmp_size)
5975
 
{
5976
 
    int i, j;
5977
 
    virBlkioDeviceWeightPtr dw;
5978
 
 
5979
 
    for (i = 0; i < tmp_size; i++) {
5980
 
        bool found = false;
5981
 
 
5982
 
        dw = &tmp[i];
5983
 
        for (j = 0; j < *def_size; j++) {
5984
 
            if (STREQ(dw->path, (*def)[j].path)) {
5985
 
                found = true;
5986
 
                (*def)[j].weight = dw->weight;
5987
 
                break;
5988
 
            }
5989
 
        }
5990
 
        if (!found) {
5991
 
            if (!dw->weight)
5992
 
                continue;
5993
 
            if (VIR_EXPAND_N(*def, *def_size, 1) < 0) {
5994
 
                virReportOOMError();
5995
 
                return -1;
5996
 
            }
5997
 
            (*def)[*def_size - 1].path = dw->path;
5998
 
            (*def)[*def_size - 1].weight = dw->weight;
5999
 
            dw->path = NULL;
6000
 
        }
6001
 
    }
6002
 
 
6003
 
    return 0;
6004
 
}
6005
 
 
6006
 
static int qemuDomainSetBlkioParameters(virDomainPtr dom,
6007
 
                                         virTypedParameterPtr params,
6008
 
                                         int nparams,
6009
 
                                         unsigned int flags)
6010
 
{
6011
 
    struct qemud_driver *driver = dom->conn->privateData;
6012
 
    int i;
6013
 
    virCgroupPtr group = NULL;
6014
 
    virDomainObjPtr vm = NULL;
6015
 
    virDomainDefPtr persistentDef = NULL;
6016
 
    int ret = -1;
6017
 
    bool isActive;
6018
 
 
6019
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6020
 
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
6021
 
    qemuDriverLock(driver);
6022
 
 
6023
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6024
 
 
6025
 
    if (vm == NULL) {
6026
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
6027
 
                        _("No such domain %s"), dom->uuid);
6028
 
        goto cleanup;
6029
 
    }
6030
 
 
6031
 
    isActive = virDomainObjIsActive(vm);
6032
 
 
6033
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
6034
 
        if (isActive)
6035
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
6036
 
        else
6037
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
6038
 
    }
6039
 
 
6040
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6041
 
        if (!isActive) {
6042
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6043
 
                            "%s", _("domain is not running"));
6044
 
            goto cleanup;
6045
 
        }
6046
 
 
6047
 
        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
6048
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted"));
6049
 
            goto cleanup;
6050
 
        }
6051
 
 
6052
 
        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
6053
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6054
 
                            _("cannot find cgroup for domain %s"), vm->def->name);
6055
 
            goto cleanup;
6056
 
        }
6057
 
    }
6058
 
 
6059
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6060
 
        if (!vm->persistent) {
6061
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
6062
 
                            _("cannot change persistent config of a transient domain"));
6063
 
            goto cleanup;
6064
 
        }
6065
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
6066
 
            goto cleanup;
6067
 
    }
6068
 
 
6069
 
    ret = 0;
6070
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6071
 
        for (i = 0; i < nparams; i++) {
6072
 
            int rc;
6073
 
            virTypedParameterPtr param = &params[i];
6074
 
 
6075
 
            if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
6076
 
                if (param->type != VIR_TYPED_PARAM_UINT) {
6077
 
                    qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6078
 
                                    _("invalid type for blkio weight tunable, expected a 'unsigned int'"));
6079
 
                    ret = -1;
6080
 
                    continue;
6081
 
                }
6082
 
 
6083
 
                if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
6084
 
                    qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6085
 
                                    _("out of blkio weight range."));
6086
 
                    ret = -1;
6087
 
                    continue;
6088
 
                }
6089
 
 
6090
 
                rc = virCgroupSetBlkioWeight(group, params[i].value.ui);
6091
 
                if (rc != 0) {
6092
 
                    virReportSystemError(-rc, "%s",
6093
 
                                         _("unable to set blkio weight tunable"));
6094
 
                    ret = -1;
6095
 
                }
6096
 
            } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
6097
 
                size_t ndevices;
6098
 
                virBlkioDeviceWeightPtr devices = NULL;
6099
 
                if (param->type != VIR_TYPED_PARAM_STRING) {
6100
 
                    qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6101
 
                                    _("invalid type for device_weight tunable, "
6102
 
                                      "expected a 'char *'"));
6103
 
                    ret = -1;
6104
 
                    continue;
6105
 
                }
6106
 
 
6107
 
                if (qemuDomainParseDeviceWeightStr(params[i].value.s,
6108
 
                                                   &devices,
6109
 
                                                   &ndevices) < 0) {
6110
 
                    ret = -1;
6111
 
                    continue;
6112
 
                }
6113
 
                for (i = 0; i < ndevices; i++) {
6114
 
                    rc = virCgroupSetBlkioDeviceWeight(group,
6115
 
                                                       devices[i].path,
6116
 
                                                       devices[i].weight);
6117
 
                    if (rc < 0) {
6118
 
                        virReportSystemError(-rc,
6119
 
                                             _("Unable to set io device weight "
6120
 
                                               "for path %s"),
6121
 
                                             devices[i].path);
6122
 
                        break;
6123
 
                    }
6124
 
                }
6125
 
                if (i != ndevices) {
6126
 
                    ret = -1;
6127
 
                    continue;
6128
 
                }
6129
 
                if (qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
6130
 
                                                 &vm->def->blkio.ndevices,
6131
 
                                                 devices, ndevices) < 0)
6132
 
                    ret = -1;
6133
 
                virBlkioDeviceWeightArrayClear(devices, ndevices);
6134
 
                VIR_FREE(devices);
6135
 
            } else {
6136
 
                qemuReportError(VIR_ERR_INVALID_ARG,
6137
 
                                _("Parameter `%s' not supported"),
6138
 
                                param->field);
6139
 
                ret = -1;
6140
 
            }
6141
 
        }
6142
 
    }
6143
 
    if (ret < 0)
6144
 
        goto cleanup;
6145
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6146
 
        /* Clang can't see that if we get here, persistentDef was set.  */
6147
 
        sa_assert(persistentDef);
6148
 
 
6149
 
        for (i = 0; i < nparams; i++) {
6150
 
            virTypedParameterPtr param = &params[i];
6151
 
 
6152
 
            if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
6153
 
                if (param->type != VIR_TYPED_PARAM_UINT) {
6154
 
                    qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6155
 
                                    _("invalid type for blkio weight tunable, expected a 'unsigned int'"));
6156
 
                    ret = -1;
6157
 
                    continue;
6158
 
                }
6159
 
 
6160
 
                if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
6161
 
                    qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6162
 
                                    _("out of blkio weight range."));
6163
 
                    ret = -1;
6164
 
                    continue;
6165
 
                }
6166
 
 
6167
 
                persistentDef->blkio.weight = params[i].value.ui;
6168
 
            } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
6169
 
                virBlkioDeviceWeightPtr devices = NULL;
6170
 
                size_t ndevices;
6171
 
                if (param->type != VIR_TYPED_PARAM_STRING) {
6172
 
                    qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6173
 
                                    _("invalid type for device_weight tunable, "
6174
 
                                      "expected a 'char *'"));
6175
 
                    ret = -1;
6176
 
                    continue;
6177
 
                }
6178
 
                if (qemuDomainParseDeviceWeightStr(params[i].value.s,
6179
 
                                                   &devices,
6180
 
                                                   &ndevices) < 0) {
6181
 
                    ret = -1;
6182
 
                    continue;
6183
 
                }
6184
 
                if (qemuDomainMergeDeviceWeights(&vm->def->blkio.devices,
6185
 
                                                 &vm->def->blkio.ndevices,
6186
 
                                                 devices, ndevices) < 0)
6187
 
                    ret = -1;
6188
 
                virBlkioDeviceWeightArrayClear(devices, ndevices);
6189
 
                VIR_FREE(devices);
6190
 
            } else {
6191
 
                qemuReportError(VIR_ERR_INVALID_ARG,
6192
 
                                _("Parameter `%s' not supported"),
6193
 
                                param->field);
6194
 
                ret = -1;
6195
 
            }
6196
 
        }
6197
 
 
6198
 
        if (virDomainSaveConfig(driver->configDir, persistentDef) < 0)
6199
 
            ret = -1;
6200
 
    }
6201
 
 
6202
 
cleanup:
6203
 
    virCgroupFree(&group);
6204
 
    if (vm)
6205
 
        virDomainObjUnlock(vm);
6206
 
    qemuDriverUnlock(driver);
6207
 
    return ret;
6208
 
}
6209
 
 
6210
 
static int qemuDomainGetBlkioParameters(virDomainPtr dom,
6211
 
                                         virTypedParameterPtr params,
6212
 
                                         int *nparams,
6213
 
                                         unsigned int flags)
6214
 
{
6215
 
    struct qemud_driver *driver = dom->conn->privateData;
6216
 
    int i, j;
6217
 
    virCgroupPtr group = NULL;
6218
 
    virDomainObjPtr vm = NULL;
6219
 
    virDomainDefPtr persistentDef = NULL;
6220
 
    unsigned int val;
6221
 
    int ret = -1;
6222
 
    int rc;
6223
 
    bool isActive;
6224
 
 
6225
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6226
 
                  VIR_DOMAIN_AFFECT_CONFIG |
6227
 
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
6228
 
    qemuDriverLock(driver);
6229
 
 
6230
 
    /* We blindly return a string, and let libvirt.c and
6231
 
     * remote_driver.c do the filtering on behalf of older clients
6232
 
     * that can't parse it.  */
6233
 
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
6234
 
 
6235
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6236
 
 
6237
 
    if (vm == NULL) {
6238
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
6239
 
                        _("No such domain %s"), dom->uuid);
6240
 
        goto cleanup;
6241
 
    }
6242
 
 
6243
 
    if ((*nparams) == 0) {
6244
 
        /* Current number of blkio parameters supported by cgroups */
6245
 
        *nparams = QEMU_NB_BLKIO_PARAM;
6246
 
        ret = 0;
6247
 
        goto cleanup;
6248
 
    }
6249
 
 
6250
 
    isActive = virDomainObjIsActive(vm);
6251
 
 
6252
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
6253
 
        if (isActive)
6254
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
6255
 
        else
6256
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
6257
 
    }
6258
 
 
6259
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6260
 
        if (!isActive) {
6261
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6262
 
                            "%s", _("domain is not running"));
6263
 
            goto cleanup;
6264
 
        }
6265
 
 
6266
 
        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
6267
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted"));
6268
 
            goto cleanup;
6269
 
        }
6270
 
 
6271
 
        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
6272
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6273
 
                            _("cannot find cgroup for domain %s"), vm->def->name);
6274
 
            goto cleanup;
6275
 
        }
6276
 
    }
6277
 
 
6278
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6279
 
        if (!vm->persistent) {
6280
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
6281
 
                            _("cannot change persistent config of a transient domain"));
6282
 
            goto cleanup;
6283
 
        }
6284
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
6285
 
            goto cleanup;
6286
 
    }
6287
 
 
6288
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6289
 
        for (i = 0; i < *nparams && i < QEMU_NB_BLKIO_PARAM; i++) {
6290
 
            virTypedParameterPtr param = &params[i];
6291
 
            val = 0;
6292
 
            param->value.ui = 0;
6293
 
            param->type = VIR_TYPED_PARAM_UINT;
6294
 
 
6295
 
            switch (i) {
6296
 
            case 0: /* fill blkio weight here */
6297
 
                rc = virCgroupGetBlkioWeight(group, &val);
6298
 
                if (rc != 0) {
6299
 
                    virReportSystemError(-rc, "%s",
6300
 
                                         _("unable to get blkio weight"));
6301
 
                    goto cleanup;
6302
 
                }
6303
 
                if (virStrcpyStatic(param->field, VIR_DOMAIN_BLKIO_WEIGHT) == NULL) {
6304
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
6305
 
                                    _("Field name '%s' too long"),
6306
 
                                    VIR_DOMAIN_BLKIO_WEIGHT);
6307
 
                    goto cleanup;
6308
 
                }
6309
 
                param->value.ui = val;
6310
 
                break;
6311
 
            case 1: /* blkiotune.device_weight */
6312
 
                if (vm->def->blkio.ndevices > 0) {
6313
 
                    virBuffer buf = VIR_BUFFER_INITIALIZER;
6314
 
                    bool comma = false;
6315
 
 
6316
 
                    for (j = 0; j < vm->def->blkio.ndevices; j++) {
6317
 
                        if (!vm->def->blkio.devices[j].weight)
6318
 
                            continue;
6319
 
                        if (comma)
6320
 
                            virBufferAddChar(&buf, ',');
6321
 
                        else
6322
 
                            comma = true;
6323
 
                        virBufferAsprintf(&buf, "%s,%u",
6324
 
                                          vm->def->blkio.devices[j].path,
6325
 
                                          vm->def->blkio.devices[j].weight);
6326
 
                    }
6327
 
                    if (virBufferError(&buf)) {
6328
 
                        virReportOOMError();
6329
 
                        goto cleanup;
6330
 
                    }
6331
 
                    param->value.s = virBufferContentAndReset(&buf);
6332
 
                }
6333
 
                if (!param->value.s) {
6334
 
                    param->value.s = strdup("");
6335
 
                    if (!param->value.s) {
6336
 
                        virReportOOMError();
6337
 
                        goto cleanup;
6338
 
                    }
6339
 
                }
6340
 
                param->type = VIR_TYPED_PARAM_STRING;
6341
 
                if (virStrcpyStatic(param->field,
6342
 
                                    VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) == NULL) {
6343
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
6344
 
                                    _("Field name '%s' too long"),
6345
 
                                    VIR_DOMAIN_BLKIO_DEVICE_WEIGHT);
6346
 
                    goto cleanup;
6347
 
                }
6348
 
                break;
6349
 
 
6350
 
            default:
6351
 
                break;
6352
 
                /* should not hit here */
6353
 
            }
6354
 
        }
6355
 
    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6356
 
        for (i = 0; i < *nparams && i < QEMU_NB_BLKIO_PARAM; i++) {
6357
 
            virTypedParameterPtr param = &params[i];
6358
 
            val = 0;
6359
 
            param->value.ui = 0;
6360
 
            param->type = VIR_TYPED_PARAM_UINT;
6361
 
 
6362
 
            switch (i) {
6363
 
            case 0: /* fill blkio weight here */
6364
 
                if (virStrcpyStatic(param->field, VIR_DOMAIN_BLKIO_WEIGHT) == NULL) {
6365
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
6366
 
                                    _("Field name '%s' too long"),
6367
 
                                    VIR_DOMAIN_BLKIO_WEIGHT);
6368
 
                    goto cleanup;
6369
 
                }
6370
 
                param->value.ui = persistentDef->blkio.weight;
6371
 
                break;
6372
 
 
6373
 
            case 1: /* blkiotune.device_weight */
6374
 
                if (persistentDef->blkio.ndevices > 0) {
6375
 
                    virBuffer buf = VIR_BUFFER_INITIALIZER;
6376
 
                    bool comma = false;
6377
 
 
6378
 
                    for (j = 0; j < persistentDef->blkio.ndevices; j++) {
6379
 
                        if (!persistentDef->blkio.devices[j].weight)
6380
 
                            continue;
6381
 
                        if (comma)
6382
 
                            virBufferAddChar(&buf, ',');
6383
 
                        else
6384
 
                            comma = true;
6385
 
                        virBufferAsprintf(&buf, "%s,%u",
6386
 
                                          persistentDef->blkio.devices[j].path,
6387
 
                                          persistentDef->blkio.devices[j].weight);
6388
 
                    }
6389
 
                    if (virBufferError(&buf)) {
6390
 
                        virReportOOMError();
6391
 
                        goto cleanup;
6392
 
                    }
6393
 
                    param->value.s = virBufferContentAndReset(&buf);
6394
 
                }
6395
 
                if (!param->value.s) {
6396
 
                    param->value.s = strdup("");
6397
 
                    if (!param->value.s) {
6398
 
                        virReportOOMError();
6399
 
                        goto cleanup;
6400
 
                    }
6401
 
                }
6402
 
                param->type = VIR_TYPED_PARAM_STRING;
6403
 
                if (virStrcpyStatic(param->field,
6404
 
                                    VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) == NULL) {
6405
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
6406
 
                                    _("Field name '%s' too long"),
6407
 
                                    VIR_DOMAIN_BLKIO_DEVICE_WEIGHT);
6408
 
                    goto cleanup;
6409
 
                }
6410
 
                break;
6411
 
 
6412
 
            default:
6413
 
                break;
6414
 
                /* should not hit here */
6415
 
            }
6416
 
        }
6417
 
    }
6418
 
 
6419
 
    if (QEMU_NB_BLKIO_PARAM < *nparams)
6420
 
        *nparams = QEMU_NB_BLKIO_PARAM;
6421
 
    ret = 0;
6422
 
 
6423
 
cleanup:
6424
 
    if (group)
6425
 
        virCgroupFree(&group);
6426
 
    if (vm)
6427
 
        virDomainObjUnlock(vm);
6428
 
    qemuDriverUnlock(driver);
6429
 
    return ret;
6430
 
}
6431
 
 
6432
 
static int qemuDomainSetMemoryParameters(virDomainPtr dom,
6433
 
                                         virTypedParameterPtr params,
6434
 
                                         int nparams,
6435
 
                                         unsigned int flags)
6436
 
{
6437
 
    struct qemud_driver *driver = dom->conn->privateData;
6438
 
    int i;
6439
 
    virDomainDefPtr persistentDef = NULL;
6440
 
    virCgroupPtr group = NULL;
6441
 
    virDomainObjPtr vm = NULL;
6442
 
    int ret = -1;
6443
 
    bool isActive;
6444
 
 
6445
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6446
 
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
6447
 
 
6448
 
    qemuDriverLock(driver);
6449
 
 
6450
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6451
 
 
6452
 
    if (vm == NULL) {
6453
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
6454
 
                        _("No such domain %s"), dom->uuid);
6455
 
        goto cleanup;
6456
 
    }
6457
 
 
6458
 
    isActive = virDomainObjIsActive(vm);
6459
 
 
6460
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
6461
 
        if (isActive)
6462
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
6463
 
        else
6464
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
6465
 
    }
6466
 
 
6467
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6468
 
        if (!isActive) {
6469
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6470
 
                            "%s", _("domain is not running"));
6471
 
            goto cleanup;
6472
 
        }
6473
 
 
6474
 
        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) {
6475
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6476
 
                            "%s", _("cgroup memory controller is not mounted"));
6477
 
            goto cleanup;
6478
 
        }
6479
 
 
6480
 
        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
6481
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6482
 
                            _("cannot find cgroup for domain %s"), vm->def->name);
6483
 
            goto cleanup;
6484
 
        }
6485
 
    }
6486
 
 
6487
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6488
 
        if (!vm->persistent) {
6489
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
6490
 
                            _("cannot change persistent config of a transient domain"));
6491
 
            goto cleanup;
6492
 
        }
6493
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
6494
 
            goto cleanup;
6495
 
    }
6496
 
 
6497
 
    ret = 0;
6498
 
    for (i = 0; i < nparams; i++) {
6499
 
        virTypedParameterPtr param = &params[i];
6500
 
 
6501
 
        if (STREQ(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
6502
 
            int rc;
6503
 
            if (param->type != VIR_TYPED_PARAM_ULLONG) {
6504
 
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6505
 
                                _("invalid type for memory hard_limit tunable, expected a 'ullong'"));
6506
 
                ret = -1;
6507
 
                continue;
6508
 
            }
6509
 
 
6510
 
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6511
 
                rc = virCgroupSetMemoryHardLimit(group, params[i].value.ul);
6512
 
                if (rc != 0) {
6513
 
                    virReportSystemError(-rc, "%s",
6514
 
                                         _("unable to set memory hard_limit tunable"));
6515
 
                    ret = -1;
6516
 
                }
6517
 
            }
6518
 
 
6519
 
            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6520
 
                persistentDef->mem.hard_limit = params[i].value.ul;
6521
 
            }
6522
 
        } else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) {
6523
 
            int rc;
6524
 
            if (param->type != VIR_TYPED_PARAM_ULLONG) {
6525
 
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6526
 
                                _("invalid type for memory soft_limit tunable, expected a 'ullong'"));
6527
 
                ret = -1;
6528
 
                continue;
6529
 
            }
6530
 
 
6531
 
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6532
 
                rc = virCgroupSetMemorySoftLimit(group, params[i].value.ul);
6533
 
                if (rc != 0) {
6534
 
                    virReportSystemError(-rc, "%s",
6535
 
                                         _("unable to set memory soft_limit tunable"));
6536
 
                    ret = -1;
6537
 
                }
6538
 
            }
6539
 
 
6540
 
            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6541
 
                persistentDef->mem.soft_limit = params[i].value.ul;
6542
 
            }
6543
 
        } else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT)) {
6544
 
            int rc;
6545
 
            if (param->type != VIR_TYPED_PARAM_ULLONG) {
6546
 
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6547
 
                                _("invalid type for swap_hard_limit tunable, expected a 'ullong'"));
6548
 
                ret = -1;
6549
 
                continue;
6550
 
            }
6551
 
 
6552
 
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6553
 
                rc = virCgroupSetMemSwapHardLimit(group, params[i].value.ul);
6554
 
                if (rc != 0) {
6555
 
                    virReportSystemError(-rc, "%s",
6556
 
                                         _("unable to set swap_hard_limit tunable"));
6557
 
                    ret = -1;
6558
 
                }
6559
 
            }
6560
 
            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6561
 
                persistentDef->mem.swap_hard_limit = params[i].value.ul;
6562
 
            }
6563
 
        } else if (STREQ(param->field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) {
6564
 
            qemuReportError(VIR_ERR_INVALID_ARG,
6565
 
                            _("Memory tunable `%s' not implemented"),
6566
 
                            param->field);
6567
 
            ret = -1;
6568
 
        } else {
6569
 
            qemuReportError(VIR_ERR_INVALID_ARG,
6570
 
                            _("Parameter `%s' not supported"), param->field);
6571
 
            ret = -1;
6572
 
        }
6573
 
    }
6574
 
 
6575
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6576
 
        if (virDomainSaveConfig(driver->configDir, persistentDef) < 0)
6577
 
            ret = -1;
6578
 
    }
6579
 
 
6580
 
cleanup:
6581
 
    virCgroupFree(&group);
6582
 
    if (vm)
6583
 
        virDomainObjUnlock(vm);
6584
 
    qemuDriverUnlock(driver);
6585
 
    return ret;
6586
 
}
6587
 
 
6588
 
static int qemuDomainGetMemoryParameters(virDomainPtr dom,
6589
 
                                         virTypedParameterPtr params,
6590
 
                                         int *nparams,
6591
 
                                         unsigned int flags)
6592
 
{
6593
 
    struct qemud_driver *driver = dom->conn->privateData;
6594
 
    int i;
6595
 
    virCgroupPtr group = NULL;
6596
 
    virDomainObjPtr vm = NULL;
6597
 
    virDomainDefPtr persistentDef = NULL;
6598
 
    unsigned long long val;
6599
 
    int ret = -1;
6600
 
    int rc;
6601
 
    bool isActive;
6602
 
 
6603
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6604
 
                  VIR_DOMAIN_AFFECT_CONFIG |
6605
 
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
6606
 
 
6607
 
    qemuDriverLock(driver);
6608
 
 
6609
 
    /* We don't return strings, and thus trivially support this flag.  */
6610
 
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
6611
 
 
6612
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6613
 
 
6614
 
    if (vm == NULL) {
6615
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
6616
 
                        _("No such domain %s"), dom->uuid);
6617
 
        goto cleanup;
6618
 
    }
6619
 
 
6620
 
    isActive = virDomainObjIsActive(vm);
6621
 
 
6622
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
6623
 
        if (isActive)
6624
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
6625
 
        else
6626
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
6627
 
    }
6628
 
 
6629
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6630
 
        if (!isActive) {
6631
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6632
 
                            "%s", _("domain is not running"));
6633
 
            goto cleanup;
6634
 
        }
6635
 
 
6636
 
        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) {
6637
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6638
 
                            "%s", _("cgroup memory controller is not mounted"));
6639
 
            goto cleanup;
6640
 
        }
6641
 
 
6642
 
        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
6643
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6644
 
                            _("cannot find cgroup for domain %s"), vm->def->name);
6645
 
            goto cleanup;
6646
 
        }
6647
 
    }
6648
 
 
6649
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6650
 
        if (!vm->persistent) {
6651
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
6652
 
                            _("cannot change persistent config of a transient domain"));
6653
 
            goto cleanup;
6654
 
        }
6655
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
6656
 
            goto cleanup;
6657
 
    }
6658
 
 
6659
 
    if ((*nparams) == 0) {
6660
 
        /* Current number of memory parameters supported by cgroups */
6661
 
        *nparams = QEMU_NB_MEM_PARAM;
6662
 
        ret = 0;
6663
 
        goto cleanup;
6664
 
    }
6665
 
 
6666
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6667
 
        for (i = 0; i < *nparams && i < QEMU_NB_MEM_PARAM; i++) {
6668
 
            virMemoryParameterPtr param = &params[i];
6669
 
            val = 0;
6670
 
            param->value.ul = 0;
6671
 
            param->type = VIR_TYPED_PARAM_ULLONG;
6672
 
 
6673
 
            switch (i) {
6674
 
            case 0: /* fill memory hard limit here */
6675
 
                if (virStrcpyStatic(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT) == NULL) {
6676
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
6677
 
                                    _("Field name '%s' too long"),
6678
 
                                    VIR_DOMAIN_MEMORY_HARD_LIMIT);
6679
 
                    goto cleanup;
6680
 
                }
6681
 
                param->value.ul = persistentDef->mem.hard_limit;
6682
 
                break;
6683
 
 
6684
 
            case 1: /* fill memory soft limit here */
6685
 
                if (virStrcpyStatic(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT) == NULL) {
6686
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
6687
 
                                    _("Field name '%s' too long"),
6688
 
                                    VIR_DOMAIN_MEMORY_SOFT_LIMIT);
6689
 
                    goto cleanup;
6690
 
                }
6691
 
                param->value.ul = persistentDef->mem.soft_limit;
6692
 
                break;
6693
 
 
6694
 
            case 2: /* fill swap hard limit here */
6695
 
                if (virStrcpyStatic(param->field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT) == NULL) {
6696
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
6697
 
                                    _("Field name '%s' too long"),
6698
 
                                    VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT);
6699
 
                    goto cleanup;
6700
 
                }
6701
 
                param->value.ul = persistentDef->mem.swap_hard_limit;
6702
 
                break;
6703
 
 
6704
 
            default:
6705
 
                break;
6706
 
                /* should not hit here */
6707
 
            }
6708
 
        }
6709
 
        goto out;
6710
 
    }
6711
 
 
6712
 
    for (i = 0; i < *nparams && i < QEMU_NB_MEM_PARAM; i++) {
6713
 
        virTypedParameterPtr param = &params[i];
6714
 
        val = 0;
6715
 
        param->value.ul = 0;
6716
 
        param->type = VIR_TYPED_PARAM_ULLONG;
6717
 
 
6718
 
        /* Coverity does not realize that if we get here, group is set.  */
6719
 
        sa_assert(group);
6720
 
 
6721
 
        switch (i) {
6722
 
        case 0: /* fill memory hard limit here */
6723
 
            rc = virCgroupGetMemoryHardLimit(group, &val);
6724
 
            if (rc != 0) {
6725
 
                virReportSystemError(-rc, "%s",
6726
 
                                     _("unable to get memory hard limit"));
6727
 
                goto cleanup;
6728
 
            }
6729
 
            if (virStrcpyStatic(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT) == NULL) {
6730
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
6731
 
                                _("Field name '%s' too long"),
6732
 
                                VIR_DOMAIN_MEMORY_HARD_LIMIT);
6733
 
                goto cleanup;
6734
 
            }
6735
 
            param->value.ul = val;
6736
 
            break;
6737
 
 
6738
 
        case 1: /* fill memory soft limit here */
6739
 
            rc = virCgroupGetMemorySoftLimit(group, &val);
6740
 
            if (rc != 0) {
6741
 
                virReportSystemError(-rc, "%s",
6742
 
                                     _("unable to get memory soft limit"));
6743
 
                goto cleanup;
6744
 
            }
6745
 
            if (virStrcpyStatic(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT) == NULL) {
6746
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
6747
 
                                _("Field name '%s' too long"),
6748
 
                                VIR_DOMAIN_MEMORY_SOFT_LIMIT);
6749
 
                goto cleanup;
6750
 
            }
6751
 
            param->value.ul = val;
6752
 
            break;
6753
 
 
6754
 
        case 2: /* fill swap hard limit here */
6755
 
            rc = virCgroupGetMemSwapHardLimit(group, &val);
6756
 
            if (rc != 0) {
6757
 
                virReportSystemError(-rc, "%s",
6758
 
                                     _("unable to get swap hard limit"));
6759
 
                goto cleanup;
6760
 
            }
6761
 
            if (virStrcpyStatic(param->field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT) == NULL) {
6762
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
6763
 
                                _("Field name '%s' too long"),
6764
 
                                VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT);
6765
 
                goto cleanup;
6766
 
            }
6767
 
            param->value.ul = val;
6768
 
            break;
6769
 
 
6770
 
        default:
6771
 
            break;
6772
 
            /* should not hit here */
6773
 
        }
6774
 
    }
6775
 
 
6776
 
out:
6777
 
    if (QEMU_NB_MEM_PARAM < *nparams)
6778
 
        *nparams = QEMU_NB_MEM_PARAM;
6779
 
    ret = 0;
6780
 
 
6781
 
cleanup:
6782
 
    if (group)
6783
 
        virCgroupFree(&group);
6784
 
    if (vm)
6785
 
        virDomainObjUnlock(vm);
6786
 
    qemuDriverUnlock(driver);
6787
 
    return ret;
6788
 
}
6789
 
 
6790
 
static int
6791
 
qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
6792
 
                   unsigned long long period, long long quota)
6793
 
{
6794
 
    int i;
6795
 
    qemuDomainObjPrivatePtr priv = vm->privateData;
6796
 
    virCgroupPtr cgroup_vcpu = NULL;
6797
 
    int rc;
6798
 
    long long vm_quota = 0;
6799
 
    long long old_quota = 0;
6800
 
    unsigned long long old_period = 0;
6801
 
 
6802
 
    if (period == 0 && quota == 0)
6803
 
        return 0;
6804
 
 
6805
 
    /* Ensure that we can multiply by vcpus without overflowing. */
6806
 
    if (quota > LLONG_MAX / vm->def->vcpus) {
6807
 
        virReportSystemError(EINVAL,
6808
 
                             _("%s"),
6809
 
                             "Unable to set cpu bandwidth quota");
6810
 
        goto cleanup;
6811
 
    }
6812
 
 
6813
 
    if (quota > 0)
6814
 
        vm_quota = quota * vm->def->vcpus;
6815
 
    else
6816
 
        vm_quota = quota;
6817
 
 
6818
 
    rc = virCgroupGetCpuCfsQuota(cgroup, &old_quota);
6819
 
    if (rc < 0) {
6820
 
        virReportSystemError(-rc, "%s",
6821
 
                             _("unable to get cpu bandwidth tunable"));
6822
 
        goto cleanup;
6823
 
    }
6824
 
 
6825
 
    rc = virCgroupGetCpuCfsPeriod(cgroup, &old_period);
6826
 
    if (rc < 0) {
6827
 
        virReportSystemError(-rc, "%s",
6828
 
                             _("unable to get cpu bandwidth period tunable"));
6829
 
        goto cleanup;
6830
 
    }
6831
 
 
6832
 
    /*
6833
 
     * If quota will be changed to a small value, we should modify vcpu's quota
6834
 
     * first. Otherwise, we should modify vm's quota first.
6835
 
     *
6836
 
     * If period will be changed to a small value, we should modify vm's period
6837
 
     * first. Otherwise, we should modify vcpu's period first.
6838
 
     *
6839
 
     * If both quota and period will be changed to a big/small value, we cannot
6840
 
     * modify period and quota together.
6841
 
     */
6842
 
    if ((quota != 0) && (period != 0)) {
6843
 
        if (((quota > old_quota) && (period > old_period)) ||
6844
 
            ((quota < old_quota) && (period < old_period))) {
6845
 
            /* modify period */
6846
 
            if (qemuSetVcpusBWLive(vm, cgroup, period, 0) < 0)
6847
 
                goto cleanup;
6848
 
 
6849
 
            /* modify quota */
6850
 
            if (qemuSetVcpusBWLive(vm, cgroup, 0, quota) < 0)
6851
 
                goto cleanup;
6852
 
            return 0;
6853
 
        }
6854
 
    }
6855
 
 
6856
 
    if (((vm_quota != 0) && (vm_quota > old_quota)) ||
6857
 
        ((period != 0) && (period < old_period)))
6858
 
        /* Set cpu bandwidth for the vm */
6859
 
        if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
6860
 
            goto cleanup;
6861
 
 
6862
 
    /* If we does not know VCPU<->PID mapping or all vcpu runs in the same
6863
 
     * thread, we cannot control each vcpu. So we only modify cpu bandwidth
6864
 
     * when each vcpu has a separated thread.
6865
 
     */
6866
 
    if (priv->nvcpupids != 0 && priv->vcpupids[0] != vm->pid) {
6867
 
        for (i = 0; i < priv->nvcpupids; i++) {
6868
 
            rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 0);
6869
 
            if (rc < 0) {
6870
 
                virReportSystemError(-rc,
6871
 
                                     _("Unable to find vcpu cgroup for %s(vcpu:"
6872
 
                                       " %d)"),
6873
 
                                     vm->def->name, i);
6874
 
                goto cleanup;
6875
 
            }
6876
 
 
6877
 
            if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
6878
 
                goto cleanup;
6879
 
 
6880
 
            virCgroupFree(&cgroup_vcpu);
6881
 
        }
6882
 
    }
6883
 
 
6884
 
    if (((vm_quota != 0) && (vm_quota <= old_quota)) ||
6885
 
        ((period != 0) && (period >= old_period)))
6886
 
        /* Set cpu bandwidth for the vm */
6887
 
        if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
6888
 
            goto cleanup;
6889
 
 
6890
 
    return 0;
6891
 
 
6892
 
cleanup:
6893
 
    virCgroupFree(&cgroup_vcpu);
6894
 
    return -1;
6895
 
}
6896
 
 
6897
 
static int qemuSetSchedulerParametersFlags(virDomainPtr dom,
6898
 
                                           virTypedParameterPtr params,
6899
 
                                           int nparams,
6900
 
                                           unsigned int flags)
6901
 
{
6902
 
    struct qemud_driver *driver = dom->conn->privateData;
6903
 
    int i;
6904
 
    virCgroupPtr group = NULL;
6905
 
    virDomainObjPtr vm = NULL;
6906
 
    virDomainDefPtr vmdef = NULL;
6907
 
    int ret = -1;
6908
 
    bool isActive;
6909
 
    int rc;
6910
 
 
6911
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6912
 
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
6913
 
 
6914
 
    qemuDriverLock(driver);
6915
 
 
6916
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
6917
 
 
6918
 
    if (vm == NULL) {
6919
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
6920
 
                        _("No such domain %s"), dom->uuid);
6921
 
        goto cleanup;
6922
 
    }
6923
 
 
6924
 
    isActive = virDomainObjIsActive(vm);
6925
 
 
6926
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
6927
 
        if (isActive)
6928
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
6929
 
        else
6930
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
6931
 
    }
6932
 
 
6933
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6934
 
        if (!vm->persistent) {
6935
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
6936
 
                            _("cannot change persistent config of a transient domain"));
6937
 
            goto cleanup;
6938
 
        }
6939
 
 
6940
 
        /* Make a copy for updated domain. */
6941
 
        vmdef = virDomainObjCopyPersistentDef(driver->caps, vm);
6942
 
        if (!vmdef)
6943
 
            goto cleanup;
6944
 
    }
6945
 
 
6946
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6947
 
        if (!isActive) {
6948
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6949
 
                            "%s", _("domain is not running"));
6950
 
            goto cleanup;
6951
 
        }
6952
 
 
6953
 
        if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
6954
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
6955
 
                            "%s", _("cgroup CPU controller is not mounted"));
6956
 
            goto cleanup;
6957
 
        }
6958
 
        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
6959
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
6960
 
                            _("cannot find cgroup for domain %s"),
6961
 
                            vm->def->name);
6962
 
            goto cleanup;
6963
 
        }
6964
 
    }
6965
 
 
6966
 
    for (i = 0; i < nparams; i++) {
6967
 
        virTypedParameterPtr param = &params[i];
6968
 
 
6969
 
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
6970
 
            if (param->type != VIR_TYPED_PARAM_ULLONG) {
6971
 
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6972
 
                                _("invalid type for cpu_shares tunable, expected a 'ullong'"));
6973
 
                goto cleanup;
6974
 
            }
6975
 
 
6976
 
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6977
 
                rc = virCgroupSetCpuShares(group, params[i].value.ul);
6978
 
                if (rc != 0) {
6979
 
                    virReportSystemError(-rc, "%s",
6980
 
                                         _("unable to set cpu shares tunable"));
6981
 
                    goto cleanup;
6982
 
                }
6983
 
 
6984
 
                vm->def->cputune.shares = params[i].value.ul;
6985
 
            }
6986
 
 
6987
 
            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
6988
 
                vmdef->cputune.shares = params[i].value.ul;
6989
 
            }
6990
 
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
6991
 
            if (param->type != VIR_TYPED_PARAM_ULLONG) {
6992
 
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
6993
 
                                _("invalid type for vcpu_period tunable,"
6994
 
                                  " expected a 'ullong'"));
6995
 
                goto cleanup;
6996
 
            }
6997
 
 
6998
 
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
6999
 
                rc = qemuSetVcpusBWLive(vm, group, params[i].value.ul, 0);
7000
 
                if (rc != 0)
7001
 
                    goto cleanup;
7002
 
 
7003
 
                if (params[i].value.ul)
7004
 
                    vm->def->cputune.period = params[i].value.ul;
7005
 
            }
7006
 
 
7007
 
            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7008
 
                vmdef->cputune.period = params[i].value.ul;
7009
 
            }
7010
 
        } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
7011
 
            if (param->type != VIR_TYPED_PARAM_LLONG) {
7012
 
                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
7013
 
                                _("invalid type for vcpu_quota tunable,"
7014
 
                                  " expected a 'llong'"));
7015
 
                goto cleanup;
7016
 
            }
7017
 
 
7018
 
            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
7019
 
                rc = qemuSetVcpusBWLive(vm, group, 0, params[i].value.l);
7020
 
                if (rc != 0)
7021
 
                    goto cleanup;
7022
 
 
7023
 
                if (params[i].value.l)
7024
 
                    vm->def->cputune.quota = params[i].value.l;
7025
 
            }
7026
 
 
7027
 
            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7028
 
                vmdef->cputune.quota = params[i].value.l;
7029
 
            }
7030
 
        } else {
7031
 
            qemuReportError(VIR_ERR_INVALID_ARG,
7032
 
                            _("Invalid parameter `%s'"), param->field);
7033
 
            goto cleanup;
7034
 
        }
7035
 
    }
7036
 
 
7037
 
    if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
7038
 
        goto cleanup;
7039
 
 
7040
 
 
7041
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7042
 
        rc = virDomainSaveConfig(driver->configDir, vmdef);
7043
 
        if (rc < 0)
7044
 
            goto cleanup;
7045
 
 
7046
 
        virDomainObjAssignDef(vm, vmdef, false);
7047
 
        vmdef = NULL;
7048
 
    }
7049
 
 
7050
 
    ret = 0;
7051
 
 
7052
 
cleanup:
7053
 
    virDomainDefFree(vmdef);
7054
 
    virCgroupFree(&group);
7055
 
    if (vm)
7056
 
        virDomainObjUnlock(vm);
7057
 
    qemuDriverUnlock(driver);
7058
 
    return ret;
7059
 
}
7060
 
 
7061
 
static int qemuSetSchedulerParameters(virDomainPtr dom,
7062
 
                                      virTypedParameterPtr params,
7063
 
                                      int nparams)
7064
 
{
7065
 
    return qemuSetSchedulerParametersFlags(dom,
7066
 
                                           params,
7067
 
                                           nparams,
7068
 
                                           VIR_DOMAIN_AFFECT_LIVE);
7069
 
}
7070
 
 
7071
 
static int
7072
 
qemuGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
7073
 
                  long long *quota)
7074
 
{
7075
 
    int rc;
7076
 
 
7077
 
    rc = virCgroupGetCpuCfsPeriod(cgroup, period);
7078
 
    if (rc < 0) {
7079
 
        virReportSystemError(-rc, "%s",
7080
 
                             _("unable to get cpu bandwidth period tunable"));
7081
 
        return -1;
7082
 
    }
7083
 
 
7084
 
    rc = virCgroupGetCpuCfsQuota(cgroup, quota);
7085
 
    if (rc < 0) {
7086
 
        virReportSystemError(-rc, "%s",
7087
 
                             _("unable to get cpu bandwidth tunable"));
7088
 
        return -1;
7089
 
    }
7090
 
 
7091
 
    return 0;
7092
 
}
7093
 
 
7094
 
static int
7095
 
qemuGetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
7096
 
                   unsigned long long *period, long long *quota)
7097
 
{
7098
 
    virCgroupPtr cgroup_vcpu = NULL;
7099
 
    qemuDomainObjPrivatePtr priv = NULL;
7100
 
    int rc;
7101
 
    int ret = -1;
7102
 
 
7103
 
    priv = vm->privateData;
7104
 
    if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
7105
 
        /* We do not create sub dir for each vcpu */
7106
 
        rc = qemuGetVcpuBWLive(cgroup, period, quota);
7107
 
        if (rc < 0)
7108
 
            goto cleanup;
7109
 
 
7110
 
        if (*quota > 0)
7111
 
            *quota /= vm->def->vcpus;
7112
 
        goto out;
7113
 
    }
7114
 
 
7115
 
    /* get period and quota for vcpu0 */
7116
 
    rc = virCgroupForVcpu(cgroup, 0, &cgroup_vcpu, 0);
7117
 
    if (!cgroup_vcpu) {
7118
 
        virReportSystemError(-rc,
7119
 
                             _("Unable to find vcpu cgroup for %s(vcpu: 0)"),
7120
 
                             vm->def->name);
7121
 
        goto cleanup;
7122
 
    }
7123
 
 
7124
 
    rc = qemuGetVcpuBWLive(cgroup_vcpu, period, quota);
7125
 
    if (rc < 0)
7126
 
        goto cleanup;
7127
 
 
7128
 
out:
7129
 
    ret = 0;
7130
 
 
7131
 
cleanup:
7132
 
    virCgroupFree(&cgroup_vcpu);
7133
 
    return ret;
7134
 
}
7135
 
 
7136
 
static int
7137
 
qemuGetSchedulerParametersFlags(virDomainPtr dom,
7138
 
                                virTypedParameterPtr params,
7139
 
                                int *nparams,
7140
 
                                unsigned int flags)
7141
 
{
7142
 
    struct qemud_driver *driver = dom->conn->privateData;
7143
 
    virCgroupPtr group = NULL;
7144
 
    virDomainObjPtr vm = NULL;
7145
 
    unsigned long long shares;
7146
 
    unsigned long long period;
7147
 
    long long quota;
7148
 
    int ret = -1;
7149
 
    int rc;
7150
 
    bool isActive;
7151
 
    bool cpu_bw_status = false;
7152
 
    int saved_nparams = 0;
7153
 
 
7154
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
7155
 
                  VIR_DOMAIN_AFFECT_CONFIG |
7156
 
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
7157
 
 
7158
 
    qemuDriverLock(driver);
7159
 
 
7160
 
    /* We don't return strings, and thus trivially support this flag.  */
7161
 
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
7162
 
 
7163
 
    if (*nparams > 1) {
7164
 
        rc = qemuGetCpuBWStatus(driver->cgroup);
7165
 
        if (rc < 0)
7166
 
            goto cleanup;
7167
 
        cpu_bw_status = !!rc;
7168
 
    }
7169
 
 
7170
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7171
 
 
7172
 
    if (vm == NULL) {
7173
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
7174
 
                        _("No such domain %s"), dom->uuid);
7175
 
        goto cleanup;
7176
 
    }
7177
 
 
7178
 
    isActive = virDomainObjIsActive(vm);
7179
 
 
7180
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
7181
 
        if (isActive)
7182
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
7183
 
        else
7184
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
7185
 
    }
7186
 
 
7187
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
7188
 
        if (!vm->persistent) {
7189
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
7190
 
                            _("cannot query persistent config of a transient domain"));
7191
 
            goto cleanup;
7192
 
        }
7193
 
 
7194
 
        if (isActive) {
7195
 
            virDomainDefPtr persistentDef;
7196
 
 
7197
 
            persistentDef = virDomainObjGetPersistentDef(driver->caps, vm);
7198
 
            if (!persistentDef) {
7199
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7200
 
                                _("can't get persistentDef"));
7201
 
                goto cleanup;
7202
 
            }
7203
 
            shares = persistentDef->cputune.shares;
7204
 
            if (*nparams > 1 && cpu_bw_status) {
7205
 
                period = persistentDef->cputune.period;
7206
 
                quota = persistentDef->cputune.quota;
7207
 
            }
7208
 
        } else {
7209
 
            shares = vm->def->cputune.shares;
7210
 
            if (*nparams > 1 && cpu_bw_status) {
7211
 
                period = vm->def->cputune.period;
7212
 
                quota = vm->def->cputune.quota;
7213
 
            }
7214
 
        }
7215
 
        goto out;
7216
 
    }
7217
 
 
7218
 
    if (!isActive) {
7219
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
7220
 
                        _("domain is not running"));
7221
 
        goto cleanup;
7222
 
    }
7223
 
 
7224
 
    if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
7225
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7226
 
                        "%s", _("cgroup CPU controller is not mounted"));
7227
 
        goto cleanup;
7228
 
    }
7229
 
 
7230
 
    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
7231
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
7232
 
                        _("cannot find cgroup for domain %s"), vm->def->name);
7233
 
        goto cleanup;
7234
 
    }
7235
 
 
7236
 
    rc = virCgroupGetCpuShares(group, &shares);
7237
 
    if (rc != 0) {
7238
 
        virReportSystemError(-rc, "%s",
7239
 
                             _("unable to get cpu shares tunable"));
7240
 
        goto cleanup;
7241
 
    }
7242
 
 
7243
 
    if (*nparams > 1 && cpu_bw_status) {
7244
 
        rc = qemuGetVcpusBWLive(vm, group, &period, &quota);
7245
 
        if (rc != 0)
7246
 
            goto cleanup;
7247
 
    }
7248
 
out:
7249
 
    params[0].value.ul = shares;
7250
 
    params[0].type = VIR_TYPED_PARAM_ULLONG;
7251
 
    if (virStrcpyStatic(params[0].field,
7252
 
                        VIR_DOMAIN_SCHEDULER_CPU_SHARES) == NULL) {
7253
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
7254
 
                        _("Field name '%s' too long"),
7255
 
                        VIR_DOMAIN_SCHEDULER_CPU_SHARES);
7256
 
        goto cleanup;
7257
 
    }
7258
 
 
7259
 
    saved_nparams++;
7260
 
 
7261
 
    if (cpu_bw_status) {
7262
 
        if (*nparams > saved_nparams) {
7263
 
            params[1].value.ul = period;
7264
 
            params[1].type = VIR_TYPED_PARAM_ULLONG;
7265
 
            if (virStrcpyStatic(params[1].field,
7266
 
                                VIR_DOMAIN_SCHEDULER_VCPU_PERIOD) == NULL) {
7267
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
7268
 
                                _("Field name '%s' too long"),
7269
 
                                VIR_DOMAIN_SCHEDULER_VCPU_PERIOD);
7270
 
                goto cleanup;
7271
 
            }
7272
 
            saved_nparams++;
7273
 
        }
7274
 
 
7275
 
        if (*nparams > saved_nparams) {
7276
 
            params[2].value.ul = quota;
7277
 
            params[2].type = VIR_TYPED_PARAM_LLONG;
7278
 
            if (virStrcpyStatic(params[2].field,
7279
 
                                VIR_DOMAIN_SCHEDULER_VCPU_QUOTA) == NULL) {
7280
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
7281
 
                                _("Field name '%s' too long"),
7282
 
                                VIR_DOMAIN_SCHEDULER_VCPU_QUOTA);
7283
 
                goto cleanup;
7284
 
            }
7285
 
            saved_nparams++;
7286
 
        }
7287
 
    }
7288
 
 
7289
 
    *nparams = saved_nparams;
7290
 
 
7291
 
    ret = 0;
7292
 
 
7293
 
cleanup:
7294
 
    virCgroupFree(&group);
7295
 
    if (vm)
7296
 
        virDomainObjUnlock(vm);
7297
 
    qemuDriverUnlock(driver);
7298
 
    return ret;
7299
 
}
7300
 
 
7301
 
static int
7302
 
qemuGetSchedulerParameters(virDomainPtr dom,
7303
 
                           virTypedParameterPtr params,
7304
 
                           int *nparams)
7305
 
{
7306
 
    return qemuGetSchedulerParametersFlags(dom, params, nparams,
7307
 
                                           VIR_DOMAIN_AFFECT_CURRENT);
7308
 
}
7309
 
 
7310
 
/**
7311
 
 * Resize a block device while a guest is running. Resize to a lower size
7312
 
 * is supported, but should be used with extreme caution.  Note that it
7313
 
 * only supports to resize image files, it can't resize block devices
7314
 
 * like LVM volumes.
7315
 
 */
7316
 
static int
7317
 
qemuDomainBlockResize (virDomainPtr dom,
7318
 
                       const char *path,
7319
 
                       unsigned long long size,
7320
 
                       unsigned int flags)
7321
 
{
7322
 
    struct qemud_driver *driver = dom->conn->privateData;
7323
 
    virDomainObjPtr vm;
7324
 
    qemuDomainObjPrivatePtr priv;
7325
 
    int ret = -1, i;
7326
 
    char *device = NULL;
7327
 
    virDomainDiskDefPtr disk = NULL;
7328
 
 
7329
 
    virCheckFlags(0, -1);
7330
 
 
7331
 
    if (path[0] == '\0') {
7332
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7333
 
                        "%s", _("empty path"));
7334
 
        return -1;
7335
 
    }
7336
 
 
7337
 
    if (size > ULLONG_MAX / 1024) {
7338
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7339
 
                        _("size must be less than %llu"),
7340
 
                        ULLONG_MAX / 1024);
7341
 
        return -1;
7342
 
    }
7343
 
 
7344
 
    qemuDriverLock(driver);
7345
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7346
 
    qemuDriverUnlock(driver);
7347
 
 
7348
 
    if (!vm) {
7349
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7350
 
        virUUIDFormat(dom->uuid, uuidstr);
7351
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7352
 
                        _("no domain matching uuid '%s'"), uuidstr);
7353
 
        goto cleanup;
7354
 
    }
7355
 
 
7356
 
    priv = vm->privateData;
7357
 
 
7358
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
7359
 
        goto cleanup;
7360
 
 
7361
 
    if (!virDomainObjIsActive(vm)) {
7362
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7363
 
                        "%s", _("domain is not running"));
7364
 
        goto endjob;
7365
 
    }
7366
 
 
7367
 
    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
7368
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7369
 
                        _("invalid path: %s"), path);
7370
 
        goto cleanup;
7371
 
    }
7372
 
    disk = vm->def->disks[i];
7373
 
 
7374
 
    if (virAsprintf(&device, "%s%s", QEMU_DRIVE_HOST_PREFIX,
7375
 
                    disk->info.alias) < 0) {
7376
 
        virReportOOMError();
7377
 
        goto endjob;
7378
 
    }
7379
 
 
7380
 
    qemuDomainObjEnterMonitor(driver, vm);
7381
 
    if (qemuMonitorBlockResize(priv->mon, device, size) < 0) {
7382
 
        qemuDomainObjExitMonitor(driver, vm);
7383
 
        goto endjob;
7384
 
    }
7385
 
    qemuDomainObjExitMonitor(driver, vm);
7386
 
 
7387
 
    ret = 0;
7388
 
 
7389
 
endjob:
7390
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
7391
 
        vm = NULL;
7392
 
 
7393
 
cleanup:
7394
 
    VIR_FREE(device);
7395
 
    if (vm)
7396
 
        virDomainObjUnlock(vm);
7397
 
    return ret;
7398
 
}
7399
 
 
7400
 
/* This uses the 'info blockstats' monitor command which was
7401
 
 * integrated into both qemu & kvm in late 2007.  If the command is
7402
 
 * not supported we detect this and return the appropriate error.
7403
 
 */
7404
 
static int
7405
 
qemuDomainBlockStats(virDomainPtr dom,
7406
 
                     const char *path,
7407
 
                     struct _virDomainBlockStats *stats)
7408
 
{
7409
 
    struct qemud_driver *driver = dom->conn->privateData;
7410
 
    int i, ret = -1;
7411
 
    virDomainObjPtr vm;
7412
 
    virDomainDiskDefPtr disk = NULL;
7413
 
    qemuDomainObjPrivatePtr priv;
7414
 
 
7415
 
    qemuDriverLock(driver);
7416
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7417
 
    qemuDriverUnlock(driver);
7418
 
    if (!vm) {
7419
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7420
 
        virUUIDFormat(dom->uuid, uuidstr);
7421
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7422
 
                        _("no domain with matching uuid '%s'"), uuidstr);
7423
 
        goto cleanup;
7424
 
    }
7425
 
 
7426
 
    if (!virDomainObjIsActive(vm)) {
7427
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7428
 
                        "%s", _("domain is not running"));
7429
 
        goto cleanup;
7430
 
    }
7431
 
 
7432
 
    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
7433
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7434
 
                        _("invalid path: %s"), path);
7435
 
        goto cleanup;
7436
 
    }
7437
 
    disk = vm->def->disks[i];
7438
 
 
7439
 
    if (!disk->info.alias) {
7440
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
7441
 
                        _("missing disk device alias name for %s"), disk->dst);
7442
 
        goto cleanup;
7443
 
    }
7444
 
 
7445
 
    priv = vm->privateData;
7446
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
7447
 
        goto cleanup;
7448
 
 
7449
 
    if (!virDomainObjIsActive(vm)) {
7450
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7451
 
                        "%s", _("domain is not running"));
7452
 
        goto endjob;
7453
 
    }
7454
 
 
7455
 
    qemuDomainObjEnterMonitor(driver, vm);
7456
 
    ret = qemuMonitorGetBlockStatsInfo(priv->mon,
7457
 
                                       disk->info.alias,
7458
 
                                       &stats->rd_req,
7459
 
                                       &stats->rd_bytes,
7460
 
                                       NULL,
7461
 
                                       &stats->wr_req,
7462
 
                                       &stats->wr_bytes,
7463
 
                                       NULL,
7464
 
                                       NULL,
7465
 
                                       NULL,
7466
 
                                       &stats->errs);
7467
 
    qemuDomainObjExitMonitor(driver, vm);
7468
 
 
7469
 
endjob:
7470
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
7471
 
        vm = NULL;
7472
 
 
7473
 
cleanup:
7474
 
    if (vm)
7475
 
        virDomainObjUnlock(vm);
7476
 
    return ret;
7477
 
}
7478
 
 
7479
 
static int
7480
 
qemuDomainBlockStatsFlags(virDomainPtr dom,
7481
 
                          const char *path,
7482
 
                          virTypedParameterPtr params,
7483
 
                          int *nparams,
7484
 
                          unsigned int flags)
7485
 
{
7486
 
    struct qemud_driver *driver = dom->conn->privateData;
7487
 
    int i, tmp, ret = -1;
7488
 
    virDomainObjPtr vm;
7489
 
    virDomainDiskDefPtr disk = NULL;
7490
 
    qemuDomainObjPrivatePtr priv;
7491
 
    long long rd_req, rd_bytes, wr_req, wr_bytes, rd_total_times;
7492
 
    long long wr_total_times, flush_req, flush_total_times, errs;
7493
 
    virTypedParameterPtr param;
7494
 
 
7495
 
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
7496
 
 
7497
 
    /* We don't return strings, and thus trivially support this flag.  */
7498
 
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
7499
 
 
7500
 
    qemuDriverLock(driver);
7501
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7502
 
    qemuDriverUnlock(driver);
7503
 
    if (!vm) {
7504
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7505
 
        virUUIDFormat(dom->uuid, uuidstr);
7506
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7507
 
                        _("no domain with matching uuid '%s'"), uuidstr);
7508
 
        goto cleanup;
7509
 
    }
7510
 
 
7511
 
    if (!virDomainObjIsActive(vm)) {
7512
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7513
 
                        "%s", _("domain is not running"));
7514
 
        goto cleanup;
7515
 
    }
7516
 
 
7517
 
    if (*nparams != 0) {
7518
 
        if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
7519
 
            qemuReportError(VIR_ERR_INVALID_ARG,
7520
 
                            _("invalid path: %s"), path);
7521
 
            goto cleanup;
7522
 
        }
7523
 
        disk = vm->def->disks[i];
7524
 
 
7525
 
        if (!disk->info.alias) {
7526
 
             qemuReportError(VIR_ERR_INTERNAL_ERROR,
7527
 
                             _("missing disk device alias name for %s"),
7528
 
                             disk->dst);
7529
 
             goto cleanup;
7530
 
        }
7531
 
    }
7532
 
 
7533
 
    priv = vm->privateData;
7534
 
    VIR_DEBUG("priv=%p, params=%p, flags=%x", priv, params, flags);
7535
 
 
7536
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
7537
 
        goto cleanup;
7538
 
 
7539
 
    if (!virDomainObjIsActive(vm)) {
7540
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7541
 
                        "%s", _("domain is not running"));
7542
 
        goto endjob;
7543
 
    }
7544
 
 
7545
 
    qemuDomainObjEnterMonitor(driver, vm);
7546
 
    tmp = *nparams;
7547
 
    ret = qemuMonitorGetBlockStatsParamsNumber(priv->mon, nparams);
7548
 
 
7549
 
    if (tmp == 0 || ret < 0) {
7550
 
        qemuDomainObjExitMonitor(driver, vm);
7551
 
        goto endjob;
7552
 
    }
7553
 
 
7554
 
    ret = qemuMonitorGetBlockStatsInfo(priv->mon,
7555
 
                                       disk->info.alias,
7556
 
                                       &rd_req,
7557
 
                                       &rd_bytes,
7558
 
                                       &rd_total_times,
7559
 
                                       &wr_req,
7560
 
                                       &wr_bytes,
7561
 
                                       &wr_total_times,
7562
 
                                       &flush_req,
7563
 
                                       &flush_total_times,
7564
 
                                       &errs);
7565
 
 
7566
 
    qemuDomainObjExitMonitor(driver, vm);
7567
 
 
7568
 
    if (ret < 0)
7569
 
        goto endjob;
7570
 
 
7571
 
    tmp = 0;
7572
 
    ret = -1;
7573
 
 
7574
 
    if (tmp < *nparams && wr_bytes != -1) {
7575
 
        param = &params[tmp];
7576
 
        if (virStrcpyStatic(param->field,
7577
 
                            VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES) == NULL) {
7578
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7579
 
                            _("Field name '%s' too long"),
7580
 
                            VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES);
7581
 
            goto endjob;
7582
 
        }
7583
 
        param->type = VIR_TYPED_PARAM_LLONG;
7584
 
        param->value.l = wr_bytes;
7585
 
        tmp++;
7586
 
    }
7587
 
 
7588
 
    if (tmp < *nparams && wr_req != -1) {
7589
 
        param = &params[tmp];
7590
 
        if (virStrcpyStatic(param->field,
7591
 
                            VIR_DOMAIN_BLOCK_STATS_WRITE_REQ) == NULL) {
7592
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7593
 
                            _("Field name '%s' too long"),
7594
 
                            VIR_DOMAIN_BLOCK_STATS_WRITE_REQ);
7595
 
            goto endjob;
7596
 
        }
7597
 
        param->type = VIR_TYPED_PARAM_LLONG;
7598
 
        param->value.l = wr_req;
7599
 
        tmp++;
7600
 
    }
7601
 
 
7602
 
    if (tmp < *nparams && rd_bytes != -1) {
7603
 
        param = &params[tmp];
7604
 
        if (virStrcpyStatic(param->field,
7605
 
                            VIR_DOMAIN_BLOCK_STATS_READ_BYTES) == NULL) {
7606
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7607
 
                            _("Field name '%s' too long"),
7608
 
                            VIR_DOMAIN_BLOCK_STATS_READ_BYTES);
7609
 
            goto endjob;
7610
 
        }
7611
 
        param->type = VIR_TYPED_PARAM_LLONG;
7612
 
        param->value.l = rd_bytes;
7613
 
        tmp++;
7614
 
    }
7615
 
 
7616
 
    if (tmp < *nparams && rd_req != -1) {
7617
 
        param = &params[tmp];
7618
 
        if (virStrcpyStatic(param->field,
7619
 
                            VIR_DOMAIN_BLOCK_STATS_READ_REQ) == NULL) {
7620
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7621
 
                            _("Field name '%s' too long"),
7622
 
                            VIR_DOMAIN_BLOCK_STATS_READ_REQ);
7623
 
            goto endjob;
7624
 
        }
7625
 
        param->type = VIR_TYPED_PARAM_LLONG;
7626
 
        param->value.l = rd_req;
7627
 
        tmp++;
7628
 
    }
7629
 
 
7630
 
    if (tmp < *nparams && flush_req != -1) {
7631
 
        param = &params[tmp];
7632
 
        if (virStrcpyStatic(param->field,
7633
 
                            VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ) == NULL) {
7634
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7635
 
                            _("Field name '%s' too long"),
7636
 
                            VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ);
7637
 
            goto endjob;
7638
 
        }
7639
 
        param->type = VIR_TYPED_PARAM_LLONG;
7640
 
        param->value.l = flush_req;
7641
 
        tmp++;
7642
 
    }
7643
 
 
7644
 
    if (tmp < *nparams && wr_total_times != -1) {
7645
 
        param = &params[tmp];
7646
 
        if (virStrcpyStatic(param->field,
7647
 
                            VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES) == NULL) {
7648
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7649
 
                            _("Field name '%s' too long"),
7650
 
                            VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES);
7651
 
            goto endjob;
7652
 
        }
7653
 
        param->type = VIR_TYPED_PARAM_LLONG;
7654
 
        param->value.l = wr_total_times;
7655
 
        tmp++;
7656
 
    }
7657
 
 
7658
 
    if (tmp < *nparams && rd_total_times != -1) {
7659
 
        param = &params[tmp];
7660
 
        if (virStrcpyStatic(param->field,
7661
 
                            VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES) == NULL) {
7662
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7663
 
                            _("Field name '%s' too long"),
7664
 
                            VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES);
7665
 
            goto endjob;
7666
 
        }
7667
 
        param->type = VIR_TYPED_PARAM_LLONG;
7668
 
        param->value.l = rd_total_times;
7669
 
        tmp++;
7670
 
    }
7671
 
 
7672
 
    if (tmp < *nparams && flush_total_times != -1) {
7673
 
        param = &params[tmp];
7674
 
        if (virStrcpyStatic(param->field,
7675
 
                            VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES) == NULL) {
7676
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
7677
 
                            _("Field name '%s' too long"),
7678
 
                            VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES);
7679
 
            goto endjob;
7680
 
        }
7681
 
        param->type = VIR_TYPED_PARAM_LLONG;
7682
 
        param->value.l = flush_total_times;
7683
 
        tmp++;
7684
 
    }
7685
 
 
7686
 
    /* Field 'errs' is meaningless for QEMU, won't set it. */
7687
 
 
7688
 
    ret = 0;
7689
 
    *nparams = tmp;
7690
 
 
7691
 
endjob:
7692
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
7693
 
        vm = NULL;
7694
 
 
7695
 
cleanup:
7696
 
    if (vm)
7697
 
        virDomainObjUnlock(vm);
7698
 
    return ret;
7699
 
}
7700
 
 
7701
 
#ifdef __linux__
7702
 
static int
7703
 
qemudDomainInterfaceStats (virDomainPtr dom,
7704
 
                           const char *path,
7705
 
                           struct _virDomainInterfaceStats *stats)
7706
 
{
7707
 
    struct qemud_driver *driver = dom->conn->privateData;
7708
 
    virDomainObjPtr vm;
7709
 
    int i;
7710
 
    int ret = -1;
7711
 
 
7712
 
    qemuDriverLock(driver);
7713
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7714
 
    qemuDriverUnlock(driver);
7715
 
 
7716
 
    if (!vm) {
7717
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7718
 
        virUUIDFormat(dom->uuid, uuidstr);
7719
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7720
 
                        _("no domain with matching uuid '%s'"), uuidstr);
7721
 
        goto cleanup;
7722
 
    }
7723
 
 
7724
 
    if (!virDomainObjIsActive(vm)) {
7725
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7726
 
                        "%s", _("domain is not running"));
7727
 
        goto cleanup;
7728
 
    }
7729
 
 
7730
 
    /* Check the path is one of the domain's network interfaces. */
7731
 
    for (i = 0 ; i < vm->def->nnets ; i++) {
7732
 
        if (vm->def->nets[i]->ifname &&
7733
 
            STREQ (vm->def->nets[i]->ifname, path)) {
7734
 
            ret = 0;
7735
 
            break;
7736
 
        }
7737
 
    }
7738
 
 
7739
 
    if (ret == 0)
7740
 
        ret = linuxDomainInterfaceStats(path, stats);
7741
 
    else
7742
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7743
 
                        _("invalid path, '%s' is not a known interface"), path);
7744
 
 
7745
 
cleanup:
7746
 
    if (vm)
7747
 
        virDomainObjUnlock(vm);
7748
 
    return ret;
7749
 
}
7750
 
#else
7751
 
static int
7752
 
qemudDomainInterfaceStats (virDomainPtr dom,
7753
 
                           const char *path ATTRIBUTE_UNUSED,
7754
 
                           struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
7755
 
{
7756
 
    qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
7757
 
                    _("interface stats not implemented on this platform"));
7758
 
    return -1;
7759
 
}
7760
 
#endif
7761
 
 
7762
 
static int
7763
 
qemudDomainMemoryStats (virDomainPtr dom,
7764
 
                        struct _virDomainMemoryStat *stats,
7765
 
                        unsigned int nr_stats,
7766
 
                        unsigned int flags)
7767
 
{
7768
 
    struct qemud_driver *driver = dom->conn->privateData;
7769
 
    virDomainObjPtr vm;
7770
 
    unsigned int ret = -1;
7771
 
 
7772
 
    virCheckFlags(0, -1);
7773
 
 
7774
 
    qemuDriverLock(driver);
7775
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7776
 
    qemuDriverUnlock(driver);
7777
 
 
7778
 
    if (!vm) {
7779
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7780
 
        virUUIDFormat(dom->uuid, uuidstr);
7781
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7782
 
                        _("no domain with matching uuid '%s'"), uuidstr);
7783
 
        goto cleanup;
7784
 
    }
7785
 
 
7786
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
7787
 
        goto cleanup;
7788
 
 
7789
 
    if (virDomainObjIsActive(vm)) {
7790
 
        qemuDomainObjPrivatePtr priv = vm->privateData;
7791
 
        qemuDomainObjEnterMonitor(driver, vm);
7792
 
        ret = qemuMonitorGetMemoryStats(priv->mon, stats, nr_stats);
7793
 
        qemuDomainObjExitMonitor(driver, vm);
7794
 
    } else {
7795
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7796
 
                        "%s", _("domain is not running"));
7797
 
    }
7798
 
 
7799
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
7800
 
        vm = NULL;
7801
 
 
7802
 
cleanup:
7803
 
    if (vm)
7804
 
        virDomainObjUnlock(vm);
7805
 
    return ret;
7806
 
}
7807
 
 
7808
 
static int
7809
 
qemudDomainBlockPeek (virDomainPtr dom,
7810
 
                      const char *path,
7811
 
                      unsigned long long offset, size_t size,
7812
 
                      void *buffer,
7813
 
                      unsigned int flags)
7814
 
{
7815
 
    struct qemud_driver *driver = dom->conn->privateData;
7816
 
    virDomainObjPtr vm;
7817
 
    int fd = -1, ret = -1;
7818
 
    const char *actual;
7819
 
 
7820
 
    virCheckFlags(0, -1);
7821
 
 
7822
 
    qemuDriverLock(driver);
7823
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7824
 
    qemuDriverUnlock(driver);
7825
 
 
7826
 
    if (!vm) {
7827
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7828
 
        virUUIDFormat(dom->uuid, uuidstr);
7829
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7830
 
                        _("no domain with matching uuid '%s'"), uuidstr);
7831
 
        goto cleanup;
7832
 
    }
7833
 
 
7834
 
    if (!path || path[0] == '\0') {
7835
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7836
 
                        "%s", _("NULL or empty path"));
7837
 
        goto cleanup;
7838
 
    }
7839
 
 
7840
 
    /* Check the path belongs to this domain.  */
7841
 
    if (!(actual = virDomainDiskPathByName(vm->def, path))) {
7842
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7843
 
                        _("invalid path '%s'"), path);
7844
 
        goto cleanup;
7845
 
    }
7846
 
    path = actual;
7847
 
 
7848
 
    /* The path is correct, now try to open it and get its size. */
7849
 
    fd = open(path, O_RDONLY);
7850
 
    if (fd == -1) {
7851
 
        virReportSystemError(errno,
7852
 
                             _("%s: failed to open"), path);
7853
 
        goto cleanup;
7854
 
    }
7855
 
 
7856
 
    /* Seek and read. */
7857
 
    /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
7858
 
     * be 64 bits on all platforms.
7859
 
     */
7860
 
    if (lseek(fd, offset, SEEK_SET) == (off_t) -1 ||
7861
 
        saferead(fd, buffer, size) == (ssize_t) -1) {
7862
 
        virReportSystemError(errno,
7863
 
                             _("%s: failed to seek or read"), path);
7864
 
        goto cleanup;
7865
 
    }
7866
 
 
7867
 
    ret = 0;
7868
 
 
7869
 
cleanup:
7870
 
    VIR_FORCE_CLOSE(fd);
7871
 
    if (vm)
7872
 
        virDomainObjUnlock(vm);
7873
 
    return ret;
7874
 
}
7875
 
 
7876
 
static int
7877
 
qemudDomainMemoryPeek (virDomainPtr dom,
7878
 
                       unsigned long long offset, size_t size,
7879
 
                       void *buffer,
7880
 
                       unsigned int flags)
7881
 
{
7882
 
    struct qemud_driver *driver = dom->conn->privateData;
7883
 
    virDomainObjPtr vm;
7884
 
    char *tmp = NULL;
7885
 
    int fd = -1, ret = -1;
7886
 
    qemuDomainObjPrivatePtr priv;
7887
 
 
7888
 
    virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);
7889
 
 
7890
 
    qemuDriverLock(driver);
7891
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7892
 
    qemuDriverUnlock(driver);
7893
 
 
7894
 
    if (!vm) {
7895
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7896
 
        virUUIDFormat(dom->uuid, uuidstr);
7897
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7898
 
                        _("no domain with matching uuid '%s'"), uuidstr);
7899
 
        goto cleanup;
7900
 
    }
7901
 
 
7902
 
    if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
7903
 
        qemuReportError(VIR_ERR_INVALID_ARG,
7904
 
                        "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
7905
 
        goto cleanup;
7906
 
    }
7907
 
 
7908
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
7909
 
        goto cleanup;
7910
 
 
7911
 
    if (!virDomainObjIsActive(vm)) {
7912
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
7913
 
                        "%s", _("domain is not running"));
7914
 
        goto endjob;
7915
 
    }
7916
 
 
7917
 
    if (virAsprintf(&tmp, "%s/qemu.mem.XXXXXX", driver->cacheDir) < 0) {
7918
 
        virReportOOMError();
7919
 
        goto endjob;
7920
 
    }
7921
 
 
7922
 
    /* Create a temporary filename. */
7923
 
    if ((fd = mkstemp (tmp)) == -1) {
7924
 
        virReportSystemError(errno,
7925
 
                             _("mkstemp(\"%s\") failed"), tmp);
7926
 
        goto endjob;
7927
 
    }
7928
 
 
7929
 
    virSecurityManagerSetSavedStateLabel(qemu_driver->securityManager, vm, tmp);
7930
 
 
7931
 
    priv = vm->privateData;
7932
 
    qemuDomainObjEnterMonitor(driver, vm);
7933
 
    if (flags == VIR_MEMORY_VIRTUAL) {
7934
 
        if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
7935
 
            qemuDomainObjExitMonitor(driver, vm);
7936
 
            goto endjob;
7937
 
        }
7938
 
    } else {
7939
 
        if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
7940
 
            qemuDomainObjExitMonitor(driver, vm);
7941
 
            goto endjob;
7942
 
        }
7943
 
    }
7944
 
    qemuDomainObjExitMonitor(driver, vm);
7945
 
 
7946
 
    /* Read the memory file into buffer. */
7947
 
    if (saferead(fd, buffer, size) == (ssize_t) -1) {
7948
 
        virReportSystemError(errno,
7949
 
                             _("failed to read temporary file "
7950
 
                               "created with template %s"), tmp);
7951
 
        goto endjob;
7952
 
    }
7953
 
 
7954
 
    ret = 0;
7955
 
 
7956
 
endjob:
7957
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
7958
 
        vm = NULL;
7959
 
 
7960
 
cleanup:
7961
 
    VIR_FORCE_CLOSE(fd);
7962
 
    if (tmp)
7963
 
        unlink(tmp);
7964
 
    VIR_FREE(tmp);
7965
 
    if (vm)
7966
 
        virDomainObjUnlock(vm);
7967
 
    return ret;
7968
 
}
7969
 
 
7970
 
 
7971
 
static int qemuDomainGetBlockInfo(virDomainPtr dom,
7972
 
                                  const char *path,
7973
 
                                  virDomainBlockInfoPtr info,
7974
 
                                  unsigned int flags) {
7975
 
    struct qemud_driver *driver = dom->conn->privateData;
7976
 
    virDomainObjPtr vm;
7977
 
    int ret = -1;
7978
 
    int fd = -1;
7979
 
    off_t end;
7980
 
    virStorageFileMetadata *meta = NULL;
7981
 
    virDomainDiskDefPtr disk = NULL;
7982
 
    struct stat sb;
7983
 
    int i;
7984
 
    int format;
7985
 
 
7986
 
    virCheckFlags(0, -1);
7987
 
 
7988
 
    qemuDriverLock(driver);
7989
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
7990
 
    qemuDriverUnlock(driver);
7991
 
    if (!vm) {
7992
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
7993
 
        virUUIDFormat(dom->uuid, uuidstr);
7994
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
7995
 
                        _("no domain with matching uuid '%s'"), uuidstr);
7996
 
        goto cleanup;
7997
 
    }
7998
 
 
7999
 
    if (!path || path[0] == '\0') {
8000
 
        qemuReportError(VIR_ERR_INVALID_ARG,
8001
 
                        "%s", _("NULL or empty path"));
8002
 
        goto cleanup;
8003
 
    }
8004
 
 
8005
 
    /* Check the path belongs to this domain. */
8006
 
    if ((i = virDomainDiskIndexByName(vm->def, path, false)) < 0) {
8007
 
        qemuReportError(VIR_ERR_INVALID_ARG,
8008
 
                        _("invalid path %s not assigned to domain"), path);
8009
 
        goto cleanup;
8010
 
    }
8011
 
    disk = vm->def->disks[i];
8012
 
    if (!disk->src) {
8013
 
        qemuReportError(VIR_ERR_INVALID_ARG,
8014
 
                        _("disk %s does not currently have a source assigned"),
8015
 
                        path);
8016
 
        goto cleanup;
8017
 
    }
8018
 
    path = disk->src;
8019
 
 
8020
 
    /* The path is correct, now try to open it and get its size. */
8021
 
    fd = open(path, O_RDONLY);
8022
 
    if (fd == -1) {
8023
 
        virReportSystemError(errno,
8024
 
                             _("failed to open path '%s'"), path);
8025
 
        goto cleanup;
8026
 
    }
8027
 
 
8028
 
    /* Probe for magic formats */
8029
 
    if (disk->driverType) {
8030
 
        if ((format = virStorageFileFormatTypeFromString(disk->driverType)) < 0) {
8031
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
8032
 
                            _("unknown disk format %s for %s"),
8033
 
                            disk->driverType, disk->src);
8034
 
            goto cleanup;
8035
 
        }
8036
 
    } else {
8037
 
        if (driver->allowDiskFormatProbing) {
8038
 
            if ((format = virStorageFileProbeFormat(disk->src)) < 0)
8039
 
                goto cleanup;
8040
 
        } else {
8041
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR,
8042
 
                            _("no disk format for %s and probing is disabled"),
8043
 
                            disk->src);
8044
 
            goto cleanup;
8045
 
        }
8046
 
    }
8047
 
 
8048
 
    if (VIR_ALLOC(meta) < 0) {
8049
 
        virReportOOMError();
8050
 
        goto cleanup;
8051
 
    }
8052
 
 
8053
 
    if (virStorageFileGetMetadataFromFD(path, fd,
8054
 
                                        format,
8055
 
                                        meta) < 0)
8056
 
        goto cleanup;
8057
 
 
8058
 
    /* Get info for normal formats */
8059
 
    if (fstat(fd, &sb) < 0) {
8060
 
        virReportSystemError(errno,
8061
 
                             _("cannot stat file '%s'"), path);
8062
 
        goto cleanup;
8063
 
    }
8064
 
 
8065
 
    if (S_ISREG(sb.st_mode)) {
8066
 
#ifndef WIN32
8067
 
        info->physical = (unsigned long long)sb.st_blocks *
8068
 
            (unsigned long long)DEV_BSIZE;
8069
 
#else
8070
 
        info->physical = sb.st_size;
8071
 
#endif
8072
 
        /* Regular files may be sparse, so logical size (capacity) is not same
8073
 
         * as actual physical above
8074
 
         */
8075
 
        info->capacity = sb.st_size;
8076
 
    } else {
8077
 
        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
8078
 
         * be 64 bits on all platforms.
8079
 
         */
8080
 
        end = lseek(fd, 0, SEEK_END);
8081
 
        if (end == (off_t)-1) {
8082
 
            virReportSystemError(errno,
8083
 
                                 _("failed to seek to end of %s"), path);
8084
 
            goto cleanup;
8085
 
        }
8086
 
        info->physical = end;
8087
 
        info->capacity = end;
8088
 
    }
8089
 
 
8090
 
    /* If the file we probed has a capacity set, then override
8091
 
     * what we calculated from file/block extents */
8092
 
    if (meta->capacity)
8093
 
        info->capacity = meta->capacity;
8094
 
 
8095
 
    /* Set default value .. */
8096
 
    info->allocation = info->physical;
8097
 
 
8098
 
    /* ..but if guest is running & not using raw
8099
 
       disk format and on a block device, then query
8100
 
       highest allocated extent from QEMU */
8101
 
    if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
8102
 
        format != VIR_STORAGE_FILE_RAW &&
8103
 
        S_ISBLK(sb.st_mode) &&
8104
 
        virDomainObjIsActive(vm)) {
8105
 
        qemuDomainObjPrivatePtr priv = vm->privateData;
8106
 
 
8107
 
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
8108
 
            goto cleanup;
8109
 
 
8110
 
        if (virDomainObjIsActive(vm)) {
8111
 
            qemuDomainObjEnterMonitor(driver, vm);
8112
 
            ret = qemuMonitorGetBlockExtent(priv->mon,
8113
 
                                            disk->info.alias,
8114
 
                                            &info->allocation);
8115
 
            qemuDomainObjExitMonitor(driver, vm);
8116
 
        } else {
8117
 
            ret = 0;
8118
 
        }
8119
 
 
8120
 
        if (qemuDomainObjEndJob(driver, vm) == 0)
8121
 
            vm = NULL;
8122
 
    } else {
8123
 
        ret = 0;
8124
 
    }
8125
 
 
8126
 
cleanup:
8127
 
    virStorageFileFreeMetadata(meta);
8128
 
    VIR_FORCE_CLOSE(fd);
8129
 
    if (vm)
8130
 
        virDomainObjUnlock(vm);
8131
 
    return ret;
8132
 
}
8133
 
 
8134
 
 
8135
 
static int
8136
 
qemuDomainEventRegister(virConnectPtr conn,
8137
 
                        virConnectDomainEventCallback callback,
8138
 
                        void *opaque,
8139
 
                        virFreeCallback freecb)
8140
 
{
8141
 
    struct qemud_driver *driver = conn->privateData;
8142
 
    int ret;
8143
 
 
8144
 
    qemuDriverLock(driver);
8145
 
    ret = virDomainEventCallbackListAdd(conn,
8146
 
                                        driver->domainEventState->callbacks,
8147
 
                                        callback, opaque, freecb);
8148
 
    qemuDriverUnlock(driver);
8149
 
 
8150
 
    return ret;
8151
 
}
8152
 
 
8153
 
 
8154
 
static int
8155
 
qemuDomainEventDeregister(virConnectPtr conn,
8156
 
                          virConnectDomainEventCallback callback)
8157
 
{
8158
 
    struct qemud_driver *driver = conn->privateData;
8159
 
    int ret;
8160
 
 
8161
 
    qemuDriverLock(driver);
8162
 
    ret = virDomainEventStateDeregister(conn,
8163
 
                                        driver->domainEventState,
8164
 
                                        callback);
8165
 
    qemuDriverUnlock(driver);
8166
 
 
8167
 
    return ret;
8168
 
}
8169
 
 
8170
 
 
8171
 
static int
8172
 
qemuDomainEventRegisterAny(virConnectPtr conn,
8173
 
                           virDomainPtr dom,
8174
 
                           int eventID,
8175
 
                           virConnectDomainEventGenericCallback callback,
8176
 
                           void *opaque,
8177
 
                           virFreeCallback freecb)
8178
 
{
8179
 
    struct qemud_driver *driver = conn->privateData;
8180
 
    int ret;
8181
 
 
8182
 
    qemuDriverLock(driver);
8183
 
    ret = virDomainEventCallbackListAddID(conn,
8184
 
                                          driver->domainEventState->callbacks,
8185
 
                                          dom, eventID,
8186
 
                                          callback, opaque, freecb);
8187
 
    qemuDriverUnlock(driver);
8188
 
 
8189
 
    return ret;
8190
 
}
8191
 
 
8192
 
 
8193
 
static int
8194
 
qemuDomainEventDeregisterAny(virConnectPtr conn,
8195
 
                             int callbackID)
8196
 
{
8197
 
    struct qemud_driver *driver = conn->privateData;
8198
 
    int ret;
8199
 
 
8200
 
    qemuDriverLock(driver);
8201
 
    ret = virDomainEventStateDeregisterAny(conn,
8202
 
                                           driver->domainEventState,
8203
 
                                           callbackID);
8204
 
    qemuDriverUnlock(driver);
8205
 
 
8206
 
    return ret;
8207
 
}
8208
 
 
8209
 
 
8210
 
/*******************************************************************
8211
 
 * Migration Protocol Version 2
8212
 
 *******************************************************************/
8213
 
 
8214
 
/* Prepare is the first step, and it runs on the destination host.
8215
 
 *
8216
 
 * This version starts an empty VM listening on a localhost TCP port, and
8217
 
 * sets up the corresponding virStream to handle the incoming data.
8218
 
 */
8219
 
static int
8220
 
qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
8221
 
                                virStreamPtr st,
8222
 
                                unsigned long flags,
8223
 
                                const char *dname,
8224
 
                                unsigned long resource ATTRIBUTE_UNUSED,
8225
 
                                const char *dom_xml)
8226
 
{
8227
 
    struct qemud_driver *driver = dconn->privateData;
8228
 
    int ret = -1;
8229
 
 
8230
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
8231
 
 
8232
 
    qemuDriverLock(driver);
8233
 
 
8234
 
    if (!dom_xml) {
8235
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8236
 
                        "%s", _("no domain XML passed"));
8237
 
        goto cleanup;
8238
 
    }
8239
 
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
8240
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8241
 
                         "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
8242
 
        goto cleanup;
8243
 
    }
8244
 
    if (st == NULL) {
8245
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8246
 
                        "%s", _("tunnelled migration requested but NULL stream passed"));
8247
 
        goto cleanup;
8248
 
    }
8249
 
 
8250
 
    if (virLockManagerPluginUsesState(driver->lockManager)) {
8251
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8252
 
                        _("Cannot use migrate v2 protocol with lock manager %s"),
8253
 
                        virLockManagerPluginGetName(driver->lockManager));
8254
 
        goto cleanup;
8255
 
    }
8256
 
 
8257
 
    ret = qemuMigrationPrepareTunnel(driver, dconn,
8258
 
                                     NULL, 0, NULL, NULL, /* No cookies in v2 */
8259
 
                                     st, dname, dom_xml);
8260
 
 
8261
 
cleanup:
8262
 
    qemuDriverUnlock(driver);
8263
 
    return ret;
8264
 
}
8265
 
 
8266
 
/* Prepare is the first step, and it runs on the destination host.
8267
 
 *
8268
 
 * This starts an empty VM listening on a TCP port.
8269
 
 */
8270
 
static int ATTRIBUTE_NONNULL (5)
8271
 
qemudDomainMigratePrepare2 (virConnectPtr dconn,
8272
 
                            char **cookie ATTRIBUTE_UNUSED,
8273
 
                            int *cookielen ATTRIBUTE_UNUSED,
8274
 
                            const char *uri_in,
8275
 
                            char **uri_out,
8276
 
                            unsigned long flags,
8277
 
                            const char *dname,
8278
 
                            unsigned long resource ATTRIBUTE_UNUSED,
8279
 
                            const char *dom_xml)
8280
 
{
8281
 
    struct qemud_driver *driver = dconn->privateData;
8282
 
    int ret = -1;
8283
 
 
8284
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
8285
 
 
8286
 
    *uri_out = NULL;
8287
 
 
8288
 
    qemuDriverLock(driver);
8289
 
 
8290
 
    if (virLockManagerPluginUsesState(driver->lockManager)) {
8291
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8292
 
                        _("Cannot use migrate v2 protocol with lock manager %s"),
8293
 
                        virLockManagerPluginGetName(driver->lockManager));
8294
 
        goto cleanup;
8295
 
    }
8296
 
 
8297
 
    if (flags & VIR_MIGRATE_TUNNELLED) {
8298
 
        /* this is a logical error; we never should have gotten here with
8299
 
         * VIR_MIGRATE_TUNNELLED set
8300
 
         */
8301
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8302
 
                        "%s", _("Tunnelled migration requested but invalid RPC method called"));
8303
 
        goto cleanup;
8304
 
    }
8305
 
 
8306
 
    if (!dom_xml) {
8307
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8308
 
                        "%s", _("no domain XML passed"));
8309
 
        goto cleanup;
8310
 
    }
8311
 
 
8312
 
    /* Do not use cookies in v2 protocol, since the cookie
8313
 
     * length was not sufficiently large, causing failures
8314
 
     * migrating between old & new libvirtd
8315
 
     */
8316
 
    ret = qemuMigrationPrepareDirect(driver, dconn,
8317
 
                                     NULL, 0, NULL, NULL, /* No cookies */
8318
 
                                     uri_in, uri_out,
8319
 
                                     dname, dom_xml);
8320
 
 
8321
 
cleanup:
8322
 
    qemuDriverUnlock(driver);
8323
 
    return ret;
8324
 
}
8325
 
 
8326
 
 
8327
 
/* Perform is the second step, and it runs on the source host. */
8328
 
static int
8329
 
qemudDomainMigratePerform (virDomainPtr dom,
8330
 
                           const char *cookie,
8331
 
                           int cookielen,
8332
 
                           const char *uri,
8333
 
                           unsigned long flags,
8334
 
                           const char *dname,
8335
 
                           unsigned long resource)
8336
 
{
8337
 
    struct qemud_driver *driver = dom->conn->privateData;
8338
 
    virDomainObjPtr vm;
8339
 
    int ret = -1;
8340
 
    const char *dconnuri = NULL;
8341
 
 
8342
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
8343
 
 
8344
 
    qemuDriverLock(driver);
8345
 
    if (virLockManagerPluginUsesState(driver->lockManager)) {
8346
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8347
 
                        _("Cannot use migrate v2 protocol with lock manager %s"),
8348
 
                        virLockManagerPluginGetName(driver->lockManager));
8349
 
        goto cleanup;
8350
 
    }
8351
 
 
8352
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
8353
 
    if (!vm) {
8354
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
8355
 
        virUUIDFormat(dom->uuid, uuidstr);
8356
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8357
 
                        _("no domain with matching uuid '%s'"), uuidstr);
8358
 
        goto cleanup;
8359
 
    }
8360
 
 
8361
 
    if (flags & VIR_MIGRATE_PEER2PEER) {
8362
 
        dconnuri = uri;
8363
 
        uri = NULL;
8364
 
    }
8365
 
 
8366
 
    /* Do not output cookies in v2 protocol, since the cookie
8367
 
     * length was not sufficiently large, causing failures
8368
 
     * migrating between old & new libvirtd.
8369
 
     *
8370
 
     * Consume any cookie we were able to decode though
8371
 
     */
8372
 
    ret = qemuMigrationPerform(driver, dom->conn, vm,
8373
 
                               NULL, dconnuri, uri, cookie, cookielen,
8374
 
                               NULL, NULL, /* No output cookies in v2 */
8375
 
                               flags, dname, resource, false);
8376
 
 
8377
 
cleanup:
8378
 
    qemuDriverUnlock(driver);
8379
 
    return ret;
8380
 
}
8381
 
 
8382
 
 
8383
 
/* Finish is the third and final step, and it runs on the destination host. */
8384
 
static virDomainPtr
8385
 
qemudDomainMigrateFinish2 (virConnectPtr dconn,
8386
 
                           const char *dname,
8387
 
                           const char *cookie ATTRIBUTE_UNUSED,
8388
 
                           int cookielen ATTRIBUTE_UNUSED,
8389
 
                           const char *uri ATTRIBUTE_UNUSED,
8390
 
                           unsigned long flags,
8391
 
                           int retcode)
8392
 
{
8393
 
    struct qemud_driver *driver = dconn->privateData;
8394
 
    virDomainObjPtr vm;
8395
 
    virDomainPtr dom = NULL;
8396
 
 
8397
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
8398
 
 
8399
 
    qemuDriverLock(driver);
8400
 
    vm = virDomainFindByName(&driver->domains, dname);
8401
 
    if (!vm) {
8402
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8403
 
                        _("no domain with matching name '%s'"), dname);
8404
 
        goto cleanup;
8405
 
    }
8406
 
 
8407
 
    /* Do not use cookies in v2 protocol, since the cookie
8408
 
     * length was not sufficiently large, causing failures
8409
 
     * migrating between old & new libvirtd
8410
 
     */
8411
 
    dom = qemuMigrationFinish(driver, dconn, vm,
8412
 
                              NULL, 0, NULL, NULL, /* No cookies */
8413
 
                              flags, retcode, false);
8414
 
 
8415
 
cleanup:
8416
 
    qemuDriverUnlock(driver);
8417
 
    return dom;
8418
 
}
8419
 
 
8420
 
 
8421
 
/*******************************************************************
8422
 
 * Migration Protocol Version 3
8423
 
 *******************************************************************/
8424
 
 
8425
 
static char *
8426
 
qemuDomainMigrateBegin3(virDomainPtr domain,
8427
 
                        const char *xmlin,
8428
 
                        char **cookieout,
8429
 
                        int *cookieoutlen,
8430
 
                        unsigned long flags,
8431
 
                        const char *dname,
8432
 
                        unsigned long resource ATTRIBUTE_UNUSED)
8433
 
{
8434
 
    struct qemud_driver *driver = domain->conn->privateData;
8435
 
    virDomainObjPtr vm;
8436
 
    char *xml = NULL;
8437
 
 
8438
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
8439
 
 
8440
 
    qemuDriverLock(driver);
8441
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
8442
 
    if (!vm) {
8443
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
8444
 
        virUUIDFormat(domain->uuid, uuidstr);
8445
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8446
 
                        _("no domain with matching uuid '%s'"), uuidstr);
8447
 
        goto cleanup;
8448
 
    }
8449
 
 
8450
 
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
8451
 
        if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
8452
 
            goto cleanup;
8453
 
    } else {
8454
 
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8455
 
            goto cleanup;
8456
 
    }
8457
 
 
8458
 
    if (!virDomainObjIsActive(vm)) {
8459
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
8460
 
                        "%s", _("domain is not running"));
8461
 
        goto endjob;
8462
 
    }
8463
 
 
8464
 
    /* Check if there is any ejected media.
8465
 
     * We don't want to require them on the destination.
8466
 
     */
8467
 
 
8468
 
    if (qemuDomainCheckEjectableMedia(driver, vm) < 0)
8469
 
        goto endjob;
8470
 
 
8471
 
    if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname,
8472
 
                                   cookieout, cookieoutlen)))
8473
 
        goto endjob;
8474
 
 
8475
 
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
8476
 
        /* We keep the job active across API calls until the confirm() call.
8477
 
         * This prevents any other APIs being invoked while migration is taking
8478
 
         * place.
8479
 
         */
8480
 
        if (qemuMigrationJobContinue(vm) == 0) {
8481
 
            vm = NULL;
8482
 
            qemuReportError(VIR_ERR_OPERATION_FAILED,
8483
 
                            "%s", _("domain disappeared"));
8484
 
            VIR_FREE(xml);
8485
 
            if (cookieout)
8486
 
                VIR_FREE(*cookieout);
8487
 
        }
8488
 
    } else {
8489
 
        goto endjob;
8490
 
    }
8491
 
 
8492
 
cleanup:
8493
 
    if (vm)
8494
 
        virDomainObjUnlock(vm);
8495
 
    qemuDriverUnlock(driver);
8496
 
    return xml;
8497
 
 
8498
 
endjob:
8499
 
    if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) {
8500
 
        if (qemuMigrationJobFinish(driver, vm) == 0)
8501
 
            vm = NULL;
8502
 
    } else {
8503
 
        if (qemuDomainObjEndJob(driver, vm) == 0)
8504
 
            vm = NULL;
8505
 
    }
8506
 
    goto cleanup;
8507
 
}
8508
 
 
8509
 
static int
8510
 
qemuDomainMigratePrepare3(virConnectPtr dconn,
8511
 
                          const char *cookiein,
8512
 
                          int cookieinlen,
8513
 
                          char **cookieout,
8514
 
                          int *cookieoutlen,
8515
 
                          const char *uri_in,
8516
 
                          char **uri_out,
8517
 
                          unsigned long flags,
8518
 
                          const char *dname,
8519
 
                          unsigned long resource ATTRIBUTE_UNUSED,
8520
 
                          const char *dom_xml)
8521
 
{
8522
 
    struct qemud_driver *driver = dconn->privateData;
8523
 
    int ret = -1;
8524
 
 
8525
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
8526
 
 
8527
 
    *uri_out = NULL;
8528
 
 
8529
 
    qemuDriverLock(driver);
8530
 
    if (flags & VIR_MIGRATE_TUNNELLED) {
8531
 
        /* this is a logical error; we never should have gotten here with
8532
 
         * VIR_MIGRATE_TUNNELLED set
8533
 
         */
8534
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8535
 
                        "%s", _("Tunnelled migration requested but invalid RPC method called"));
8536
 
        goto cleanup;
8537
 
    }
8538
 
 
8539
 
    if (!dom_xml) {
8540
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8541
 
                        "%s", _("no domain XML passed"));
8542
 
        goto cleanup;
8543
 
    }
8544
 
 
8545
 
    ret = qemuMigrationPrepareDirect(driver, dconn,
8546
 
                                     cookiein, cookieinlen,
8547
 
                                     cookieout, cookieoutlen,
8548
 
                                     uri_in, uri_out,
8549
 
                                     dname, dom_xml);
8550
 
 
8551
 
cleanup:
8552
 
    qemuDriverUnlock(driver);
8553
 
    return ret;
8554
 
}
8555
 
 
8556
 
 
8557
 
static int
8558
 
qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
8559
 
                                virStreamPtr st,
8560
 
                                const char *cookiein,
8561
 
                                int cookieinlen,
8562
 
                                char **cookieout,
8563
 
                                int *cookieoutlen,
8564
 
                                unsigned long flags,
8565
 
                                const char *dname,
8566
 
                                unsigned long resource ATTRIBUTE_UNUSED,
8567
 
                                const char *dom_xml)
8568
 
{
8569
 
    struct qemud_driver *driver = dconn->privateData;
8570
 
    int ret = -1;
8571
 
 
8572
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
8573
 
 
8574
 
    if (!dom_xml) {
8575
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8576
 
                        "%s", _("no domain XML passed"));
8577
 
        goto cleanup;
8578
 
    }
8579
 
    if (!(flags & VIR_MIGRATE_TUNNELLED)) {
8580
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8581
 
                         "%s", _("PrepareTunnel called but no TUNNELLED flag set"));
8582
 
        goto cleanup;
8583
 
    }
8584
 
    if (st == NULL) {
8585
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
8586
 
                        "%s", _("tunnelled migration requested but NULL stream passed"));
8587
 
        goto cleanup;
8588
 
    }
8589
 
 
8590
 
    qemuDriverLock(driver);
8591
 
    ret = qemuMigrationPrepareTunnel(driver, dconn,
8592
 
                                     cookiein, cookieinlen,
8593
 
                                     cookieout, cookieoutlen,
8594
 
                                     st, dname, dom_xml);
8595
 
    qemuDriverUnlock(driver);
8596
 
 
8597
 
cleanup:
8598
 
    return ret;
8599
 
}
8600
 
 
8601
 
 
8602
 
static int
8603
 
qemuDomainMigratePerform3(virDomainPtr dom,
8604
 
                          const char *xmlin,
8605
 
                          const char *cookiein,
8606
 
                          int cookieinlen,
8607
 
                          char **cookieout,
8608
 
                          int *cookieoutlen,
8609
 
                          const char *dconnuri,
8610
 
                          const char *uri,
8611
 
                          unsigned long flags,
8612
 
                          const char *dname,
8613
 
                          unsigned long resource)
8614
 
{
8615
 
    struct qemud_driver *driver = dom->conn->privateData;
8616
 
    virDomainObjPtr vm;
8617
 
    int ret = -1;
8618
 
 
8619
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
8620
 
 
8621
 
    qemuDriverLock(driver);
8622
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
8623
 
    if (!vm) {
8624
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
8625
 
        virUUIDFormat(dom->uuid, uuidstr);
8626
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8627
 
                        _("no domain with matching uuid '%s'"), uuidstr);
8628
 
        goto cleanup;
8629
 
    }
8630
 
 
8631
 
    ret = qemuMigrationPerform(driver, dom->conn, vm, xmlin,
8632
 
                               dconnuri, uri, cookiein, cookieinlen,
8633
 
                               cookieout, cookieoutlen,
8634
 
                               flags, dname, resource, true);
8635
 
 
8636
 
cleanup:
8637
 
    qemuDriverUnlock(driver);
8638
 
    return ret;
8639
 
}
8640
 
 
8641
 
 
8642
 
static virDomainPtr
8643
 
qemuDomainMigrateFinish3(virConnectPtr dconn,
8644
 
                         const char *dname,
8645
 
                         const char *cookiein,
8646
 
                         int cookieinlen,
8647
 
                         char **cookieout,
8648
 
                         int *cookieoutlen,
8649
 
                         const char *dconnuri ATTRIBUTE_UNUSED,
8650
 
                         const char *uri ATTRIBUTE_UNUSED,
8651
 
                         unsigned long flags,
8652
 
                         int cancelled)
8653
 
{
8654
 
    struct qemud_driver *driver = dconn->privateData;
8655
 
    virDomainObjPtr vm;
8656
 
    virDomainPtr dom = NULL;
8657
 
 
8658
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
8659
 
 
8660
 
    qemuDriverLock(driver);
8661
 
    vm = virDomainFindByName(&driver->domains, dname);
8662
 
    if (!vm) {
8663
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8664
 
                        _("no domain with matching name '%s'"), dname);
8665
 
        goto cleanup;
8666
 
    }
8667
 
 
8668
 
    dom = qemuMigrationFinish(driver, dconn, vm,
8669
 
                              cookiein, cookieinlen,
8670
 
                              cookieout, cookieoutlen,
8671
 
                              flags, cancelled, true);
8672
 
 
8673
 
cleanup:
8674
 
    qemuDriverUnlock(driver);
8675
 
    return dom;
8676
 
}
8677
 
 
8678
 
static int
8679
 
qemuDomainMigrateConfirm3(virDomainPtr domain,
8680
 
                          const char *cookiein,
8681
 
                          int cookieinlen,
8682
 
                          unsigned long flags,
8683
 
                          int cancelled)
8684
 
{
8685
 
    struct qemud_driver *driver = domain->conn->privateData;
8686
 
    virDomainObjPtr vm;
8687
 
    int ret = -1;
8688
 
    enum qemuMigrationJobPhase phase;
8689
 
 
8690
 
    virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
8691
 
 
8692
 
    qemuDriverLock(driver);
8693
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
8694
 
    if (!vm) {
8695
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
8696
 
        virUUIDFormat(domain->uuid, uuidstr);
8697
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8698
 
                        _("no domain with matching uuid '%s'"), uuidstr);
8699
 
        goto cleanup;
8700
 
    }
8701
 
 
8702
 
    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT))
8703
 
        goto cleanup;
8704
 
 
8705
 
    if (cancelled)
8706
 
        phase = QEMU_MIGRATION_PHASE_CONFIRM3_CANCELLED;
8707
 
    else
8708
 
        phase = QEMU_MIGRATION_PHASE_CONFIRM3;
8709
 
 
8710
 
    qemuMigrationJobStartPhase(driver, vm, phase);
8711
 
 
8712
 
    ret = qemuMigrationConfirm(driver, domain->conn, vm,
8713
 
                               cookiein, cookieinlen,
8714
 
                               flags, cancelled);
8715
 
 
8716
 
    if (qemuMigrationJobFinish(driver, vm) == 0) {
8717
 
        vm = NULL;
8718
 
    } else if (!virDomainObjIsActive(vm) &&
8719
 
               (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))) {
8720
 
        if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
8721
 
            virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
8722
 
        qemuDomainRemoveInactive(driver, vm);
8723
 
        vm = NULL;
8724
 
    }
8725
 
 
8726
 
cleanup:
8727
 
    if (vm)
8728
 
        virDomainObjUnlock(vm);
8729
 
    qemuDriverUnlock(driver);
8730
 
    return ret;
8731
 
}
8732
 
 
8733
 
 
8734
 
static int
8735
 
qemudNodeDeviceGetPciInfo (virNodeDevicePtr dev,
8736
 
                           unsigned *domain,
8737
 
                           unsigned *bus,
8738
 
                           unsigned *slot,
8739
 
                           unsigned *function)
8740
 
{
8741
 
    virNodeDeviceDefPtr def = NULL;
8742
 
    virNodeDevCapsDefPtr cap;
8743
 
    char *xml = NULL;
8744
 
    int ret = -1;
8745
 
 
8746
 
    xml = virNodeDeviceGetXMLDesc(dev, 0);
8747
 
    if (!xml)
8748
 
        goto out;
8749
 
 
8750
 
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE);
8751
 
    if (!def)
8752
 
        goto out;
8753
 
 
8754
 
    cap = def->caps;
8755
 
    while (cap) {
8756
 
        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
8757
 
            *domain   = cap->data.pci_dev.domain;
8758
 
            *bus      = cap->data.pci_dev.bus;
8759
 
            *slot     = cap->data.pci_dev.slot;
8760
 
            *function = cap->data.pci_dev.function;
8761
 
            break;
8762
 
        }
8763
 
 
8764
 
        cap = cap->next;
8765
 
    }
8766
 
 
8767
 
    if (!cap) {
8768
 
        qemuReportError(VIR_ERR_INVALID_ARG,
8769
 
                        _("device %s is not a PCI device"), dev->name);
8770
 
        goto out;
8771
 
    }
8772
 
 
8773
 
    ret = 0;
8774
 
out:
8775
 
    virNodeDeviceDefFree(def);
8776
 
    VIR_FREE(xml);
8777
 
    return ret;
8778
 
}
8779
 
 
8780
 
static int
8781
 
qemudNodeDeviceDettach (virNodeDevicePtr dev)
8782
 
{
8783
 
    struct qemud_driver *driver = dev->conn->privateData;
8784
 
    pciDevice *pci;
8785
 
    unsigned domain, bus, slot, function;
8786
 
    int ret = -1;
8787
 
 
8788
 
    if (qemudNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
8789
 
        return -1;
8790
 
 
8791
 
    pci = pciGetDevice(domain, bus, slot, function);
8792
 
    if (!pci)
8793
 
        return -1;
8794
 
 
8795
 
    qemuDriverLock(driver);
8796
 
    if (pciDettachDevice(pci, driver->activePciHostdevs) < 0)
8797
 
        goto out;
8798
 
 
8799
 
    ret = 0;
8800
 
out:
8801
 
    qemuDriverUnlock(driver);
8802
 
    pciFreeDevice(pci);
8803
 
    return ret;
8804
 
}
8805
 
 
8806
 
static int
8807
 
qemudNodeDeviceReAttach (virNodeDevicePtr dev)
8808
 
{
8809
 
    struct qemud_driver *driver = dev->conn->privateData;
8810
 
    pciDevice *pci;
8811
 
    unsigned domain, bus, slot, function;
8812
 
    int ret = -1;
8813
 
 
8814
 
    if (qemudNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
8815
 
        return -1;
8816
 
 
8817
 
    pci = pciGetDevice(domain, bus, slot, function);
8818
 
    if (!pci)
8819
 
        return -1;
8820
 
 
8821
 
    pciDeviceReAttachInit(pci);
8822
 
 
8823
 
    qemuDriverLock(driver);
8824
 
    if (pciReAttachDevice(pci, driver->activePciHostdevs) < 0)
8825
 
        goto out;
8826
 
 
8827
 
    ret = 0;
8828
 
out:
8829
 
    qemuDriverUnlock(driver);
8830
 
    pciFreeDevice(pci);
8831
 
    return ret;
8832
 
}
8833
 
 
8834
 
static int
8835
 
qemudNodeDeviceReset (virNodeDevicePtr dev)
8836
 
{
8837
 
    struct qemud_driver *driver = dev->conn->privateData;
8838
 
    pciDevice *pci;
8839
 
    unsigned domain, bus, slot, function;
8840
 
    int ret = -1;
8841
 
 
8842
 
    if (qemudNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
8843
 
        return -1;
8844
 
 
8845
 
    pci = pciGetDevice(domain, bus, slot, function);
8846
 
    if (!pci)
8847
 
        return -1;
8848
 
 
8849
 
    qemuDriverLock(driver);
8850
 
 
8851
 
    if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
8852
 
        goto out;
8853
 
 
8854
 
    ret = 0;
8855
 
out:
8856
 
    qemuDriverUnlock(driver);
8857
 
    pciFreeDevice(pci);
8858
 
    return ret;
8859
 
}
8860
 
 
8861
 
static int
8862
 
qemuCPUCompare(virConnectPtr conn,
8863
 
               const char *xmlDesc,
8864
 
               unsigned int flags)
8865
 
{
8866
 
    struct qemud_driver *driver = conn->privateData;
8867
 
    int ret = VIR_CPU_COMPARE_ERROR;
8868
 
 
8869
 
    virCheckFlags(0, VIR_CPU_COMPARE_ERROR);
8870
 
 
8871
 
    qemuDriverLock(driver);
8872
 
 
8873
 
    if (!driver->caps || !driver->caps->host.cpu) {
8874
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
8875
 
                        "%s", _("cannot get host CPU capabilities"));
8876
 
    } else {
8877
 
        ret = cpuCompareXML(driver->caps->host.cpu, xmlDesc);
8878
 
    }
8879
 
 
8880
 
    qemuDriverUnlock(driver);
8881
 
 
8882
 
    return ret;
8883
 
}
8884
 
 
8885
 
 
8886
 
static char *
8887
 
qemuCPUBaseline(virConnectPtr conn ATTRIBUTE_UNUSED,
8888
 
                const char **xmlCPUs,
8889
 
                unsigned int ncpus,
8890
 
                unsigned int flags)
8891
 
{
8892
 
    char *cpu;
8893
 
 
8894
 
    virCheckFlags(0, NULL);
8895
 
 
8896
 
    cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0);
8897
 
 
8898
 
    return cpu;
8899
 
}
8900
 
 
8901
 
 
8902
 
static int qemuDomainGetJobInfo(virDomainPtr dom,
8903
 
                                virDomainJobInfoPtr info) {
8904
 
    struct qemud_driver *driver = dom->conn->privateData;
8905
 
    virDomainObjPtr vm;
8906
 
    int ret = -1;
8907
 
    qemuDomainObjPrivatePtr priv;
8908
 
 
8909
 
    qemuDriverLock(driver);
8910
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
8911
 
    qemuDriverUnlock(driver);
8912
 
    if (!vm) {
8913
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
8914
 
        virUUIDFormat(dom->uuid, uuidstr);
8915
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8916
 
                        _("no domain with matching uuid '%s'"), uuidstr);
8917
 
        goto cleanup;
8918
 
    }
8919
 
 
8920
 
    priv = vm->privateData;
8921
 
 
8922
 
    if (virDomainObjIsActive(vm)) {
8923
 
        if (priv->job.asyncJob) {
8924
 
            memcpy(info, &priv->job.info, sizeof(*info));
8925
 
 
8926
 
            /* Refresh elapsed time again just to ensure it
8927
 
             * is fully updated. This is primarily for benefit
8928
 
             * of incoming migration which we don't currently
8929
 
             * monitor actively in the background thread
8930
 
             */
8931
 
            if (virTimeMillisNow(&info->timeElapsed) < 0)
8932
 
                goto cleanup;
8933
 
            info->timeElapsed -= priv->job.start;
8934
 
        } else {
8935
 
            memset(info, 0, sizeof(*info));
8936
 
            info->type = VIR_DOMAIN_JOB_NONE;
8937
 
        }
8938
 
    } else {
8939
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
8940
 
                        "%s", _("domain is not running"));
8941
 
        goto cleanup;
8942
 
    }
8943
 
 
8944
 
    ret = 0;
8945
 
 
8946
 
cleanup:
8947
 
    if (vm)
8948
 
        virDomainObjUnlock(vm);
8949
 
    return ret;
8950
 
}
8951
 
 
8952
 
 
8953
 
static int qemuDomainAbortJob(virDomainPtr dom) {
8954
 
    struct qemud_driver *driver = dom->conn->privateData;
8955
 
    virDomainObjPtr vm;
8956
 
    int ret = -1;
8957
 
    qemuDomainObjPrivatePtr priv;
8958
 
 
8959
 
    qemuDriverLock(driver);
8960
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
8961
 
    qemuDriverUnlock(driver);
8962
 
    if (!vm) {
8963
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
8964
 
        virUUIDFormat(dom->uuid, uuidstr);
8965
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
8966
 
                        _("no domain with matching uuid '%s'"), uuidstr);
8967
 
        goto cleanup;
8968
 
    }
8969
 
 
8970
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_ABORT) < 0)
8971
 
        goto cleanup;
8972
 
 
8973
 
    if (!virDomainObjIsActive(vm)) {
8974
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
8975
 
                        "%s", _("domain is not running"));
8976
 
        goto endjob;
8977
 
    }
8978
 
 
8979
 
    priv = vm->privateData;
8980
 
 
8981
 
    if (!priv->job.asyncJob) {
8982
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
8983
 
                        "%s", _("no job is active on the domain"));
8984
 
        goto endjob;
8985
 
    } else if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
8986
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
8987
 
                        _("cannot abort incoming migration;"
8988
 
                          " use virDomainDestroy instead"));
8989
 
        goto endjob;
8990
 
    }
8991
 
 
8992
 
    VIR_DEBUG("Cancelling job at client request");
8993
 
    qemuDomainObjEnterMonitor(driver, vm);
8994
 
    ret = qemuMonitorMigrateCancel(priv->mon);
8995
 
    qemuDomainObjExitMonitor(driver, vm);
8996
 
 
8997
 
endjob:
8998
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
8999
 
        vm = NULL;
9000
 
 
9001
 
cleanup:
9002
 
    if (vm)
9003
 
        virDomainObjUnlock(vm);
9004
 
    return ret;
9005
 
}
9006
 
 
9007
 
 
9008
 
static int
9009
 
qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
9010
 
                                unsigned long long downtime,
9011
 
                                unsigned int flags)
9012
 
{
9013
 
    struct qemud_driver *driver = dom->conn->privateData;
9014
 
    virDomainObjPtr vm;
9015
 
    qemuDomainObjPrivatePtr priv;
9016
 
    int ret = -1;
9017
 
 
9018
 
    virCheckFlags(0, -1);
9019
 
 
9020
 
    qemuDriverLock(driver);
9021
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
9022
 
    qemuDriverUnlock(driver);
9023
 
 
9024
 
    if (!vm) {
9025
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
9026
 
        virUUIDFormat(dom->uuid, uuidstr);
9027
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9028
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9029
 
        return -1;
9030
 
    }
9031
 
 
9032
 
    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
9033
 
        goto cleanup;
9034
 
 
9035
 
    if (!virDomainObjIsActive(vm)) {
9036
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
9037
 
                        "%s", _("domain is not running"));
9038
 
        goto endjob;
9039
 
    }
9040
 
 
9041
 
    priv = vm->privateData;
9042
 
 
9043
 
    if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) {
9044
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
9045
 
                        "%s", _("domain is not being migrated"));
9046
 
        goto endjob;
9047
 
    }
9048
 
 
9049
 
    VIR_DEBUG("Setting migration downtime to %llums", downtime);
9050
 
    qemuDomainObjEnterMonitor(driver, vm);
9051
 
    ret = qemuMonitorSetMigrationDowntime(priv->mon, downtime);
9052
 
    qemuDomainObjExitMonitor(driver, vm);
9053
 
 
9054
 
endjob:
9055
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
9056
 
        vm = NULL;
9057
 
 
9058
 
cleanup:
9059
 
    if (vm)
9060
 
        virDomainObjUnlock(vm);
9061
 
    return ret;
9062
 
}
9063
 
 
9064
 
static int
9065
 
qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
9066
 
                             unsigned long bandwidth,
9067
 
                             unsigned int flags)
9068
 
{
9069
 
    struct qemud_driver *driver = dom->conn->privateData;
9070
 
    virDomainObjPtr vm;
9071
 
    qemuDomainObjPrivatePtr priv;
9072
 
    int ret = -1;
9073
 
 
9074
 
    virCheckFlags(0, -1);
9075
 
 
9076
 
    qemuDriverLock(driver);
9077
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
9078
 
    qemuDriverUnlock(driver);
9079
 
 
9080
 
    if (!vm) {
9081
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
9082
 
        virUUIDFormat(dom->uuid, uuidstr);
9083
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9084
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9085
 
        return -1;
9086
 
    }
9087
 
 
9088
 
    priv = vm->privateData;
9089
 
    if (virDomainObjIsActive(vm)) {
9090
 
        if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
9091
 
            goto cleanup;
9092
 
 
9093
 
        if (!virDomainObjIsActive(vm)) {
9094
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
9095
 
                            "%s", _("domain is not running"));
9096
 
            goto endjob;
9097
 
        }
9098
 
 
9099
 
        VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
9100
 
        qemuDomainObjEnterMonitor(driver, vm);
9101
 
        ret = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
9102
 
        qemuDomainObjExitMonitor(driver, vm);
9103
 
 
9104
 
        if (ret == 0)
9105
 
            priv->migMaxBandwidth = bandwidth;
9106
 
 
9107
 
endjob:
9108
 
        if (qemuDomainObjEndJob(driver, vm) == 0)
9109
 
            vm = NULL;
9110
 
    } else {
9111
 
        priv->migMaxBandwidth = bandwidth;
9112
 
        ret = 0;
9113
 
    }
9114
 
 
9115
 
cleanup:
9116
 
    if (vm)
9117
 
        virDomainObjUnlock(vm);
9118
 
    return ret;
9119
 
}
9120
 
 
9121
 
static int
9122
 
qemuDomainMigrateGetMaxSpeed(virDomainPtr dom,
9123
 
                             unsigned long *bandwidth,
9124
 
                             unsigned int flags)
9125
 
{
9126
 
    struct qemud_driver *driver = dom->conn->privateData;
9127
 
    virDomainObjPtr vm;
9128
 
    qemuDomainObjPrivatePtr priv;
9129
 
    int ret = -1;
9130
 
 
9131
 
    virCheckFlags(0, -1);
9132
 
 
9133
 
    qemuDriverLock(driver);
9134
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
9135
 
    qemuDriverUnlock(driver);
9136
 
 
9137
 
    if (!vm) {
9138
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
9139
 
        virUUIDFormat(dom->uuid, uuidstr);
9140
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9141
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9142
 
        goto cleanup;
9143
 
    }
9144
 
 
9145
 
    priv = vm->privateData;
9146
 
    *bandwidth = priv->migMaxBandwidth;
9147
 
    ret = 0;
9148
 
 
9149
 
cleanup:
9150
 
    if (vm)
9151
 
        virDomainObjUnlock(vm);
9152
 
    return ret;
9153
 
}
9154
 
 
9155
 
static int qemuDomainSnapshotIsAllowed(virDomainObjPtr vm)
9156
 
{
9157
 
    int i;
9158
 
 
9159
 
    /* FIXME: we need to figure out what else here might succeed; in
9160
 
     * particular, if it's a raw device but on LVM, we could probably make
9161
 
     * that succeed as well
9162
 
     */
9163
 
    for (i = 0; i < vm->def->ndisks; i++) {
9164
 
        if (vm->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
9165
 
            (!vm->def->disks[i]->driverType ||
9166
 
             STRNEQ(vm->def->disks[i]->driverType, "qcow2"))) {
9167
 
            qemuReportError(VIR_ERR_OPERATION_INVALID,
9168
 
                            _("Disk '%s' does not support snapshotting"),
9169
 
                            vm->def->disks[i]->src);
9170
 
            return 0;
9171
 
        }
9172
 
    }
9173
 
 
9174
 
    return 1;
9175
 
}
9176
 
 
9177
 
/* The domain is expected to be locked and inactive. */
9178
 
static int
9179
 
qemuDomainSnapshotCreateInactive(struct qemud_driver *driver,
9180
 
                                 virDomainObjPtr vm,
9181
 
                                 virDomainSnapshotObjPtr snap)
9182
 
{
9183
 
    return qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-c", false);
9184
 
}
9185
 
 
9186
 
/* The domain is expected to be locked and active. */
9187
 
static int
9188
 
qemuDomainSnapshotCreateActive(virConnectPtr conn,
9189
 
                               struct qemud_driver *driver,
9190
 
                               virDomainObjPtr *vmptr,
9191
 
                               virDomainSnapshotObjPtr snap,
9192
 
                               unsigned int flags)
9193
 
{
9194
 
    virDomainObjPtr vm = *vmptr;
9195
 
    qemuDomainObjPrivatePtr priv = vm->privateData;
9196
 
    bool resume = false;
9197
 
    int ret = -1;
9198
 
 
9199
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
9200
 
        return -1;
9201
 
 
9202
 
    if (!virDomainObjIsActive(vm)) {
9203
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
9204
 
                        "%s", _("domain is not running"));
9205
 
        goto endjob;
9206
 
    }
9207
 
 
9208
 
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
9209
 
        /* savevm monitor command pauses the domain emitting an event which
9210
 
         * confuses libvirt since it's not notified when qemu resumes the
9211
 
         * domain. Thus we stop and start CPUs ourselves.
9212
 
         */
9213
 
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
9214
 
                                QEMU_ASYNC_JOB_NONE) < 0)
9215
 
            goto cleanup;
9216
 
 
9217
 
        resume = true;
9218
 
        if (!virDomainObjIsActive(vm)) {
9219
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9220
 
                            _("guest unexpectedly quit"));
9221
 
            goto cleanup;
9222
 
        }
9223
 
    }
9224
 
 
9225
 
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
9226
 
    ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
9227
 
    qemuDomainObjExitMonitorWithDriver(driver, vm);
9228
 
    if (ret < 0)
9229
 
        goto cleanup;
9230
 
 
9231
 
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
9232
 
        virDomainEventPtr event;
9233
 
 
9234
 
        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
9235
 
                                         VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
9236
 
        qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
9237
 
        virDomainAuditStop(vm, "from-snapshot");
9238
 
        /* We already filtered the _HALT flag for persistent domains
9239
 
         * only, so this end job never drops the last reference.  */
9240
 
        ignore_value(qemuDomainObjEndJob(driver, vm));
9241
 
        resume = false;
9242
 
        vm = NULL;
9243
 
        if (event)
9244
 
            qemuDomainEventQueue(driver, event);
9245
 
    }
9246
 
 
9247
 
cleanup:
9248
 
    if (resume && virDomainObjIsActive(vm) &&
9249
 
        qemuProcessStartCPUs(driver, vm, conn,
9250
 
                             VIR_DOMAIN_RUNNING_UNPAUSED,
9251
 
                             QEMU_ASYNC_JOB_NONE) < 0 &&
9252
 
        virGetLastError() == NULL) {
9253
 
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
9254
 
                        _("resuming after snapshot failed"));
9255
 
    }
9256
 
 
9257
 
endjob:
9258
 
    if (vm && qemuDomainObjEndJob(driver, vm) == 0) {
9259
 
        /* Only possible if a transient vm quit while our locks were down,
9260
 
         * in which case we don't want to save snapshot metadata.  */
9261
 
        *vmptr = NULL;
9262
 
        ret = -1;
9263
 
    }
9264
 
 
9265
 
    return ret;
9266
 
}
9267
 
 
9268
 
static int
9269
 
qemuDomainSnapshotDiskPrepare(virDomainObjPtr vm, virDomainSnapshotDefPtr def)
9270
 
{
9271
 
    int ret = -1;
9272
 
    int i;
9273
 
    bool found = false;
9274
 
    bool active = virDomainObjIsActive(vm);
9275
 
    struct stat st;
9276
 
 
9277
 
    for (i = 0; i < def->ndisks; i++) {
9278
 
        virDomainSnapshotDiskDefPtr disk = &def->disks[i];
9279
 
 
9280
 
        switch (disk->snapshot) {
9281
 
        case VIR_DOMAIN_DISK_SNAPSHOT_INTERNAL:
9282
 
            if (active) {
9283
 
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9284
 
                                _("active qemu domains require external disk "
9285
 
                                  "snapshots; disk %s requested internal"),
9286
 
                                disk->name);
9287
 
                goto cleanup;
9288
 
            }
9289
 
            if (!vm->def->disks[i]->driverType ||
9290
 
                STRNEQ(vm->def->disks[i]->driverType, "qcow2")) {
9291
 
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9292
 
                                _("internal snapshot for disk %s unsupported "
9293
 
                                  "for storage type %s"),
9294
 
                                disk->name,
9295
 
                                NULLSTR(vm->def->disks[i]->driverType));
9296
 
                goto cleanup;
9297
 
            }
9298
 
            found = true;
9299
 
            break;
9300
 
 
9301
 
        case VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL:
9302
 
            if (!disk->driverType) {
9303
 
                if (!(disk->driverType = strdup("qcow2"))) {
9304
 
                    virReportOOMError();
9305
 
                    goto cleanup;
9306
 
                }
9307
 
            } else if (STRNEQ(disk->driverType, "qcow2")) {
9308
 
                /* XXX We should also support QED */
9309
 
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9310
 
                                _("external snapshot format for disk %s "
9311
 
                                  "is unsupported: %s"),
9312
 
                                disk->name, disk->driverType);
9313
 
                goto cleanup;
9314
 
            }
9315
 
            if (stat(disk->file, &st) < 0) {
9316
 
                if (errno != ENOENT) {
9317
 
                    virReportSystemError(errno,
9318
 
                                         _("unable to stat for disk %s: %s"),
9319
 
                                         disk->name, disk->file);
9320
 
                    goto cleanup;
9321
 
                }
9322
 
            } else if (!S_ISBLK(st.st_mode)) {
9323
 
                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9324
 
                                _("external snapshot file for disk %s already "
9325
 
                                  "exists and is not a block device: %s"),
9326
 
                                disk->name, disk->file);
9327
 
                goto cleanup;
9328
 
            }
9329
 
            found = true;
9330
 
            break;
9331
 
 
9332
 
        case VIR_DOMAIN_DISK_SNAPSHOT_NO:
9333
 
            break;
9334
 
 
9335
 
        case VIR_DOMAIN_DISK_SNAPSHOT_DEFAULT:
9336
 
        default:
9337
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9338
 
                            _("unexpected code path"));
9339
 
            goto cleanup;
9340
 
        }
9341
 
    }
9342
 
 
9343
 
    if (!found) {
9344
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9345
 
                        _("disk snapshots require at least one disk to be "
9346
 
                          "selected for snapshot"));
9347
 
        goto cleanup;
9348
 
    }
9349
 
 
9350
 
    ret = 0;
9351
 
 
9352
 
cleanup:
9353
 
    return ret;
9354
 
}
9355
 
 
9356
 
/* The domain is expected to hold monitor lock.  */
9357
 
static int
9358
 
qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver,
9359
 
                                         virDomainObjPtr vm,
9360
 
                                         virDomainSnapshotDiskDefPtr snap,
9361
 
                                         virDomainDiskDefPtr disk,
9362
 
                                         virDomainDiskDefPtr persistDisk)
9363
 
{
9364
 
    qemuDomainObjPrivatePtr priv = vm->privateData;
9365
 
    char *device = NULL;
9366
 
    char *source = NULL;
9367
 
    char *driverType = NULL;
9368
 
    char *persistSource = NULL;
9369
 
    char *persistDriverType = NULL;
9370
 
    int ret = -1;
9371
 
    int fd = -1;
9372
 
    char *origsrc = NULL;
9373
 
    char *origdriver = NULL;
9374
 
    bool need_unlink = false;
9375
 
 
9376
 
    if (snap->snapshot != VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL) {
9377
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9378
 
                        _("unexpected code path"));
9379
 
        return -1;
9380
 
    }
9381
 
 
9382
 
    if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
9383
 
        !(source = strdup(snap->file)) ||
9384
 
        (STRNEQ_NULLABLE(disk->driverType, "qcow2") &&
9385
 
         !(driverType = strdup("qcow2"))) ||
9386
 
        (persistDisk &&
9387
 
         (!(persistSource = strdup(source)) ||
9388
 
          (STRNEQ_NULLABLE(persistDisk->driverType, "qcow2") &&
9389
 
           !(persistDriverType = strdup("qcow2")))))) {
9390
 
        virReportOOMError();
9391
 
        goto cleanup;
9392
 
    }
9393
 
 
9394
 
    /* create the stub file and set selinux labels; manipulate disk in
9395
 
     * place, in a way that can be reverted on failure. */
9396
 
    fd = qemuOpenFile(driver, source, O_WRONLY | O_TRUNC | O_CREAT,
9397
 
                      &need_unlink, NULL);
9398
 
    if (fd < 0)
9399
 
        goto cleanup;
9400
 
    VIR_FORCE_CLOSE(fd);
9401
 
 
9402
 
    origsrc = disk->src;
9403
 
    disk->src = source;
9404
 
    origdriver = disk->driverType;
9405
 
    disk->driverType = (char *) "raw"; /* Don't want to probe backing files */
9406
 
 
9407
 
    if (virDomainLockDiskAttach(driver->lockManager, vm, disk) < 0)
9408
 
        goto cleanup;
9409
 
    if (virSecurityManagerSetImageLabel(driver->securityManager, vm,
9410
 
                                        disk) < 0) {
9411
 
        if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
9412
 
            VIR_WARN("Unable to release lock on %s", source);
9413
 
        goto cleanup;
9414
 
    }
9415
 
 
9416
 
    disk->src = origsrc;
9417
 
    origsrc = NULL;
9418
 
    disk->driverType = origdriver;
9419
 
    origdriver = NULL;
9420
 
 
9421
 
    /* create the actual snapshot */
9422
 
    ret = qemuMonitorDiskSnapshot(priv->mon, device, source);
9423
 
    virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0);
9424
 
    if (ret < 0)
9425
 
        goto cleanup;
9426
 
 
9427
 
    /* Update vm in place to match changes.  */
9428
 
    need_unlink = false;
9429
 
    VIR_FREE(disk->src);
9430
 
    disk->src = source;
9431
 
    source = NULL;
9432
 
    if (driverType) {
9433
 
        VIR_FREE(disk->driverType);
9434
 
        disk->driverType = driverType;
9435
 
        driverType = NULL;
9436
 
    }
9437
 
    if (persistDisk) {
9438
 
        VIR_FREE(persistDisk->src);
9439
 
        persistDisk->src = persistSource;
9440
 
        persistSource = NULL;
9441
 
        if (persistDriverType) {
9442
 
            VIR_FREE(persistDisk->driverType);
9443
 
            persistDisk->driverType = persistDriverType;
9444
 
            persistDriverType = NULL;
9445
 
        }
9446
 
    }
9447
 
 
9448
 
cleanup:
9449
 
    if (origsrc) {
9450
 
        disk->src = origsrc;
9451
 
        disk->driverType = origdriver;
9452
 
    }
9453
 
    if (need_unlink && unlink(source))
9454
 
        VIR_WARN("unable to unlink just-created %s", source);
9455
 
    VIR_FREE(device);
9456
 
    VIR_FREE(source);
9457
 
    VIR_FREE(driverType);
9458
 
    VIR_FREE(persistSource);
9459
 
    VIR_FREE(persistDriverType);
9460
 
    return ret;
9461
 
}
9462
 
 
9463
 
/* The domain is expected to be locked and active. */
9464
 
static int
9465
 
qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
9466
 
                                   struct qemud_driver *driver,
9467
 
                                   virDomainObjPtr *vmptr,
9468
 
                                   virDomainSnapshotObjPtr snap,
9469
 
                                   unsigned int flags)
9470
 
{
9471
 
    virDomainObjPtr vm = *vmptr;
9472
 
    bool resume = false;
9473
 
    int ret = -1;
9474
 
    int i;
9475
 
    bool persist = false;
9476
 
 
9477
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
9478
 
        return -1;
9479
 
 
9480
 
    if (!virDomainObjIsActive(vm)) {
9481
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
9482
 
                        "%s", _("domain is not running"));
9483
 
        goto endjob;
9484
 
    }
9485
 
 
9486
 
 
9487
 
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
9488
 
        /* In qemu, snapshot_blkdev on a single disk will pause cpus,
9489
 
         * but this confuses libvirt since notifications are not given
9490
 
         * when qemu resumes.  And for multiple disks, libvirt must
9491
 
         * pause externally to get all snapshots to be at the same
9492
 
         * point in time.  For simplicitly, we always pause ourselves
9493
 
         * rather than relying on qemu doing pause.
9494
 
         */
9495
 
        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
9496
 
                                QEMU_ASYNC_JOB_NONE) < 0)
9497
 
            goto cleanup;
9498
 
 
9499
 
        resume = true;
9500
 
        if (!virDomainObjIsActive(vm)) {
9501
 
            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9502
 
                            _("guest unexpectedly quit"));
9503
 
            goto cleanup;
9504
 
        }
9505
 
    }
9506
 
 
9507
 
    /* No way to roll back if first disk succeeds but later disks
9508
 
     * fail.  Based on earlier qemuDomainSnapshotDiskPrepare, all
9509
 
     * disks in this list are now either SNAPSHOT_NO, or
9510
 
     * SNAPSHOT_EXTERNAL with a valid file name and qcow2 format.  */
9511
 
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
9512
 
    for (i = 0; i < snap->def->ndisks; i++) {
9513
 
        virDomainDiskDefPtr persistDisk = NULL;
9514
 
 
9515
 
        if (snap->def->disks[i].snapshot == VIR_DOMAIN_DISK_SNAPSHOT_NO)
9516
 
            continue;
9517
 
        if (vm->newDef) {
9518
 
            int indx = virDomainDiskIndexByName(vm->newDef,
9519
 
                                                vm->def->disks[i]->dst,
9520
 
                                                false);
9521
 
            if (indx >= 0) {
9522
 
                persistDisk = vm->newDef->disks[indx];
9523
 
                persist = true;
9524
 
            }
9525
 
        }
9526
 
 
9527
 
        ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
9528
 
                                                       &snap->def->disks[i],
9529
 
                                                       vm->def->disks[i],
9530
 
                                                       persistDisk);
9531
 
        if (ret < 0)
9532
 
            break;
9533
 
    }
9534
 
    qemuDomainObjExitMonitorWithDriver(driver, vm);
9535
 
    if (ret < 0)
9536
 
        goto cleanup;
9537
 
 
9538
 
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
9539
 
        virDomainEventPtr event;
9540
 
 
9541
 
        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
9542
 
                                         VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
9543
 
        qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
9544
 
        virDomainAuditStop(vm, "from-snapshot");
9545
 
        /* We already filtered the _HALT flag for persistent domains
9546
 
         * only, so this end job never drops the last reference.  */
9547
 
        ignore_value(qemuDomainObjEndJob(driver, vm));
9548
 
        resume = false;
9549
 
        vm = NULL;
9550
 
        if (event)
9551
 
            qemuDomainEventQueue(driver, event);
9552
 
    }
9553
 
 
9554
 
cleanup:
9555
 
    if (resume && virDomainObjIsActive(vm) &&
9556
 
        qemuProcessStartCPUs(driver, vm, conn,
9557
 
                             VIR_DOMAIN_RUNNING_UNPAUSED,
9558
 
                             QEMU_ASYNC_JOB_NONE) < 0 &&
9559
 
        virGetLastError() == NULL) {
9560
 
        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
9561
 
                        _("resuming after snapshot failed"));
9562
 
    }
9563
 
 
9564
 
    if (vm) {
9565
 
        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0 ||
9566
 
            (persist &&
9567
 
             virDomainSaveConfig(driver->configDir, vm->newDef) < 0))
9568
 
            ret = -1;
9569
 
    }
9570
 
 
9571
 
endjob:
9572
 
    if (vm && (qemuDomainObjEndJob(driver, vm) == 0)) {
9573
 
            /* Only possible if a transient vm quit while our locks were down,
9574
 
             * in which case we don't want to save snapshot metadata.  */
9575
 
            *vmptr = NULL;
9576
 
            ret = -1;
9577
 
    }
9578
 
 
9579
 
    return ret;
9580
 
}
9581
 
 
9582
 
static virDomainSnapshotPtr
9583
 
qemuDomainSnapshotCreateXML(virDomainPtr domain,
9584
 
                            const char *xmlDesc,
9585
 
                            unsigned int flags)
9586
 
{
9587
 
    struct qemud_driver *driver = domain->conn->privateData;
9588
 
    virDomainObjPtr vm = NULL;
9589
 
    char *xml = NULL;
9590
 
    virDomainSnapshotObjPtr snap = NULL;
9591
 
    virDomainSnapshotPtr snapshot = NULL;
9592
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
9593
 
    virDomainSnapshotDefPtr def = NULL;
9594
 
    bool update_current = true;
9595
 
    unsigned int parse_flags = 0;
9596
 
    virDomainSnapshotObjPtr other = NULL;
9597
 
 
9598
 
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
9599
 
                  VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
9600
 
                  VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
9601
 
                  VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
9602
 
                  VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, NULL);
9603
 
 
9604
 
    if (((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
9605
 
         !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
9606
 
        (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA))
9607
 
        update_current = false;
9608
 
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)
9609
 
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
9610
 
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY)
9611
 
        parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
9612
 
 
9613
 
    qemuDriverLock(driver);
9614
 
    virUUIDFormat(domain->uuid, uuidstr);
9615
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
9616
 
    if (!vm) {
9617
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9618
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9619
 
        goto cleanup;
9620
 
    }
9621
 
 
9622
 
    if (qemuProcessAutoDestroyActive(driver, vm)) {
9623
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
9624
 
                        "%s", _("domain is marked for auto destroy"));
9625
 
        goto cleanup;
9626
 
    }
9627
 
    if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
9628
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
9629
 
                        _("cannot halt after transient domain snapshot"));
9630
 
        goto cleanup;
9631
 
    }
9632
 
 
9633
 
    if (!(def = virDomainSnapshotDefParseString(xmlDesc, driver->caps,
9634
 
                                                QEMU_EXPECTED_VIRT_TYPES,
9635
 
                                                parse_flags)))
9636
 
        goto cleanup;
9637
 
 
9638
 
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
9639
 
        /* Prevent circular chains */
9640
 
        if (def->parent) {
9641
 
            if (STREQ(def->name, def->parent)) {
9642
 
                qemuReportError(VIR_ERR_INVALID_ARG,
9643
 
                                _("cannot set snapshot %s as its own parent"),
9644
 
                                def->name);
9645
 
                goto cleanup;
9646
 
            }
9647
 
            other = virDomainSnapshotFindByName(&vm->snapshots, def->parent);
9648
 
            if (!other) {
9649
 
                qemuReportError(VIR_ERR_INVALID_ARG,
9650
 
                                _("parent %s for snapshot %s not found"),
9651
 
                                def->parent, def->name);
9652
 
                goto cleanup;
9653
 
            }
9654
 
            while (other->def->parent) {
9655
 
                if (STREQ(other->def->parent, def->name)) {
9656
 
                    qemuReportError(VIR_ERR_INVALID_ARG,
9657
 
                                    _("parent %s would create cycle to %s"),
9658
 
                                    other->def->name, def->name);
9659
 
                    goto cleanup;
9660
 
                }
9661
 
                other = virDomainSnapshotFindByName(&vm->snapshots,
9662
 
                                                    other->def->parent);
9663
 
                if (!other) {
9664
 
                    VIR_WARN("snapshots are inconsistent for %s",
9665
 
                             vm->def->name);
9666
 
                    break;
9667
 
                }
9668
 
            }
9669
 
        }
9670
 
 
9671
 
        /* Check that any replacement is compatible */
9672
 
        if (def->dom &&
9673
 
            memcmp(def->dom->uuid, domain->uuid, VIR_UUID_BUFLEN)) {
9674
 
            qemuReportError(VIR_ERR_INVALID_ARG,
9675
 
                            _("definition for snapshot %s must use uuid %s"),
9676
 
                            def->name, uuidstr);
9677
 
            goto cleanup;
9678
 
        }
9679
 
        other = virDomainSnapshotFindByName(&vm->snapshots, def->name);
9680
 
        if (other) {
9681
 
            if ((other->def->state == VIR_DOMAIN_RUNNING ||
9682
 
                 other->def->state == VIR_DOMAIN_PAUSED) !=
9683
 
                (def->state == VIR_DOMAIN_RUNNING ||
9684
 
                 def->state == VIR_DOMAIN_PAUSED)) {
9685
 
                qemuReportError(VIR_ERR_INVALID_ARG,
9686
 
                                _("cannot change between online and offline "
9687
 
                                  "snapshot state in snapshot %s"),
9688
 
                                def->name);
9689
 
                goto cleanup;
9690
 
            }
9691
 
            if ((other->def->state == VIR_DOMAIN_DISK_SNAPSHOT) !=
9692
 
                (def->state == VIR_DOMAIN_DISK_SNAPSHOT)) {
9693
 
                qemuReportError(VIR_ERR_INVALID_ARG,
9694
 
                                _("cannot change between disk snapshot and "
9695
 
                                  "system checkpoint in snapshot %s"),
9696
 
                                def->name);
9697
 
                goto cleanup;
9698
 
            }
9699
 
            if (other->def->dom) {
9700
 
                if (def->dom) {
9701
 
                    if (!virDomainDefCheckABIStability(other->def->dom,
9702
 
                                                       def->dom))
9703
 
                        goto cleanup;
9704
 
                } else {
9705
 
                    /* Transfer the domain def */
9706
 
                    def->dom = other->def->dom;
9707
 
                    other->def->dom = NULL;
9708
 
                }
9709
 
            }
9710
 
            if (other == vm->current_snapshot) {
9711
 
                update_current = true;
9712
 
                vm->current_snapshot = NULL;
9713
 
            }
9714
 
            /* Drop and rebuild the parent relationship, but keep all
9715
 
             * child relations by reusing snap.  */
9716
 
            virDomainSnapshotDropParent(&vm->snapshots, other);
9717
 
            virDomainSnapshotDefFree(other->def);
9718
 
            other->def = NULL;
9719
 
            snap = other;
9720
 
        }
9721
 
        if (def->state == VIR_DOMAIN_DISK_SNAPSHOT && def->dom) {
9722
 
            if (virDomainSnapshotAlignDisks(def,
9723
 
                                            VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL,
9724
 
                                            false) < 0)
9725
 
                goto cleanup;
9726
 
        }
9727
 
    } else {
9728
 
        /* Easiest way to clone inactive portion of vm->def is via
9729
 
         * conversion in and back out of xml.  */
9730
 
        if (!(xml = virDomainDefFormat(vm->def, (VIR_DOMAIN_XML_INACTIVE |
9731
 
                                                 VIR_DOMAIN_XML_SECURE))) ||
9732
 
            !(def->dom = virDomainDefParseString(driver->caps, xml,
9733
 
                                                 QEMU_EXPECTED_VIRT_TYPES,
9734
 
                                                 VIR_DOMAIN_XML_INACTIVE)))
9735
 
            goto cleanup;
9736
 
 
9737
 
        if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
9738
 
            if (virDomainSnapshotAlignDisks(def,
9739
 
                                            VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL,
9740
 
                                            false) < 0)
9741
 
                goto cleanup;
9742
 
            if (qemuDomainSnapshotDiskPrepare(vm, def) < 0)
9743
 
                goto cleanup;
9744
 
            def->state = VIR_DOMAIN_DISK_SNAPSHOT;
9745
 
        } else {
9746
 
            /* In a perfect world, we would allow qemu to tell us this.
9747
 
             * The problem is that qemu only does this check
9748
 
             * device-by-device; so if you had a domain that booted from a
9749
 
             * large qcow2 device, but had a secondary raw device
9750
 
             * attached, you wouldn't find out that you can't snapshot
9751
 
             * your guest until *after* it had spent the time to snapshot
9752
 
             * the boot device.  This is probably a bug in qemu, but we'll
9753
 
             * work around it here for now.
9754
 
             */
9755
 
            if (!qemuDomainSnapshotIsAllowed(vm))
9756
 
                goto cleanup;
9757
 
            def->state = virDomainObjGetState(vm, NULL);
9758
 
        }
9759
 
    }
9760
 
 
9761
 
    if (snap)
9762
 
        snap->def = def;
9763
 
    else if (!(snap = virDomainSnapshotAssignDef(&vm->snapshots, def)))
9764
 
        goto cleanup;
9765
 
    def = NULL;
9766
 
 
9767
 
    if (update_current)
9768
 
        snap->def->current = true;
9769
 
    if (vm->current_snapshot) {
9770
 
        if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
9771
 
            snap->def->parent = strdup(vm->current_snapshot->def->name);
9772
 
            if (snap->def->parent == NULL) {
9773
 
                virReportOOMError();
9774
 
                goto cleanup;
9775
 
            }
9776
 
        }
9777
 
        if (update_current) {
9778
 
            vm->current_snapshot->def->current = false;
9779
 
            if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
9780
 
                                                driver->snapshotDir) < 0)
9781
 
                goto cleanup;
9782
 
            vm->current_snapshot = NULL;
9783
 
        }
9784
 
    }
9785
 
 
9786
 
    /* actually do the snapshot */
9787
 
    if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
9788
 
        /* XXX Should we validate that the redefined snapshot even
9789
 
         * makes sense, such as checking that qemu-img recognizes the
9790
 
         * snapshot name in at least one of the domain's disks?  */
9791
 
    } else if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
9792
 
        if (!virDomainObjIsActive(vm)) {
9793
 
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9794
 
                            _("disk snapshots of inactive domains not "
9795
 
                              "implemented yet"));
9796
 
            goto cleanup;
9797
 
        }
9798
 
        if (qemuDomainSnapshotCreateDiskActive(domain->conn, driver,
9799
 
                                               &vm, snap, flags) < 0)
9800
 
            goto cleanup;
9801
 
    } else if (!virDomainObjIsActive(vm)) {
9802
 
        if (qemuDomainSnapshotCreateInactive(driver, vm, snap) < 0)
9803
 
            goto cleanup;
9804
 
    } else {
9805
 
        if (qemuDomainSnapshotCreateActive(domain->conn, driver,
9806
 
                                           &vm, snap, flags) < 0)
9807
 
            goto cleanup;
9808
 
    }
9809
 
 
9810
 
    /* If we fail after this point, there's not a whole lot we can
9811
 
     * do; we've successfully taken the snapshot, and we are now running
9812
 
     * on it, so we have to go forward the best we can
9813
 
     */
9814
 
    snapshot = virGetDomainSnapshot(domain, snap->def->name);
9815
 
 
9816
 
cleanup:
9817
 
    if (vm) {
9818
 
        if (snapshot && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
9819
 
            if (qemuDomainSnapshotWriteMetadata(vm, snap,
9820
 
                                                driver->snapshotDir) < 0) {
9821
 
                VIR_WARN("unable to save metadata for snapshot %s",
9822
 
                         snap->def->name);
9823
 
            } else {
9824
 
                if (update_current)
9825
 
                    vm->current_snapshot = snap;
9826
 
                if (snap->def->parent) {
9827
 
                    other = virDomainSnapshotFindByName(&vm->snapshots,
9828
 
                                                        snap->def->parent);
9829
 
                    snap->parent = other;
9830
 
                    other->nchildren++;
9831
 
                    snap->sibling = other->first_child;
9832
 
                    other->first_child = snap;
9833
 
                } else {
9834
 
                    vm->snapshots.nroots++;
9835
 
                    snap->sibling = vm->snapshots.first_root;
9836
 
                    vm->snapshots.first_root = snap;
9837
 
                }
9838
 
            }
9839
 
        } else if (snap) {
9840
 
            virDomainSnapshotObjListRemove(&vm->snapshots, snap);
9841
 
        }
9842
 
        virDomainObjUnlock(vm);
9843
 
    }
9844
 
    virDomainSnapshotDefFree(def);
9845
 
    VIR_FREE(xml);
9846
 
    qemuDriverUnlock(driver);
9847
 
    return snapshot;
9848
 
}
9849
 
 
9850
 
static int qemuDomainSnapshotListNames(virDomainPtr domain, char **names,
9851
 
                                       int nameslen,
9852
 
                                       unsigned int flags)
9853
 
{
9854
 
    struct qemud_driver *driver = domain->conn->privateData;
9855
 
    virDomainObjPtr vm = NULL;
9856
 
    int n = -1;
9857
 
 
9858
 
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
9859
 
                  VIR_DOMAIN_SNAPSHOT_LIST_METADATA |
9860
 
                  VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, -1);
9861
 
 
9862
 
    qemuDriverLock(driver);
9863
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
9864
 
    if (!vm) {
9865
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
9866
 
        virUUIDFormat(domain->uuid, uuidstr);
9867
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9868
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9869
 
        goto cleanup;
9870
 
    }
9871
 
 
9872
 
    n = virDomainSnapshotObjListGetNames(&vm->snapshots, names, nameslen,
9873
 
                                         flags);
9874
 
 
9875
 
cleanup:
9876
 
    if (vm)
9877
 
        virDomainObjUnlock(vm);
9878
 
    qemuDriverUnlock(driver);
9879
 
    return n;
9880
 
}
9881
 
 
9882
 
static int qemuDomainSnapshotNum(virDomainPtr domain,
9883
 
                                 unsigned int flags)
9884
 
{
9885
 
    struct qemud_driver *driver = domain->conn->privateData;
9886
 
    virDomainObjPtr vm = NULL;
9887
 
    int n = -1;
9888
 
 
9889
 
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
9890
 
                  VIR_DOMAIN_SNAPSHOT_LIST_METADATA |
9891
 
                  VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, -1);
9892
 
 
9893
 
    qemuDriverLock(driver);
9894
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
9895
 
    if (!vm) {
9896
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
9897
 
        virUUIDFormat(domain->uuid, uuidstr);
9898
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9899
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9900
 
        goto cleanup;
9901
 
    }
9902
 
 
9903
 
    /* All qemu snapshots have libvirt metadata, so
9904
 
     * VIR_DOMAIN_SNAPSHOT_LIST_METADATA makes no difference to our
9905
 
     * answer.  */
9906
 
 
9907
 
    n = virDomainSnapshotObjListNum(&vm->snapshots, flags);
9908
 
 
9909
 
cleanup:
9910
 
    if (vm)
9911
 
        virDomainObjUnlock(vm);
9912
 
    qemuDriverUnlock(driver);
9913
 
    return n;
9914
 
}
9915
 
 
9916
 
static int
9917
 
qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
9918
 
                                    char **names,
9919
 
                                    int nameslen,
9920
 
                                    unsigned int flags)
9921
 
{
9922
 
    struct qemud_driver *driver = snapshot->domain->conn->privateData;
9923
 
    virDomainObjPtr vm = NULL;
9924
 
    virDomainSnapshotObjPtr snap = NULL;
9925
 
    int n = -1;
9926
 
 
9927
 
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
9928
 
                  VIR_DOMAIN_SNAPSHOT_LIST_METADATA |
9929
 
                  VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, -1);
9930
 
 
9931
 
    qemuDriverLock(driver);
9932
 
    vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
9933
 
    if (!vm) {
9934
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
9935
 
        virUUIDFormat(snapshot->domain->uuid, uuidstr);
9936
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9937
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9938
 
        goto cleanup;
9939
 
    }
9940
 
 
9941
 
    snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
9942
 
    if (!snap) {
9943
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
9944
 
                        _("no domain snapshot with matching name '%s'"),
9945
 
                        snapshot->name);
9946
 
        goto cleanup;
9947
 
    }
9948
 
 
9949
 
    n = virDomainSnapshotObjListGetNamesFrom(snap, names, nameslen, flags);
9950
 
 
9951
 
cleanup:
9952
 
    if (vm)
9953
 
        virDomainObjUnlock(vm);
9954
 
    qemuDriverUnlock(driver);
9955
 
    return n;
9956
 
}
9957
 
 
9958
 
static int
9959
 
qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
9960
 
                              unsigned int flags)
9961
 
{
9962
 
    struct qemud_driver *driver = snapshot->domain->conn->privateData;
9963
 
    virDomainObjPtr vm = NULL;
9964
 
    virDomainSnapshotObjPtr snap = NULL;
9965
 
    int n = -1;
9966
 
 
9967
 
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
9968
 
                  VIR_DOMAIN_SNAPSHOT_LIST_METADATA |
9969
 
                  VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, -1);
9970
 
 
9971
 
    qemuDriverLock(driver);
9972
 
    vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
9973
 
    if (!vm) {
9974
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
9975
 
        virUUIDFormat(snapshot->domain->uuid, uuidstr);
9976
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
9977
 
                        _("no domain with matching uuid '%s'"), uuidstr);
9978
 
        goto cleanup;
9979
 
    }
9980
 
 
9981
 
    snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
9982
 
    if (!snap) {
9983
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
9984
 
                        _("no domain snapshot with matching name '%s'"),
9985
 
                        snapshot->name);
9986
 
        goto cleanup;
9987
 
    }
9988
 
 
9989
 
    /* All qemu snapshots have libvirt metadata, so
9990
 
     * VIR_DOMAIN_SNAPSHOT_LIST_METADATA makes no difference to our
9991
 
     * answer.  */
9992
 
 
9993
 
    n = virDomainSnapshotObjListNumFrom(snap, flags);
9994
 
 
9995
 
cleanup:
9996
 
    if (vm)
9997
 
        virDomainObjUnlock(vm);
9998
 
    qemuDriverUnlock(driver);
9999
 
    return n;
10000
 
}
10001
 
 
10002
 
static virDomainSnapshotPtr qemuDomainSnapshotLookupByName(virDomainPtr domain,
10003
 
                                                           const char *name,
10004
 
                                                           unsigned int flags)
10005
 
{
10006
 
    struct qemud_driver *driver = domain->conn->privateData;
10007
 
    virDomainObjPtr vm;
10008
 
    virDomainSnapshotObjPtr snap = NULL;
10009
 
    virDomainSnapshotPtr snapshot = NULL;
10010
 
 
10011
 
    virCheckFlags(0, NULL);
10012
 
 
10013
 
    qemuDriverLock(driver);
10014
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
10015
 
    if (!vm) {
10016
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
10017
 
        virUUIDFormat(domain->uuid, uuidstr);
10018
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10019
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10020
 
        goto cleanup;
10021
 
    }
10022
 
 
10023
 
    snap = virDomainSnapshotFindByName(&vm->snapshots, name);
10024
 
    if (!snap) {
10025
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
10026
 
                        _("no snapshot with matching name '%s'"), name);
10027
 
        goto cleanup;
10028
 
    }
10029
 
 
10030
 
    snapshot = virGetDomainSnapshot(domain, snap->def->name);
10031
 
 
10032
 
cleanup:
10033
 
    if (vm)
10034
 
        virDomainObjUnlock(vm);
10035
 
    qemuDriverUnlock(driver);
10036
 
    return snapshot;
10037
 
}
10038
 
 
10039
 
static int qemuDomainHasCurrentSnapshot(virDomainPtr domain,
10040
 
                                        unsigned int flags)
10041
 
{
10042
 
    struct qemud_driver *driver = domain->conn->privateData;
10043
 
    virDomainObjPtr vm;
10044
 
    int ret = -1;
10045
 
 
10046
 
    virCheckFlags(0, -1);
10047
 
 
10048
 
    qemuDriverLock(driver);
10049
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
10050
 
    if (!vm) {
10051
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
10052
 
        virUUIDFormat(domain->uuid, uuidstr);
10053
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10054
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10055
 
        goto cleanup;
10056
 
    }
10057
 
 
10058
 
    ret = (vm->current_snapshot != NULL);
10059
 
 
10060
 
cleanup:
10061
 
    if (vm)
10062
 
        virDomainObjUnlock(vm);
10063
 
    qemuDriverUnlock(driver);
10064
 
    return ret;
10065
 
}
10066
 
 
10067
 
static virDomainSnapshotPtr
10068
 
qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
10069
 
                            unsigned int flags)
10070
 
{
10071
 
    struct qemud_driver *driver = snapshot->domain->conn->privateData;
10072
 
    virDomainObjPtr vm;
10073
 
    virDomainSnapshotObjPtr snap = NULL;
10074
 
    virDomainSnapshotPtr parent = NULL;
10075
 
 
10076
 
    virCheckFlags(0, NULL);
10077
 
 
10078
 
    qemuDriverLock(driver);
10079
 
    vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
10080
 
    if (!vm) {
10081
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
10082
 
        virUUIDFormat(snapshot->domain->uuid, uuidstr);
10083
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10084
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10085
 
        goto cleanup;
10086
 
    }
10087
 
 
10088
 
    snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
10089
 
    if (!snap) {
10090
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
10091
 
                        _("no domain snapshot with matching name '%s'"),
10092
 
                        snapshot->name);
10093
 
        goto cleanup;
10094
 
    }
10095
 
 
10096
 
    if (!snap->def->parent) {
10097
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
10098
 
                        _("snapshot '%s' does not have a parent"),
10099
 
                        snap->def->name);
10100
 
        goto cleanup;
10101
 
    }
10102
 
 
10103
 
    parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent);
10104
 
 
10105
 
cleanup:
10106
 
    if (vm)
10107
 
        virDomainObjUnlock(vm);
10108
 
    qemuDriverUnlock(driver);
10109
 
    return parent;
10110
 
}
10111
 
 
10112
 
static virDomainSnapshotPtr qemuDomainSnapshotCurrent(virDomainPtr domain,
10113
 
                                                      unsigned int flags)
10114
 
{
10115
 
    struct qemud_driver *driver = domain->conn->privateData;
10116
 
    virDomainObjPtr vm;
10117
 
    virDomainSnapshotPtr snapshot = NULL;
10118
 
 
10119
 
    virCheckFlags(0, NULL);
10120
 
 
10121
 
    qemuDriverLock(driver);
10122
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
10123
 
    if (!vm) {
10124
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
10125
 
        virUUIDFormat(domain->uuid, uuidstr);
10126
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10127
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10128
 
        goto cleanup;
10129
 
    }
10130
 
 
10131
 
    if (!vm->current_snapshot) {
10132
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
10133
 
                        _("the domain does not have a current snapshot"));
10134
 
        goto cleanup;
10135
 
    }
10136
 
 
10137
 
    snapshot = virGetDomainSnapshot(domain, vm->current_snapshot->def->name);
10138
 
 
10139
 
cleanup:
10140
 
    if (vm)
10141
 
        virDomainObjUnlock(vm);
10142
 
    qemuDriverUnlock(driver);
10143
 
    return snapshot;
10144
 
}
10145
 
 
10146
 
static char *qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
10147
 
                                          unsigned int flags)
10148
 
{
10149
 
    struct qemud_driver *driver = snapshot->domain->conn->privateData;
10150
 
    virDomainObjPtr vm = NULL;
10151
 
    char *xml = NULL;
10152
 
    virDomainSnapshotObjPtr snap = NULL;
10153
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
10154
 
 
10155
 
    virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);
10156
 
 
10157
 
    qemuDriverLock(driver);
10158
 
    virUUIDFormat(snapshot->domain->uuid, uuidstr);
10159
 
    vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
10160
 
    if (!vm) {
10161
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10162
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10163
 
        goto cleanup;
10164
 
    }
10165
 
 
10166
 
    snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
10167
 
    if (!snap) {
10168
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
10169
 
                        _("no domain snapshot with matching name '%s'"),
10170
 
                        snapshot->name);
10171
 
        goto cleanup;
10172
 
    }
10173
 
 
10174
 
    xml = virDomainSnapshotDefFormat(uuidstr, snap->def, flags, 0);
10175
 
 
10176
 
cleanup:
10177
 
    if (vm)
10178
 
        virDomainObjUnlock(vm);
10179
 
    qemuDriverUnlock(driver);
10180
 
    return xml;
10181
 
}
10182
 
 
10183
 
/* The domain is expected to be locked and inactive. */
10184
 
static int
10185
 
qemuDomainSnapshotRevertInactive(struct qemud_driver *driver,
10186
 
                                 virDomainObjPtr vm,
10187
 
                                 virDomainSnapshotObjPtr snap)
10188
 
{
10189
 
    /* Try all disks, but report failure if we skipped any.  */
10190
 
    int ret = qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-a", true);
10191
 
    return ret > 0 ? -1 : ret;
10192
 
}
10193
 
 
10194
 
static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
10195
 
                                      unsigned int flags)
10196
 
{
10197
 
    struct qemud_driver *driver = snapshot->domain->conn->privateData;
10198
 
    virDomainObjPtr vm = NULL;
10199
 
    int ret = -1;
10200
 
    virDomainSnapshotObjPtr snap = NULL;
10201
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
10202
 
    virDomainEventPtr event = NULL;
10203
 
    virDomainEventPtr event2 = NULL;
10204
 
    int detail;
10205
 
    qemuDomainObjPrivatePtr priv;
10206
 
    int rc;
10207
 
    virDomainDefPtr config = NULL;
10208
 
 
10209
 
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
10210
 
                  VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
10211
 
                  VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, -1);
10212
 
 
10213
 
    /* We have the following transitions, which create the following events:
10214
 
     * 1. inactive -> inactive: none
10215
 
     * 2. inactive -> running:  EVENT_STARTED
10216
 
     * 3. inactive -> paused:   EVENT_STARTED, EVENT_PAUSED
10217
 
     * 4. running  -> inactive: EVENT_STOPPED
10218
 
     * 5. running  -> running:  none
10219
 
     * 6. running  -> paused:   EVENT_PAUSED
10220
 
     * 7. paused   -> inactive: EVENT_STOPPED
10221
 
     * 8. paused   -> running:  EVENT_RESUMED
10222
 
     * 9. paused   -> paused:   none
10223
 
     * Also, several transitions occur even if we fail partway through,
10224
 
     * and use of FORCE can cause multiple transitions.
10225
 
     */
10226
 
 
10227
 
    qemuDriverLock(driver);
10228
 
    virUUIDFormat(snapshot->domain->uuid, uuidstr);
10229
 
    vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
10230
 
    if (!vm) {
10231
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10232
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10233
 
        goto cleanup;
10234
 
    }
10235
 
 
10236
 
    snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
10237
 
    if (!snap) {
10238
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
10239
 
                        _("no domain snapshot with matching name '%s'"),
10240
 
                        snapshot->name);
10241
 
        goto cleanup;
10242
 
    }
10243
 
 
10244
 
    if (!vm->persistent &&
10245
 
        snap->def->state != VIR_DOMAIN_RUNNING &&
10246
 
        snap->def->state != VIR_DOMAIN_PAUSED &&
10247
 
        (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
10248
 
                  VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) == 0) {
10249
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
10250
 
                        _("transient domain needs to request run or pause "
10251
 
                          "to revert to inactive snapshot"));
10252
 
        goto cleanup;
10253
 
    }
10254
 
    if (snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT) {
10255
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10256
 
                        _("revert to external disk snapshot not supported "
10257
 
                          "yet"));
10258
 
        goto cleanup;
10259
 
    }
10260
 
    if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
10261
 
        if (!snap->def->dom) {
10262
 
            qemuReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
10263
 
                            _("snapshot '%s' lacks domain '%s' rollback info"),
10264
 
                            snap->def->name, vm->def->name);
10265
 
            goto cleanup;
10266
 
        }
10267
 
        if (virDomainObjIsActive(vm) &&
10268
 
            !(snap->def->state == VIR_DOMAIN_RUNNING
10269
 
              || snap->def->state == VIR_DOMAIN_PAUSED) &&
10270
 
            (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
10271
 
                      VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
10272
 
            qemuReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
10273
 
                            _("must respawn qemu to start inactive snapshot"));
10274
 
            goto cleanup;
10275
 
        }
10276
 
    }
10277
 
 
10278
 
 
10279
 
    if (vm->current_snapshot) {
10280
 
        vm->current_snapshot->def->current = false;
10281
 
        if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
10282
 
                                            driver->snapshotDir) < 0)
10283
 
            goto cleanup;
10284
 
        vm->current_snapshot = NULL;
10285
 
        /* XXX Should we restore vm->current_snapshot after this point
10286
 
         * in the failure cases where we know there was no change?  */
10287
 
    }
10288
 
 
10289
 
    /* Prepare to copy the snapshot inactive xml as the config of this
10290
 
     * domain.  Easiest way is by a round trip through xml.
10291
 
     *
10292
 
     * XXX Should domain snapshots track live xml rather
10293
 
     * than inactive xml?  */
10294
 
    snap->def->current = true;
10295
 
    if (snap->def->dom) {
10296
 
        char *xml;
10297
 
        if (!(xml = virDomainDefFormat(snap->def->dom,
10298
 
                                       (VIR_DOMAIN_XML_INACTIVE |
10299
 
                                        VIR_DOMAIN_XML_SECURE))))
10300
 
            goto cleanup;
10301
 
        config = virDomainDefParseString(driver->caps, xml,
10302
 
                                         QEMU_EXPECTED_VIRT_TYPES,
10303
 
                                         VIR_DOMAIN_XML_INACTIVE);
10304
 
        VIR_FREE(xml);
10305
 
        if (!config)
10306
 
            goto cleanup;
10307
 
    }
10308
 
 
10309
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
10310
 
        goto cleanup;
10311
 
 
10312
 
    if (snap->def->state == VIR_DOMAIN_RUNNING
10313
 
        || snap->def->state == VIR_DOMAIN_PAUSED) {
10314
 
        /* Transitions 2, 3, 5, 6, 8, 9 */
10315
 
        bool was_running = false;
10316
 
        bool was_stopped = false;
10317
 
 
10318
 
        /* When using the loadvm monitor command, qemu does not know
10319
 
         * whether to pause or run the reverted domain, and just stays
10320
 
         * in the same state as before the monitor command, whether
10321
 
         * that is paused or running.  We always pause before loadvm,
10322
 
         * to have finer control.  */
10323
 
        if (virDomainObjIsActive(vm)) {
10324
 
            /* Transitions 5, 6, 8, 9 */
10325
 
            /* Check for ABI compatibility.  */
10326
 
            if (config && !virDomainDefCheckABIStability(vm->def, config)) {
10327
 
                virErrorPtr err = virGetLastError();
10328
 
 
10329
 
                if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
10330
 
                    /* Re-spawn error using correct category. */
10331
 
                    if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
10332
 
                        qemuReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
10333
 
                                        err->str2);
10334
 
                    goto endjob;
10335
 
                }
10336
 
                virResetError(err);
10337
 
                qemuProcessStop(driver, vm, 0,
10338
 
                                VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
10339
 
                virDomainAuditStop(vm, "from-snapshot");
10340
 
                detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
10341
 
                event = virDomainEventNewFromObj(vm,
10342
 
                                                 VIR_DOMAIN_EVENT_STOPPED,
10343
 
                                                 detail);
10344
 
                if (event)
10345
 
                    qemuDomainEventQueue(driver, event);
10346
 
                goto load;
10347
 
            }
10348
 
 
10349
 
            priv = vm->privateData;
10350
 
            if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
10351
 
                /* Transitions 5, 6 */
10352
 
                was_running = true;
10353
 
                if (qemuProcessStopCPUs(driver, vm,
10354
 
                                        VIR_DOMAIN_PAUSED_FROM_SNAPSHOT,
10355
 
                                        QEMU_ASYNC_JOB_NONE) < 0)
10356
 
                    goto endjob;
10357
 
                /* Create an event now in case the restore fails, so
10358
 
                 * that user will be alerted that they are now paused.
10359
 
                 * If restore later succeeds, we might replace this. */
10360
 
                detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
10361
 
                event = virDomainEventNewFromObj(vm,
10362
 
                                                 VIR_DOMAIN_EVENT_SUSPENDED,
10363
 
                                                 detail);
10364
 
                if (!virDomainObjIsActive(vm)) {
10365
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10366
 
                                    _("guest unexpectedly quit"));
10367
 
                    goto endjob;
10368
 
                }
10369
 
            }
10370
 
            qemuDomainObjEnterMonitorWithDriver(driver, vm);
10371
 
            rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name);
10372
 
            qemuDomainObjExitMonitorWithDriver(driver, vm);
10373
 
            if (rc < 0) {
10374
 
                /* XXX resume domain if it was running before the
10375
 
                 * failed loadvm attempt? */
10376
 
                goto endjob;
10377
 
            }
10378
 
            if (config)
10379
 
                virDomainObjAssignDef(vm, config, false);
10380
 
        } else {
10381
 
            /* Transitions 2, 3 */
10382
 
        load:
10383
 
            was_stopped = true;
10384
 
            if (config)
10385
 
                virDomainObjAssignDef(vm, config, false);
10386
 
 
10387
 
            rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
10388
 
                                  true, false, -1, NULL, snap,
10389
 
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE);
10390
 
            virDomainAuditStart(vm, "from-snapshot", rc >= 0);
10391
 
            detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
10392
 
            event = virDomainEventNewFromObj(vm,
10393
 
                                             VIR_DOMAIN_EVENT_STARTED,
10394
 
                                             detail);
10395
 
            if (rc < 0)
10396
 
                goto endjob;
10397
 
        }
10398
 
 
10399
 
        /* Touch up domain state.  */
10400
 
        if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
10401
 
            (snap->def->state == VIR_DOMAIN_PAUSED ||
10402
 
             (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
10403
 
            /* Transitions 3, 6, 9 */
10404
 
            virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
10405
 
                                 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
10406
 
            if (was_stopped) {
10407
 
                /* Transition 3, use event as-is and add event2 */
10408
 
                detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
10409
 
                event2 = virDomainEventNewFromObj(vm,
10410
 
                                                  VIR_DOMAIN_EVENT_SUSPENDED,
10411
 
                                                  detail);
10412
 
            } /* else transition 6 and 9 use event as-is */
10413
 
        } else {
10414
 
            /* Transitions 2, 5, 8 */
10415
 
            if (!virDomainObjIsActive(vm)) {
10416
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10417
 
                                _("guest unexpectedly quit"));
10418
 
                goto endjob;
10419
 
            }
10420
 
            rc = qemuProcessStartCPUs(driver, vm, snapshot->domain->conn,
10421
 
                                      VIR_DOMAIN_RUNNING_FROM_SNAPSHOT,
10422
 
                                      QEMU_ASYNC_JOB_NONE);
10423
 
            if (rc < 0)
10424
 
                goto endjob;
10425
 
            virDomainEventFree(event);
10426
 
            event = NULL;
10427
 
            if (was_stopped) {
10428
 
                /* Transition 2 */
10429
 
                detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
10430
 
                event = virDomainEventNewFromObj(vm,
10431
 
                                                 VIR_DOMAIN_EVENT_STARTED,
10432
 
                                                 detail);
10433
 
            } else if (was_running) {
10434
 
                /* Transition 8 */
10435
 
                detail = VIR_DOMAIN_EVENT_RESUMED;
10436
 
                event = virDomainEventNewFromObj(vm,
10437
 
                                                 VIR_DOMAIN_EVENT_RESUMED,
10438
 
                                                 detail);
10439
 
            }
10440
 
        }
10441
 
    } else {
10442
 
        /* Transitions 1, 4, 7 */
10443
 
        /* Newer qemu -loadvm refuses to revert to the state of a snapshot
10444
 
         * created by qemu-img snapshot -c.  If the domain is running, we
10445
 
         * must take it offline; then do the revert using qemu-img.
10446
 
         */
10447
 
 
10448
 
        if (virDomainObjIsActive(vm)) {
10449
 
            /* Transitions 4, 7 */
10450
 
            qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
10451
 
            virDomainAuditStop(vm, "from-snapshot");
10452
 
            detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
10453
 
            event = virDomainEventNewFromObj(vm,
10454
 
                                             VIR_DOMAIN_EVENT_STOPPED,
10455
 
                                             detail);
10456
 
        }
10457
 
 
10458
 
        if (qemuDomainSnapshotRevertInactive(driver, vm, snap) < 0) {
10459
 
            if (!vm->persistent) {
10460
 
                if (qemuDomainObjEndJob(driver, vm) > 0)
10461
 
                    qemuDomainRemoveInactive(driver, vm);
10462
 
                vm = NULL;
10463
 
                goto cleanup;
10464
 
            }
10465
 
            goto endjob;
10466
 
        }
10467
 
        if (config)
10468
 
            virDomainObjAssignDef(vm, config, false);
10469
 
 
10470
 
        if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
10471
 
                     VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
10472
 
            /* Flush first event, now do transition 2 or 3 */
10473
 
            bool paused = (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED) != 0;
10474
 
 
10475
 
            if (event)
10476
 
                qemuDomainEventQueue(driver, event);
10477
 
            rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
10478
 
                                  paused, false, -1, NULL, NULL,
10479
 
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE);
10480
 
            virDomainAuditStart(vm, "from-snapshot", rc >= 0);
10481
 
            if (rc < 0) {
10482
 
                if (!vm->persistent) {
10483
 
                    if (qemuDomainObjEndJob(driver, vm) > 0)
10484
 
                        qemuDomainRemoveInactive(driver, vm);
10485
 
                    vm = NULL;
10486
 
                    goto cleanup;
10487
 
                }
10488
 
                goto endjob;
10489
 
            }
10490
 
            detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
10491
 
            event = virDomainEventNewFromObj(vm,
10492
 
                                             VIR_DOMAIN_EVENT_STARTED,
10493
 
                                             detail);
10494
 
            if (paused) {
10495
 
                detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
10496
 
                event2 = virDomainEventNewFromObj(vm,
10497
 
                                                  VIR_DOMAIN_EVENT_SUSPENDED,
10498
 
                                                  detail);
10499
 
            }
10500
 
        }
10501
 
    }
10502
 
 
10503
 
    ret = 0;
10504
 
 
10505
 
endjob:
10506
 
    if (vm && qemuDomainObjEndJob(driver, vm) == 0)
10507
 
        vm = NULL;
10508
 
 
10509
 
cleanup:
10510
 
    if (vm && ret == 0) {
10511
 
        if (qemuDomainSnapshotWriteMetadata(vm, snap,
10512
 
                                            driver->snapshotDir) < 0)
10513
 
            ret = -1;
10514
 
        else
10515
 
            vm->current_snapshot = snap;
10516
 
    } else if (snap) {
10517
 
        snap->def->current = false;
10518
 
    }
10519
 
    if (event) {
10520
 
        qemuDomainEventQueue(driver, event);
10521
 
        if (event2)
10522
 
            qemuDomainEventQueue(driver, event2);
10523
 
    }
10524
 
    if (vm)
10525
 
        virDomainObjUnlock(vm);
10526
 
    qemuDriverUnlock(driver);
10527
 
 
10528
 
    return ret;
10529
 
}
10530
 
 
10531
 
struct snap_reparent {
10532
 
    struct qemud_driver *driver;
10533
 
    virDomainSnapshotObjPtr parent;
10534
 
    virDomainObjPtr vm;
10535
 
    int err;
10536
 
    virDomainSnapshotObjPtr last;
10537
 
};
10538
 
 
10539
 
static void
10540
 
qemuDomainSnapshotReparentChildren(void *payload,
10541
 
                                   const void *name ATTRIBUTE_UNUSED,
10542
 
                                   void *data)
10543
 
{
10544
 
    virDomainSnapshotObjPtr snap = payload;
10545
 
    struct snap_reparent *rep = data;
10546
 
 
10547
 
    if (rep->err < 0) {
10548
 
        return;
10549
 
    }
10550
 
 
10551
 
    VIR_FREE(snap->def->parent);
10552
 
    snap->parent = rep->parent;
10553
 
 
10554
 
    if (rep->parent) {
10555
 
        snap->def->parent = strdup(rep->parent->def->name);
10556
 
 
10557
 
        if (snap->def->parent == NULL) {
10558
 
            virReportOOMError();
10559
 
            rep->err = -1;
10560
 
            return;
10561
 
        }
10562
 
    }
10563
 
 
10564
 
    if (!snap->sibling)
10565
 
        rep->last = snap;
10566
 
 
10567
 
    rep->err = qemuDomainSnapshotWriteMetadata(rep->vm, snap,
10568
 
                                               rep->driver->snapshotDir);
10569
 
}
10570
 
 
10571
 
static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
10572
 
                                    unsigned int flags)
10573
 
{
10574
 
    struct qemud_driver *driver = snapshot->domain->conn->privateData;
10575
 
    virDomainObjPtr vm = NULL;
10576
 
    int ret = -1;
10577
 
    virDomainSnapshotObjPtr snap = NULL;
10578
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
10579
 
    struct qemu_snap_remove rem;
10580
 
    struct snap_reparent rep;
10581
 
    bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);
10582
 
    int external = 0;
10583
 
 
10584
 
    virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
10585
 
                  VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY |
10586
 
                  VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);
10587
 
 
10588
 
    qemuDriverLock(driver);
10589
 
    virUUIDFormat(snapshot->domain->uuid, uuidstr);
10590
 
    vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
10591
 
    if (!vm) {
10592
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10593
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10594
 
        goto cleanup;
10595
 
    }
10596
 
 
10597
 
    snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
10598
 
    if (!snap) {
10599
 
        qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
10600
 
                        _("no domain snapshot with matching name '%s'"),
10601
 
                        snapshot->name);
10602
 
        goto cleanup;
10603
 
    }
10604
 
 
10605
 
    if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY)) {
10606
 
        if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
10607
 
            snap->def->state == VIR_DOMAIN_DISK_SNAPSHOT)
10608
 
            external++;
10609
 
        if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN)
10610
 
            virDomainSnapshotForEachDescendant(snap,
10611
 
                                               qemuDomainSnapshotCountExternal,
10612
 
                                               &external);
10613
 
        if (external) {
10614
 
            qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10615
 
                            _("deletion of %d external disk snapshots not "
10616
 
                              "supported yet"), external);
10617
 
            goto cleanup;
10618
 
        }
10619
 
    }
10620
 
 
10621
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
10622
 
        goto cleanup;
10623
 
 
10624
 
    if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
10625
 
                 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
10626
 
        rem.driver = driver;
10627
 
        rem.vm = vm;
10628
 
        rem.metadata_only = metadata_only;
10629
 
        rem.err = 0;
10630
 
        rem.current = false;
10631
 
        virDomainSnapshotForEachDescendant(snap,
10632
 
                                           qemuDomainSnapshotDiscardAll,
10633
 
                                           &rem);
10634
 
        if (rem.err < 0)
10635
 
            goto endjob;
10636
 
        if (rem.current) {
10637
 
            if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
10638
 
                snap->def->current = true;
10639
 
                if (qemuDomainSnapshotWriteMetadata(vm, snap,
10640
 
                                                    driver->snapshotDir) < 0) {
10641
 
                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
10642
 
                                    _("failed to set snapshot '%s' as current"),
10643
 
                                    snap->def->name);
10644
 
                    snap->def->current = false;
10645
 
                    goto endjob;
10646
 
                }
10647
 
            }
10648
 
            vm->current_snapshot = snap;
10649
 
        }
10650
 
    } else if (snap->nchildren) {
10651
 
        rep.driver = driver;
10652
 
        rep.parent = snap->parent;
10653
 
        rep.vm = vm;
10654
 
        rep.err = 0;
10655
 
        rep.last = NULL;
10656
 
        virDomainSnapshotForEachChild(snap,
10657
 
                                      qemuDomainSnapshotReparentChildren,
10658
 
                                      &rep);
10659
 
        if (rep.err < 0)
10660
 
            goto endjob;
10661
 
        /* Can't modify siblings during ForEachChild, so do it now.  */
10662
 
        if (snap->parent) {
10663
 
            snap->parent->nchildren += snap->nchildren;
10664
 
            rep.last->sibling = snap->parent->first_child;
10665
 
            snap->parent->first_child = snap->first_child;
10666
 
        } else {
10667
 
            vm->snapshots.nroots += snap->nchildren;
10668
 
            rep.last->sibling = vm->snapshots.first_root;
10669
 
            vm->snapshots.first_root = snap->first_child;
10670
 
        }
10671
 
    }
10672
 
 
10673
 
    if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
10674
 
        snap->nchildren = 0;
10675
 
        snap->first_child = NULL;
10676
 
        ret = 0;
10677
 
    } else {
10678
 
        virDomainSnapshotDropParent(&vm->snapshots, snap);
10679
 
        ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
10680
 
    }
10681
 
 
10682
 
endjob:
10683
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
10684
 
        vm = NULL;
10685
 
 
10686
 
cleanup:
10687
 
    if (vm)
10688
 
        virDomainObjUnlock(vm);
10689
 
    qemuDriverUnlock(driver);
10690
 
    return ret;
10691
 
}
10692
 
 
10693
 
static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd,
10694
 
                                    char **result, unsigned int flags)
10695
 
{
10696
 
    struct qemud_driver *driver = domain->conn->privateData;
10697
 
    virDomainObjPtr vm = NULL;
10698
 
    int ret = -1;
10699
 
    qemuDomainObjPrivatePtr priv;
10700
 
    bool hmp;
10701
 
 
10702
 
    virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
10703
 
 
10704
 
    qemuDriverLock(driver);
10705
 
    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
10706
 
    if (!vm) {
10707
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
10708
 
        virUUIDFormat(domain->uuid, uuidstr);
10709
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10710
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10711
 
        goto cleanup;
10712
 
    }
10713
 
 
10714
 
    if (!virDomainObjIsActive(vm)) {
10715
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
10716
 
                        "%s", _("domain is not running"));
10717
 
        goto cleanup;
10718
 
   }
10719
 
 
10720
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
10721
 
        goto cleanup;
10722
 
 
10723
 
    if (!virDomainObjIsActive(vm)) {
10724
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
10725
 
                        _("domain is not running"));
10726
 
        goto endjob;
10727
 
    }
10728
 
 
10729
 
    priv = vm->privateData;
10730
 
 
10731
 
    qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_MONITOR, -1);
10732
 
 
10733
 
    hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);
10734
 
 
10735
 
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
10736
 
    ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
10737
 
    qemuDomainObjExitMonitorWithDriver(driver, vm);
10738
 
 
10739
 
endjob:
10740
 
    if (qemuDomainObjEndJob(driver, vm) == 0) {
10741
 
        vm = NULL;
10742
 
    }
10743
 
 
10744
 
cleanup:
10745
 
    if (vm)
10746
 
        virDomainObjUnlock(vm);
10747
 
    qemuDriverUnlock(driver);
10748
 
    return ret;
10749
 
}
10750
 
 
10751
 
 
10752
 
static virDomainPtr qemuDomainAttach(virConnectPtr conn,
10753
 
                                     unsigned int pid,
10754
 
                                     unsigned int flags)
10755
 
{
10756
 
    struct qemud_driver *driver = conn->privateData;
10757
 
    virDomainObjPtr vm = NULL;
10758
 
    virDomainDefPtr def = NULL;
10759
 
    virDomainPtr dom = NULL;
10760
 
    virDomainChrSourceDefPtr monConfig = NULL;
10761
 
    bool monJSON = false;
10762
 
    char *pidfile = NULL;
10763
 
 
10764
 
    virCheckFlags(0, NULL);
10765
 
 
10766
 
    qemuDriverLock(driver);
10767
 
 
10768
 
    if (!(def = qemuParseCommandLinePid(driver->caps, pid,
10769
 
                                        &pidfile, &monConfig, &monJSON)))
10770
 
        goto cleanup;
10771
 
 
10772
 
    if (!monConfig) {
10773
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10774
 
                        _("No monitor connection for pid %u"),
10775
 
                        pid);
10776
 
        goto cleanup;
10777
 
    }
10778
 
    if (monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
10779
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10780
 
                        _("Cannot connect to monitor connection of type '%s' for pid %u"),
10781
 
                        virDomainChrTypeToString(monConfig->type), pid);
10782
 
        goto cleanup;
10783
 
    }
10784
 
 
10785
 
    if (!(def->name) &&
10786
 
        virAsprintf(&def->name, "attach-pid-%u", pid) < 0) {
10787
 
        virReportOOMError();
10788
 
        goto cleanup;
10789
 
    }
10790
 
 
10791
 
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
10792
 
        goto cleanup;
10793
 
 
10794
 
    if (qemudCanonicalizeMachine(driver, def) < 0)
10795
 
        goto cleanup;
10796
 
 
10797
 
    if (qemuDomainAssignPCIAddresses(def) < 0)
10798
 
        goto cleanup;
10799
 
 
10800
 
    if (!(vm = virDomainAssignDef(driver->caps,
10801
 
                                  &driver->domains,
10802
 
                                  def, false)))
10803
 
        goto cleanup;
10804
 
 
10805
 
    def = NULL;
10806
 
 
10807
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
10808
 
        goto cleanup;
10809
 
 
10810
 
    if (qemuProcessAttach(conn, driver, vm, pid,
10811
 
                          pidfile, monConfig, monJSON) < 0) {
10812
 
        monConfig = NULL;
10813
 
        goto endjob;
10814
 
    }
10815
 
 
10816
 
    monConfig = NULL;
10817
 
 
10818
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
10819
 
    if (dom) dom->id = vm->def->id;
10820
 
 
10821
 
endjob:
10822
 
    if (qemuDomainObjEndJob(driver, vm) == 0) {
10823
 
        vm = NULL;
10824
 
        goto cleanup;
10825
 
    }
10826
 
 
10827
 
cleanup:
10828
 
    virDomainDefFree(def);
10829
 
    virDomainChrSourceDefFree(monConfig);
10830
 
    if (vm)
10831
 
        virDomainObjUnlock(vm);
10832
 
    qemuDriverUnlock(driver);
10833
 
    VIR_FREE(pidfile);
10834
 
    return dom;
10835
 
}
10836
 
 
10837
 
 
10838
 
static int
10839
 
qemuDomainOpenConsole(virDomainPtr dom,
10840
 
                      const char *dev_name,
10841
 
                      virStreamPtr st,
10842
 
                      unsigned int flags)
10843
 
{
10844
 
    struct qemud_driver *driver = dom->conn->privateData;
10845
 
    virDomainObjPtr vm = NULL;
10846
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
10847
 
    int ret = -1;
10848
 
    int i;
10849
 
    virDomainChrDefPtr chr = NULL;
10850
 
 
10851
 
    virCheckFlags(0, -1);
10852
 
 
10853
 
    qemuDriverLock(driver);
10854
 
    virUUIDFormat(dom->uuid, uuidstr);
10855
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
10856
 
    if (!vm) {
10857
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10858
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10859
 
        goto cleanup;
10860
 
    }
10861
 
 
10862
 
    if (!virDomainObjIsActive(vm)) {
10863
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
10864
 
                        "%s", _("domain is not running"));
10865
 
        goto cleanup;
10866
 
    }
10867
 
 
10868
 
    if (dev_name) {
10869
 
        for (i = 0 ; !chr && i < vm->def->nconsoles ; i++) {
10870
 
            if (vm->def->consoles[i]->info.alias &&
10871
 
                STREQ(dev_name, vm->def->consoles[i]->info.alias))
10872
 
                chr = vm->def->consoles[i];
10873
 
        }
10874
 
        for (i = 0 ; !chr && i < vm->def->nserials ; i++) {
10875
 
            if (STREQ(dev_name, vm->def->serials[i]->info.alias))
10876
 
                chr = vm->def->serials[i];
10877
 
        }
10878
 
        for (i = 0 ; !chr && i < vm->def->nparallels ; i++) {
10879
 
            if (STREQ(dev_name, vm->def->parallels[i]->info.alias))
10880
 
                chr = vm->def->parallels[i];
10881
 
        }
10882
 
    } else {
10883
 
        if (vm->def->nconsoles)
10884
 
            chr = vm->def->consoles[0];
10885
 
        else if (vm->def->nserials)
10886
 
            chr = vm->def->serials[0];
10887
 
    }
10888
 
 
10889
 
    if (!chr) {
10890
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
10891
 
                        _("cannot find character device %s"),
10892
 
                        NULLSTR(dev_name));
10893
 
        goto cleanup;
10894
 
    }
10895
 
 
10896
 
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
10897
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
10898
 
                        _("character device %s is not using a PTY"),
10899
 
                        NULLSTR(dev_name));
10900
 
        goto cleanup;
10901
 
    }
10902
 
 
10903
 
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
10904
 
                            0, 0, O_RDWR) < 0)
10905
 
        goto cleanup;
10906
 
 
10907
 
    ret = 0;
10908
 
cleanup:
10909
 
    if (vm)
10910
 
        virDomainObjUnlock(vm);
10911
 
    qemuDriverUnlock(driver);
10912
 
    return ret;
10913
 
}
10914
 
 
10915
 
static char *
10916
 
qemuDiskPathToAlias(virDomainObjPtr vm, const char *path)
10917
 
{
10918
 
    int i;
10919
 
    char *ret = NULL;
10920
 
    virDomainDiskDefPtr disk;
10921
 
 
10922
 
    i = virDomainDiskIndexByName(vm->def, path, true);
10923
 
    if (i < 0)
10924
 
        goto cleanup;
10925
 
 
10926
 
    disk = vm->def->disks[i];
10927
 
 
10928
 
    if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
10929
 
        disk->type != VIR_DOMAIN_DISK_TYPE_FILE)
10930
 
        goto cleanup;
10931
 
 
10932
 
    if (disk->src) {
10933
 
        if (virAsprintf(&ret, "drive-%s", disk->info.alias) < 0) {
10934
 
            virReportOOMError();
10935
 
            return NULL;
10936
 
        }
10937
 
    }
10938
 
 
10939
 
cleanup:
10940
 
    if (!ret) {
10941
 
        qemuReportError(VIR_ERR_INVALID_ARG,
10942
 
                        "%s", _("No device found for specified path"));
10943
 
    }
10944
 
    return ret;
10945
 
}
10946
 
 
10947
 
static int
10948
 
qemuDomainBlockJobImpl(virDomainPtr dom, const char *path,
10949
 
                       unsigned long bandwidth, virDomainBlockJobInfoPtr info,
10950
 
                       int mode)
10951
 
{
10952
 
    struct qemud_driver *driver = dom->conn->privateData;
10953
 
    virDomainObjPtr vm = NULL;
10954
 
    qemuDomainObjPrivatePtr priv;
10955
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
10956
 
    char *device = NULL;
10957
 
    int ret = -1;
10958
 
 
10959
 
    qemuDriverLock(driver);
10960
 
    virUUIDFormat(dom->uuid, uuidstr);
10961
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
10962
 
    if (!vm) {
10963
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
10964
 
                        _("no domain with matching uuid '%s'"), uuidstr);
10965
 
        goto cleanup;
10966
 
    }
10967
 
 
10968
 
    if (!virDomainObjIsActive(vm)) {
10969
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
10970
 
                        "%s", _("domain is not running"));
10971
 
        goto cleanup;
10972
 
    }
10973
 
 
10974
 
    device = qemuDiskPathToAlias(vm, path);
10975
 
    if (!device) {
10976
 
        goto cleanup;
10977
 
    }
10978
 
 
10979
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
10980
 
        goto cleanup;
10981
 
 
10982
 
    if (!virDomainObjIsActive(vm)) {
10983
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
10984
 
                        _("domain is not running"));
10985
 
        goto endjob;
10986
 
    }
10987
 
 
10988
 
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
10989
 
    priv = vm->privateData;
10990
 
    ret = qemuMonitorBlockJob(priv->mon, device, bandwidth, info, mode);
10991
 
    qemuDomainObjExitMonitorWithDriver(driver, vm);
10992
 
 
10993
 
endjob:
10994
 
    if (qemuDomainObjEndJob(driver, vm) == 0) {
10995
 
        vm = NULL;
10996
 
        goto cleanup;
10997
 
    }
10998
 
 
10999
 
cleanup:
11000
 
    VIR_FREE(device);
11001
 
    if (vm)
11002
 
        virDomainObjUnlock(vm);
11003
 
    qemuDriverUnlock(driver);
11004
 
    return ret;
11005
 
}
11006
 
 
11007
 
static int
11008
 
qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags)
11009
 
{
11010
 
    virCheckFlags(0, -1);
11011
 
    return qemuDomainBlockJobImpl(dom, path, 0, NULL, BLOCK_JOB_ABORT);
11012
 
}
11013
 
 
11014
 
static int
11015
 
qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
11016
 
                           virDomainBlockJobInfoPtr info, unsigned int flags)
11017
 
{
11018
 
    virCheckFlags(0, -1);
11019
 
    return qemuDomainBlockJobImpl(dom, path, 0, info, BLOCK_JOB_INFO);
11020
 
}
11021
 
 
11022
 
static int
11023
 
qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
11024
 
                           unsigned long bandwidth, unsigned int flags)
11025
 
{
11026
 
    virCheckFlags(0, -1);
11027
 
    return qemuDomainBlockJobImpl(dom, path, bandwidth, NULL, BLOCK_JOB_SPEED);
11028
 
}
11029
 
 
11030
 
static int
11031
 
qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
11032
 
                    unsigned int flags)
11033
 
{
11034
 
    int ret;
11035
 
 
11036
 
    virCheckFlags(0, -1);
11037
 
    ret = qemuDomainBlockJobImpl(dom, path, bandwidth, NULL, BLOCK_JOB_PULL);
11038
 
    if (ret == 0 && bandwidth != 0)
11039
 
        ret = qemuDomainBlockJobImpl(dom, path, bandwidth, NULL,
11040
 
                                     BLOCK_JOB_SPEED);
11041
 
    return ret;
11042
 
}
11043
 
 
11044
 
static int
11045
 
qemuDomainOpenGraphics(virDomainPtr dom,
11046
 
                       unsigned int idx,
11047
 
                       int fd,
11048
 
                       unsigned int flags)
11049
 
{
11050
 
    struct qemud_driver *driver = dom->conn->privateData;
11051
 
    virDomainObjPtr vm = NULL;
11052
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
11053
 
    int ret = -1;
11054
 
    qemuDomainObjPrivatePtr priv;
11055
 
    const char *protocol;
11056
 
 
11057
 
    virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
11058
 
 
11059
 
    qemuDriverLock(driver);
11060
 
    virUUIDFormat(dom->uuid, uuidstr);
11061
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
11062
 
    if (!vm) {
11063
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
11064
 
                        _("no domain with matching uuid '%s'"), uuidstr);
11065
 
        goto cleanup;
11066
 
    }
11067
 
 
11068
 
    if (!virDomainObjIsActive(vm)) {
11069
 
        qemuReportError(VIR_ERR_OPERATION_INVALID,
11070
 
                        "%s", _("domain is not running"));
11071
 
        goto cleanup;
11072
 
    }
11073
 
 
11074
 
    priv = vm->privateData;
11075
 
 
11076
 
    if (idx >= vm->def->ngraphics) {
11077
 
        qemuReportError(VIR_ERR_INTERNAL_ERROR,
11078
 
                        _("No graphics backend with index %d"), idx);
11079
 
        goto cleanup;
11080
 
    }
11081
 
    switch (vm->def->graphics[idx]->type) {
11082
 
    case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
11083
 
        protocol = "vnc";
11084
 
        break;
11085
 
    case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
11086
 
        protocol = "spice";
11087
 
        break;
11088
 
    default:
11089
 
        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11090
 
                        _("Can only open VNC or SPICE graphics backends, not %s"),
11091
 
                        virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
11092
 
        goto cleanup;
11093
 
    }
11094
 
 
11095
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
11096
 
        goto cleanup;
11097
 
    qemuDomainObjEnterMonitorWithDriver(driver, vm);
11098
 
    ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
11099
 
                                  (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
11100
 
    qemuDomainObjExitMonitorWithDriver(driver, vm);
11101
 
    if (qemuDomainObjEndJob(driver, vm) == 0) {
11102
 
        vm = NULL;
11103
 
        goto cleanup;
11104
 
    }
11105
 
 
11106
 
cleanup:
11107
 
    if (vm)
11108
 
        virDomainObjUnlock(vm);
11109
 
    qemuDriverUnlock(driver);
11110
 
    return ret;
11111
 
}
11112
 
 
11113
 
static int
11114
 
qemuDomainSetBlockIoTune(virDomainPtr dom,
11115
 
                         const char *disk,
11116
 
                         virTypedParameterPtr params,
11117
 
                         int nparams,
11118
 
                         unsigned int flags)
11119
 
{
11120
 
    struct qemud_driver *driver = dom->conn->privateData;
11121
 
    virDomainObjPtr vm = NULL;
11122
 
    qemuDomainObjPrivatePtr priv;
11123
 
    virDomainDefPtr persistentDef = NULL;
11124
 
    virDomainBlockIoTuneInfo info;
11125
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
11126
 
    const char *device = NULL;
11127
 
    int ret = -1;
11128
 
    int i;
11129
 
    bool isActive;
11130
 
    int idx = -1;
11131
 
 
11132
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
11133
 
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
11134
 
 
11135
 
    memset(&info, 0, sizeof(info));
11136
 
 
11137
 
    qemuDriverLock(driver);
11138
 
    virUUIDFormat(dom->uuid, uuidstr);
11139
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
11140
 
    if (!vm) {
11141
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
11142
 
                        _("no domain with matching uuid '%s'"), uuidstr);
11143
 
        goto cleanup;
11144
 
    }
11145
 
 
11146
 
    device = qemuDiskPathToAlias(vm, disk);
11147
 
    if (!device) {
11148
 
        goto cleanup;
11149
 
    }
11150
 
 
11151
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
11152
 
        goto cleanup;
11153
 
 
11154
 
    isActive = virDomainObjIsActive(vm);
11155
 
 
11156
 
    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
11157
 
        if (isActive)
11158
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
11159
 
        else
11160
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
11161
 
    }
11162
 
 
11163
 
    if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
11164
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
11165
 
                        _("domain is not running"));
11166
 
        goto endjob;
11167
 
    }
11168
 
 
11169
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
11170
 
        if (!vm->persistent) {
11171
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
11172
 
                            _("cannot change persistent config of a transient domain"));
11173
 
            goto endjob;
11174
 
        }
11175
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
11176
 
            goto endjob;
11177
 
        idx = virDomainDiskIndexByName(persistentDef, disk, true);
11178
 
        if (idx < 0)
11179
 
            goto endjob;
11180
 
    }
11181
 
 
11182
 
    for (i = 0; i < nparams; i++) {
11183
 
        virTypedParameterPtr param = &params[i];
11184
 
 
11185
 
        if (param->type != VIR_TYPED_PARAM_ULLONG) {
11186
 
            qemuReportError(VIR_ERR_INVALID_ARG,
11187
 
                            _("expected unsigned long long for parameter %s"),
11188
 
                            param->field);
11189
 
            goto endjob;
11190
 
        }
11191
 
 
11192
 
        if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC)) {
11193
 
            info.total_bytes_sec = param->value.ul;
11194
 
        } else if (STREQ(param->field,
11195
 
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC)) {
11196
 
            info.read_bytes_sec = param->value.ul;
11197
 
        } else if (STREQ(param->field,
11198
 
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC)) {
11199
 
            info.write_bytes_sec = param->value.ul;
11200
 
        } else if (STREQ(param->field,
11201
 
                         VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC)) {
11202
 
            info.total_iops_sec = param->value.ul;
11203
 
        } else if (STREQ(param->field,
11204
 
                         VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC)) {
11205
 
            info.read_iops_sec = param->value.ul;
11206
 
        } else if (STREQ(param->field,
11207
 
                         VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC)) {
11208
 
            info.write_iops_sec = param->value.ul;
11209
 
        } else {
11210
 
            qemuReportError(VIR_ERR_INVALID_ARG,
11211
 
                            _("Unrecognized parameter %s"),
11212
 
                            param->field);
11213
 
            goto endjob;
11214
 
        }
11215
 
    }
11216
 
 
11217
 
    if ((info.total_bytes_sec && info.read_bytes_sec) ||
11218
 
        (info.total_bytes_sec && info.write_bytes_sec)) {
11219
 
        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
11220
 
                        _("total and read/write of bytes_sec cannot be set at the same time"));
11221
 
        goto endjob;
11222
 
    }
11223
 
 
11224
 
    if ((info.total_iops_sec && info.read_iops_sec) ||
11225
 
        (info.total_iops_sec && info.write_iops_sec)) {
11226
 
        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
11227
 
                        _("total and read/write of iops_sec cannot be set at the same time"));
11228
 
        goto endjob;
11229
 
    }
11230
 
 
11231
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
11232
 
        priv = vm->privateData;
11233
 
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
11234
 
        ret = qemuMonitorSetBlockIoThrottle(priv->mon, device, &info);
11235
 
        qemuDomainObjExitMonitorWithDriver(driver, vm);
11236
 
        if (ret < 0)
11237
 
            goto endjob;
11238
 
    }
11239
 
 
11240
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
11241
 
        sa_assert(persistentDef && idx >= 0);
11242
 
        persistentDef->disks[idx]->blkdeviotune = info;
11243
 
        ret = virDomainSaveConfig(driver->configDir, persistentDef);
11244
 
        if (ret < 0) {
11245
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
11246
 
                           _("Write to config file failed"));
11247
 
            goto endjob;
11248
 
        }
11249
 
    }
11250
 
 
11251
 
endjob:
11252
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
11253
 
        vm = NULL;
11254
 
 
11255
 
cleanup:
11256
 
    VIR_FREE(device);
11257
 
    if (vm)
11258
 
        virDomainObjUnlock(vm);
11259
 
    qemuDriverUnlock(driver);
11260
 
    return ret;
11261
 
}
11262
 
 
11263
 
static int
11264
 
qemuDomainGetBlockIoTune(virDomainPtr dom,
11265
 
                         const char *disk,
11266
 
                         virTypedParameterPtr params,
11267
 
                         int *nparams,
11268
 
                         unsigned int flags)
11269
 
{
11270
 
    struct qemud_driver *driver = dom->conn->privateData;
11271
 
    virDomainObjPtr vm = NULL;
11272
 
    qemuDomainObjPrivatePtr priv;
11273
 
    virDomainDefPtr persistentDef = NULL;
11274
 
    virDomainBlockIoTuneInfo reply;
11275
 
    char uuidstr[VIR_UUID_STRING_BUFLEN];
11276
 
    const char *device = NULL;
11277
 
    int ret = -1;
11278
 
    int i;
11279
 
    bool isActive;
11280
 
 
11281
 
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
11282
 
                  VIR_DOMAIN_AFFECT_CONFIG |
11283
 
                  VIR_TYPED_PARAM_STRING_OKAY, -1);
11284
 
 
11285
 
    /* We don't return strings, and thus trivially support this flag.  */
11286
 
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
11287
 
 
11288
 
    qemuDriverLock(driver);
11289
 
    virUUIDFormat(dom->uuid, uuidstr);
11290
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
11291
 
    if (!vm) {
11292
 
        qemuReportError(VIR_ERR_NO_DOMAIN,
11293
 
                        _("no domain with matching uuid '%s'"), uuidstr);
11294
 
        goto cleanup;
11295
 
    }
11296
 
 
11297
 
    if ((*nparams) == 0) {
11298
 
        /* Current number of parameters supported by QEMU Block I/O Throttling */
11299
 
        *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM;
11300
 
        ret = 0;
11301
 
        goto cleanup;
11302
 
    }
11303
 
 
11304
 
    device = qemuDiskPathToAlias(vm, disk);
11305
 
 
11306
 
    if (!device) {
11307
 
        goto cleanup;
11308
 
    }
11309
 
 
11310
 
    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
11311
 
        goto cleanup;
11312
 
 
11313
 
    isActive = virDomainObjIsActive(vm);
11314
 
 
11315
 
    if (flags  == VIR_DOMAIN_AFFECT_CURRENT) {
11316
 
        if (isActive)
11317
 
            flags = VIR_DOMAIN_AFFECT_LIVE;
11318
 
        else
11319
 
            flags = VIR_DOMAIN_AFFECT_CONFIG;
11320
 
    }
11321
 
 
11322
 
    if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
11323
 
        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
11324
 
                        _("domain is not running"));
11325
 
        goto endjob;
11326
 
    }
11327
 
 
11328
 
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
11329
 
        priv = vm->privateData;
11330
 
        qemuDomainObjEnterMonitorWithDriver(driver, vm);
11331
 
        ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, &reply);
11332
 
        qemuDomainObjExitMonitorWithDriver(driver, vm);
11333
 
        if (ret < 0)
11334
 
            goto endjob;
11335
 
    }
11336
 
 
11337
 
    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
11338
 
        if (!vm->persistent) {
11339
 
            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
11340
 
                            _("domain is transient"));
11341
 
            goto endjob;
11342
 
        }
11343
 
        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
11344
 
            goto endjob;
11345
 
 
11346
 
        int idx = virDomainDiskIndexByName(vm->def, disk, true);
11347
 
        if (idx < 0)
11348
 
            goto endjob;
11349
 
        reply = persistentDef->disks[idx]->blkdeviotune;
11350
 
    }
11351
 
 
11352
 
    for (i = 0; i < QEMU_NB_BLOCK_IO_TUNE_PARAM && i < *nparams; i++) {
11353
 
        virTypedParameterPtr param = &params[i];
11354
 
        param->value.ul = 0;
11355
 
        param->type = VIR_TYPED_PARAM_ULLONG;
11356
 
 
11357
 
        switch(i) {
11358
 
        case 0:
11359
 
            if (virStrcpyStatic(param->field,
11360
 
                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC) == NULL) {
11361
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
11362
 
                                _("Field name '%s' too long"),
11363
 
                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC);
11364
 
                goto endjob;
11365
 
            }
11366
 
            param->value.ul = reply.total_bytes_sec;
11367
 
            break;
11368
 
 
11369
 
        case 1:
11370
 
            if (virStrcpyStatic(param->field,
11371
 
                                VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC) == NULL) {
11372
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
11373
 
                                _("Field name '%s' too long"),
11374
 
                                VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC);
11375
 
                goto endjob;
11376
 
            }
11377
 
            param->value.ul = reply.read_bytes_sec;
11378
 
            break;
11379
 
 
11380
 
        case 2:
11381
 
            if (virStrcpyStatic(param->field,
11382
 
                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC) == NULL) {
11383
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
11384
 
                                _("Field name '%s' too long"),
11385
 
                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC);
11386
 
                goto endjob;
11387
 
            }
11388
 
            param->value.ul = reply.write_bytes_sec;
11389
 
            break;
11390
 
 
11391
 
        case 3:
11392
 
            if (virStrcpyStatic(param->field,
11393
 
                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC) == NULL) {
11394
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
11395
 
                                _("Field name '%s' too long"),
11396
 
                                VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC);
11397
 
                goto endjob;
11398
 
            }
11399
 
            param->value.ul = reply.total_iops_sec;
11400
 
            break;
11401
 
 
11402
 
        case 4:
11403
 
            if (virStrcpyStatic(param->field,
11404
 
                                VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC) == NULL) {
11405
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
11406
 
                                _("Field name '%s' too long"),
11407
 
                                VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC);
11408
 
                goto endjob;
11409
 
            }
11410
 
            param->value.ul = reply.read_iops_sec;
11411
 
            break;
11412
 
 
11413
 
        case 5:
11414
 
            if (virStrcpyStatic(param->field,
11415
 
                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC) == NULL) {
11416
 
                qemuReportError(VIR_ERR_INTERNAL_ERROR,
11417
 
                                _("Field name '%s' too long"),
11418
 
                                VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC);
11419
 
                goto endjob;
11420
 
            }
11421
 
            param->value.ul = reply.write_iops_sec;
11422
 
            break;
11423
 
        default:
11424
 
            break;
11425
 
        }
11426
 
    }
11427
 
 
11428
 
    if (*nparams > QEMU_NB_BLOCK_IO_TUNE_PARAM)
11429
 
        *nparams = QEMU_NB_BLOCK_IO_TUNE_PARAM;
11430
 
    ret = 0;
11431
 
 
11432
 
endjob:
11433
 
    if (qemuDomainObjEndJob(driver, vm) == 0)
11434
 
        vm = NULL;
11435
 
 
11436
 
cleanup:
11437
 
    VIR_FREE(device);
11438
 
    if (vm)
11439
 
        virDomainObjUnlock(vm);
11440
 
    qemuDriverUnlock(driver);
11441
 
    return ret;
11442
 
}
11443
 
 
11444
 
static virDriver qemuDriver = {
11445
 
    .no = VIR_DRV_QEMU,
11446
 
    .name = "QEMU",
11447
 
    .open = qemudOpen, /* 0.2.0 */
11448
 
    .close = qemudClose, /* 0.2.0 */
11449
 
    .supports_feature = qemudSupportsFeature, /* 0.5.0 */
11450
 
    .type = qemudGetType, /* 0.2.0 */
11451
 
    .version = qemudGetVersion, /* 0.2.0 */
11452
 
    .getHostname = virGetHostname, /* 0.3.3 */
11453
 
    .getSysinfo = qemuGetSysinfo, /* 0.8.8 */
11454
 
    .getMaxVcpus = qemudGetMaxVCPUs, /* 0.2.1 */
11455
 
    .nodeGetInfo = nodeGetInfo, /* 0.2.0 */
11456
 
    .getCapabilities = qemudGetCapabilities, /* 0.2.1 */
11457
 
    .listDomains = qemudListDomains, /* 0.2.0 */
11458
 
    .numOfDomains = qemudNumDomains, /* 0.2.0 */
11459
 
    .domainCreateXML = qemudDomainCreate, /* 0.2.0 */
11460
 
    .domainLookupByID = qemudDomainLookupByID, /* 0.2.0 */
11461
 
    .domainLookupByUUID = qemudDomainLookupByUUID, /* 0.2.0 */
11462
 
    .domainLookupByName = qemudDomainLookupByName, /* 0.2.0 */
11463
 
    .domainSuspend = qemudDomainSuspend, /* 0.2.0 */
11464
 
    .domainResume = qemudDomainResume, /* 0.2.0 */
11465
 
    .domainShutdown = qemuDomainShutdown, /* 0.2.0 */
11466
 
    .domainReboot = qemuDomainReboot, /* 0.9.3 */
11467
 
    .domainReset = qemuDomainReset, /* 0.9.7 */
11468
 
    .domainDestroy = qemuDomainDestroy, /* 0.2.0 */
11469
 
    .domainDestroyFlags = qemuDomainDestroyFlags, /* 0.9.4 */
11470
 
    .domainGetOSType = qemudDomainGetOSType, /* 0.2.2 */
11471
 
    .domainGetMaxMemory = qemudDomainGetMaxMemory, /* 0.4.2 */
11472
 
    .domainSetMaxMemory = qemudDomainSetMaxMemory, /* 0.4.2 */
11473
 
    .domainSetMemory = qemudDomainSetMemory, /* 0.4.2 */
11474
 
    .domainSetMemoryFlags = qemudDomainSetMemoryFlags, /* 0.9.0 */
11475
 
    .domainSetMemoryParameters = qemuDomainSetMemoryParameters, /* 0.8.5 */
11476
 
    .domainGetMemoryParameters = qemuDomainGetMemoryParameters, /* 0.8.5 */
11477
 
    .domainSetBlkioParameters = qemuDomainSetBlkioParameters, /* 0.9.0 */
11478
 
    .domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */
11479
 
    .domainGetInfo = qemudDomainGetInfo, /* 0.2.0 */
11480
 
    .domainGetState = qemuDomainGetState, /* 0.9.2 */
11481
 
    .domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */
11482
 
    .domainSave = qemuDomainSave, /* 0.2.0 */
11483
 
    .domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */
11484
 
    .domainRestore = qemuDomainRestore, /* 0.2.0 */
11485
 
    .domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */
11486
 
    .domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */
11487
 
    .domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */
11488
 
    .domainCoreDump = qemudDomainCoreDump, /* 0.7.0 */
11489
 
    .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */
11490
 
    .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */
11491
 
    .domainSetVcpusFlags = qemuDomainSetVcpusFlags, /* 0.8.5 */
11492
 
    .domainGetVcpusFlags = qemudDomainGetVcpusFlags, /* 0.8.5 */
11493
 
    .domainPinVcpu = qemudDomainPinVcpu, /* 0.4.4 */
11494
 
    .domainPinVcpuFlags = qemudDomainPinVcpuFlags, /* 0.9.3 */
11495
 
    .domainGetVcpuPinInfo = qemudDomainGetVcpuPinInfo, /* 0.9.3 */
11496
 
    .domainGetVcpus = qemudDomainGetVcpus, /* 0.4.4 */
11497
 
    .domainGetMaxVcpus = qemudDomainGetMaxVcpus, /* 0.4.4 */
11498
 
    .domainGetSecurityLabel = qemudDomainGetSecurityLabel, /* 0.6.1 */
11499
 
    .nodeGetSecurityModel = qemudNodeGetSecurityModel, /* 0.6.1 */
11500
 
    .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */
11501
 
    .domainXMLFromNative = qemuDomainXMLFromNative, /* 0.6.4 */
11502
 
    .domainXMLToNative = qemuDomainXMLToNative, /* 0.6.4 */
11503
 
    .listDefinedDomains = qemudListDefinedDomains, /* 0.2.0 */
11504
 
    .numOfDefinedDomains = qemudNumDefinedDomains, /* 0.2.0 */
11505
 
    .domainCreate = qemuDomainStart, /* 0.2.0 */
11506
 
    .domainCreateWithFlags = qemuDomainStartWithFlags, /* 0.8.2 */
11507
 
    .domainDefineXML = qemudDomainDefine, /* 0.2.0 */
11508
 
    .domainUndefine = qemudDomainUndefine, /* 0.2.0 */
11509
 
    .domainUndefineFlags = qemuDomainUndefineFlags, /* 0.9.4 */
11510
 
    .domainAttachDevice = qemuDomainAttachDevice, /* 0.4.1 */
11511
 
    .domainAttachDeviceFlags = qemuDomainAttachDeviceFlags, /* 0.7.7 */
11512
 
    .domainDetachDevice = qemuDomainDetachDevice, /* 0.5.0 */
11513
 
    .domainDetachDeviceFlags = qemuDomainDetachDeviceFlags, /* 0.7.7 */
11514
 
    .domainUpdateDeviceFlags = qemuDomainUpdateDeviceFlags, /* 0.8.0 */
11515
 
    .domainGetAutostart = qemudDomainGetAutostart, /* 0.2.1 */
11516
 
    .domainSetAutostart = qemudDomainSetAutostart, /* 0.2.1 */
11517
 
    .domainGetSchedulerType = qemuGetSchedulerType, /* 0.7.0 */
11518
 
    .domainGetSchedulerParameters = qemuGetSchedulerParameters, /* 0.7.0 */
11519
 
    .domainGetSchedulerParametersFlags = qemuGetSchedulerParametersFlags, /* 0.9.2 */
11520
 
    .domainSetSchedulerParameters = qemuSetSchedulerParameters, /* 0.7.0 */
11521
 
    .domainSetSchedulerParametersFlags = qemuSetSchedulerParametersFlags, /* 0.9.2 */
11522
 
    .domainMigratePerform = qemudDomainMigratePerform, /* 0.5.0 */
11523
 
    .domainBlockResize = qemuDomainBlockResize, /* 0.9.8 */
11524
 
    .domainBlockStats = qemuDomainBlockStats, /* 0.4.1 */
11525
 
    .domainBlockStatsFlags = qemuDomainBlockStatsFlags, /* 0.9.5 */
11526
 
    .domainInterfaceStats = qemudDomainInterfaceStats, /* 0.4.1 */
11527
 
    .domainMemoryStats = qemudDomainMemoryStats, /* 0.7.5 */
11528
 
    .domainBlockPeek = qemudDomainBlockPeek, /* 0.4.4 */
11529
 
    .domainMemoryPeek = qemudDomainMemoryPeek, /* 0.4.4 */
11530
 
    .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
11531
 
    .nodeGetCPUStats = nodeGetCPUStats, /* 0.9.3 */
11532
 
    .nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.3 */
11533
 
    .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.4.4 */
11534
 
    .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.4.4 */
11535
 
    .domainEventRegister = qemuDomainEventRegister, /* 0.5.0 */
11536
 
    .domainEventDeregister = qemuDomainEventDeregister, /* 0.5.0 */
11537
 
    .domainMigratePrepare2 = qemudDomainMigratePrepare2, /* 0.5.0 */
11538
 
    .domainMigrateFinish2 = qemudDomainMigrateFinish2, /* 0.5.0 */
11539
 
    .nodeDeviceDettach = qemudNodeDeviceDettach, /* 0.6.1 */
11540
 
    .nodeDeviceReAttach = qemudNodeDeviceReAttach, /* 0.6.1 */
11541
 
    .nodeDeviceReset = qemudNodeDeviceReset, /* 0.6.1 */
11542
 
    .domainMigratePrepareTunnel = qemudDomainMigratePrepareTunnel, /* 0.7.2 */
11543
 
    .isEncrypted = qemuIsEncrypted, /* 0.7.3 */
11544
 
    .isSecure = qemuIsSecure, /* 0.7.3 */
11545
 
    .domainIsActive = qemuDomainIsActive, /* 0.7.3 */
11546
 
    .domainIsPersistent = qemuDomainIsPersistent, /* 0.7.3 */
11547
 
    .domainIsUpdated = qemuDomainIsUpdated, /* 0.8.6 */
11548
 
    .cpuCompare = qemuCPUCompare, /* 0.7.5 */
11549
 
    .cpuBaseline = qemuCPUBaseline, /* 0.7.7 */
11550
 
    .domainGetJobInfo = qemuDomainGetJobInfo, /* 0.7.7 */
11551
 
    .domainAbortJob = qemuDomainAbortJob, /* 0.7.7 */
11552
 
    .domainMigrateSetMaxDowntime = qemuDomainMigrateSetMaxDowntime, /* 0.8.0 */
11553
 
    .domainMigrateSetMaxSpeed = qemuDomainMigrateSetMaxSpeed, /* 0.9.0 */
11554
 
    .domainMigrateGetMaxSpeed = qemuDomainMigrateGetMaxSpeed, /* 0.9.5 */
11555
 
    .domainEventRegisterAny = qemuDomainEventRegisterAny, /* 0.8.0 */
11556
 
    .domainEventDeregisterAny = qemuDomainEventDeregisterAny, /* 0.8.0 */
11557
 
    .domainManagedSave = qemuDomainManagedSave, /* 0.8.0 */
11558
 
    .domainHasManagedSaveImage = qemuDomainHasManagedSaveImage, /* 0.8.0 */
11559
 
    .domainManagedSaveRemove = qemuDomainManagedSaveRemove, /* 0.8.0 */
11560
 
    .domainSnapshotCreateXML = qemuDomainSnapshotCreateXML, /* 0.8.0 */
11561
 
    .domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */
11562
 
    .domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */
11563
 
    .domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */
11564
 
    .domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */
11565
 
    .domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */
11566
 
    .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */
11567
 
    .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */
11568
 
    .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */
11569
 
    .domainSnapshotCurrent = qemuDomainSnapshotCurrent, /* 0.8.0 */
11570
 
    .domainRevertToSnapshot = qemuDomainRevertToSnapshot, /* 0.8.0 */
11571
 
    .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
11572
 
    .qemuDomainMonitorCommand = qemuDomainMonitorCommand, /* 0.8.3 */
11573
 
    .qemuDomainAttach = qemuDomainAttach, /* 0.9.4 */
11574
 
    .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
11575
 
    .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
11576
 
    .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
11577
 
    .domainMigrateBegin3 = qemuDomainMigrateBegin3, /* 0.9.2 */
11578
 
    .domainMigratePrepare3 = qemuDomainMigratePrepare3, /* 0.9.2 */
11579
 
    .domainMigratePrepareTunnel3 = qemuDomainMigratePrepareTunnel3, /* 0.9.2 */
11580
 
    .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
11581
 
    .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
11582
 
    .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
11583
 
    .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
11584
 
    .domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
11585
 
    .domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
11586
 
    .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
11587
 
    .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
11588
 
    .isAlive = qemuIsAlive, /* 0.9.8 */
11589
 
    .nodeSuspendForDuration = nodeSuspendForDuration, /* 0.9.8 */
11590
 
    .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
11591
 
    .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
11592
 
};
11593
 
 
11594
 
 
11595
 
static virStateDriver qemuStateDriver = {
11596
 
    .name = "QEMU",
11597
 
    .initialize = qemudStartup,
11598
 
    .cleanup = qemudShutdown,
11599
 
    .reload = qemudReload,
11600
 
    .active = qemudActive,
11601
 
};
11602
 
 
11603
 
static void
11604
 
qemuVMDriverLock(void) {
11605
 
    qemuDriverLock(qemu_driver);
11606
 
};
11607
 
 
11608
 
 
11609
 
static void
11610
 
qemuVMDriverUnlock(void) {
11611
 
    qemuDriverUnlock(qemu_driver);
11612
 
};
11613
 
 
11614
 
 
11615
 
static int
11616
 
qemuVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
11617
 
                    virHashIterator iter, void *data)
11618
 
{
11619
 
    virHashForEach(qemu_driver->domains.objs, iter, data);
11620
 
 
11621
 
    return 0;
11622
 
}
11623
 
 
11624
 
static virNWFilterCallbackDriver qemuCallbackDriver = {
11625
 
    .name = "QEMU",
11626
 
    .vmFilterRebuild = qemuVMFilterRebuild,
11627
 
    .vmDriverLock = qemuVMDriverLock,
11628
 
    .vmDriverUnlock = qemuVMDriverUnlock,
11629
 
};
11630
 
 
11631
 
int qemuRegister(void) {
11632
 
    virRegisterDriver(&qemuDriver);
11633
 
    virRegisterStateDriver(&qemuStateDriver);
11634
 
    virNWFilterRegisterCallbackDriver(&qemuCallbackDriver);
11635
 
    return 0;
11636
 
}